Creating a java compiler plugin
Содержание:
Codiva
This online compiler is definitely on the top due to its unique features. To begin working in Codiva, we need to start a new project.
Its design is similar to common IDE interfaces. We have a project structure on the left, and the source file editor on the right. By default, the working directory is src > hello > com > example. We can easily add new java files by clicking the + sign next to the file name.
The source file immediately is added to the working tree:
To get started, let’s click the Run button on the top right side. It compiles the code as we start typing. Furthermore, Codiva shows all the errors during the compilation and displays the program execution result as we finish typing.
Additionally, it offers syntax highlighting and autocomplete to save time.
Last but not least, we can embed the Java project into any blog or website. First, we need to press the Share button and make the project public. After, Codiva gives two options for sharing:
- A public URL
- HTML code to copy and paste into our website
As a disadvantage, this tool doesn’t support compiler settings and works only for Java, C, C++ languages.
EXAMPLES
Compiling a Simple Program
The following source file, , defines a class called greetings.Hello:
package greetings; public class Hello { public static void main(String[] args) { for (int i=0; i < args.length; i++) { System.out.println("Hello " + args); } } }
The directory is the package directory both for the source file and the class file and is off the current directory. This allows us to use the default user class path. It also makes it unnecessary to specify a separate destination directory with -d.
C:\>javac greetings\Hello.java C:\>dir greetings /B Hello.class Hello.java C:\>java greetings.Hello World Universe Everyone Hello World Hello Universe Hello Everyone
Compiling Multiple Source Files
This example compiles all the source files in the package .
C:\>dir /B greetings C:\>dir greetings /B Aloha.java GutenTag.java Hello.java Hi.java C:\>javac greetings\*.java C:\>dir greetings /B Aloha.class Aloha.java GutenTag.class GutenTag.java Hello.class Hello.java Hi.class Hi.java
Specifying a User Class Path
Having changed one of the source files in the previous example, we recompile it:
C:\>cd \examples C:\>javac greetings\Hi.java
Since refers to other classes in the package, the compiler needs to find these other classes. The example above works, because our default user class path happens to be the directory containing the package directory. But suppose we want to recompile this file and not worry about which directory we’re in? Then we need to add to the user class path. We can do this by setting CLASSPATH, but here we’ll use the -classpath option.
C:\>javac -classpath \examples \examples\greetings\Hi.java
If we change again, to use a banner utility, that utility also needs to be accessible through the user class path.
C:\>javac -classpath \examples;\lib\Banners.jar ^ \examples\greetings\Hi.java
To execute a class in , we need access both to and to the classes it uses.
C:\>java -classpath \examples;\lib\Banners.jar greetings.Hi
Separating Source Files and Class Files
It often makes sense to keep source files and class files in separate directories, especially on large projects. We use -d to indicate the separate class file destination. Since the source files are not in the user class path, we use -sourcepath to help the compiler find them.
C:\>dir /B classes lib src C:\>dir src farewells C:\>dir src\farewells Base.java GoodBye.java C:\>dir lib Banners.jar C:\>dir classes C:\>javac -sourcepath src -classpath classes;lib\Banners.jar ^ src\farewells\GoodBye.java -d classes C:\>dir classes farewells C:\>dir classes\farewells Base.class GoodBye.class
Note: The compiler compiled , even though we didn’t specify it on the command line. To trace automatic compiles, use the -verbose option.
Cross-Compilation Example
The following example uses javac to compile code that will run on a 1.6 VM.
C\:>javac -source 1.6 -target 1.6 -bootclasspath C:\jdk1.6.0\lib\rt.jar ^ -extdirs "" OldCode.java
The option specifies that version 1.6 (or 6) of the Java programming language be used to compile . The option -target 1.6 option ensures that the generated class files will be compatible with 1.6 VMs. Note that in most cases, the value of the -target option is the value of the -source option; in this example, you can omit the -target option.
You must specify the -bootclasspath option to specify the correct version of the bootstrap classes (the library). If not, the compiler generates a warning:
C:\>javac -source 1.6 OldCode.java warning: bootstrap class path not set in conjunction with -source 1.6
If you do not specify the correct version of bootstrap classes, the compiler will use the old language rules (in this example, it will use version 1.6 of the Java programming language) combined with the new bootstrap classes, which can result in class files that do not work on the older platform (in this case, Java SE 6) because reference to non-existent methods can get included.
Repl.it
Repl.it has an interactive programming environment supporting many languages. Also, we can create a simple web project including HTML and JS files to practice basic web skills. Its very popular among teachers, interviewers, universities, and colleges.
First of all, we need to sign up on the platform. It is worth mentioning that this requirement doesn’t exist in any of the previously listed compilers:
One important feature is a built-in version control which allows to save the current work, work with the session later, or compare the changes with each version.
Additionally, it has a multi-functional terminal emulator, provides with the rich API and code sharing/collaboration tools, third-party library support.
COMMAND LINE ARGUMENT FILES
To shorten or simplify the javac command line, you can specify one or more files that themselves contain arguments to the command (except options). This enables you to create javac commands of any length on any operating system.
An argument file can include javac options and source filenames in any combination. The arguments within a file can be space-separated or newline-separated. If a filename contains embedded spaces, put the whole filename in double quotes, and double each backslash ().
Filenames within an argument file are relative to the current directory, not the location of the argument file. Wildcards (*) are not allowed in these lists (such as for specifying ). Use of the ‘@‘ character to recursively interpret files is not supported. The options are not supported because they are passed to the launcher, which does not support argument files.
When executing javac, pass in the path and name of each argument file with the ‘@‘ leading character. When javac encounters an argument beginning with the character `@‘, it expands the contents of that file into the argument list.
Example — Single Arg File
You could use a single argument file named «» to hold all javac arguments:
C:\>javac @argfile
This argument file could contain the contents of both files shown in the next example.
Example — Two Arg Files
You can create two argument files — one for the javac options and the other for the source filenames: (Notice the following lists have no line-continuation characters.)
Create a file named «» containing:
-d classes -g -sourcepath C:\java\pubs\ws\1.3\src\share\classes
Create a file named «» containing:
MyClass1.java MyClass2.java MyClass3.java
You would then run javac with:
C:\>javac @options @classes
Example — Arg Files with Paths
The argument files can have paths, but any filenames inside the files are relative to the current working directory (not or ):
C:\>javac @path1\options @path2\classes
Типичные ошибки компиляции и запуска Java программ
Команда javac не найдена
Если при запуске javac, т.е. при попытке компиляции Java программы вы получаете ошибку:
"javac" не является внутренней или внешней командой, исполняемой программой или пакетным файлом.
Это означает, что JDK не установлен. Либо установлен, но не настроены переменные окружения. Способы исправления очевидны:
- установить JDK
- настроить переменные окружения
Если JDK установлен, то можно обойтись без добавления переменной окружения. Для этого используйте абсолютный путь до исполнимого файла javac:
C:\Program Files\Java\jdk1.8.0_131\bin\javac.exe программа_для_компиляции.java
Ошибка Class names are only accepted if annotation processing is explicitly requested
Если попытаться скомпилировать программу следующим образом:
"C:\Program Files\Java\jdk1.8.0_131\bin\javac.exe" Welcome2
то возникнет ошибка:
error: Class names, 'Welcome', are only accepted if annotation processing is explicitly requested 1 error
Причина ошибки в том – что вы забыли указать расширение файла .java.
Ошибка записи (error while writing)
Запуск компиляции:
C:\Users\Alex>"C:\Program Files\Java\jdk1.8.0_131\bin\javac.exe" C:\Welcome.java
Компиляция заканчивается ошибкой:
C:\Welcome.java:1: error: error while writing Welcome: C:\Welcome.class (╬Єърчрэю т фюёЄєях) public class Welcome { ^ 1 error
Причина ошибки в том, что у компилятора (javac) недостаточно прав на запись в тот каталог, куда он пытается сохранить новый файл .class. Чтобы ошибка исчезла: предоставьте компилятору дополнительные права (запустите от имени администратора), либо сохраняйте в папку, на которую у текущего пользователя имеются права записи.
Ошибка «class is public, should be declared in a file named»
Запуск компиляции
"C:\Program Files\Java\jdk1.8.0_131\bin\javac.exe" C:\Welcome.java
который заканчивается примерной такой ошибкой
C:\Welcome.java:1: error: class Welcomee is public, should be declared in a file named Welcomee.java public class Welcomee { ^ 1 error
означает, что вы неправильно назвали класс в исходном коде программы. Имя класса должно совпадать с именем файла. В данном случае файл называется Welcome.java, а класс внутри программы назван Welcomee
Error: Could not find or load main class
Если попытаться запустить программу следующим образом:
java Welcome.class
то возникнет ошибка
Error: Could not find or load main class Welcome.class
Причина её в том, что не нужно было добавлять к названию файла расширение .class. Виртуальная машина автоматически добавляет расширение и в приведённом примере она ищет файл Welcome.class.class
Ошибка Error: Could not find or load main class при запуске Java программы по абсолютному пути
Эта ошибка возможно при запуске Java программы по абсолютному пути:
java C:\Welcome
Будет выведено:
Error: Could not find or load main class C:\Welcome
Ошибка возникает как в Windows, так и в Linux:
java /home/mial/Welcome Error: Could not find or load main class .home.mial.Welcome
Если в терминале вы находитесь в той же директории, что и файл, который вы запускаете, то не нужно указывать абсолютный путь. Например, нужно запускать так:
cd C:\ java Welcome
Если же вы находитесь в другой директории, то нужно использовать опцию -cp, после которой указать путь до каталога, где размещена запускаемая программа. А далее указать запускаемый файл без расширения .class:
java -cp C:\ Welcome
Как видно из скриншота, командная строка находится в папке C:\WINDOWS\system32. Файл, который нам нужно запустить, находится в папке C:\ (корень диска). Мы указываем после ключа -cp папку C:\, а затем пишем имя файла программы без расширения – Welcome.
Аналогично нужно поступать в Linux. Пример команды:
java -cp /home/mial/ Welcome
Ошибка Main method not found in class
Если при запуске вы столкнулись с ошибкой:
Error: Main method not found in class Welcome, please define the main method as: public static void main(String[] args) or a JavaFX application class must extend javafx.application.Application
Это означает, что вы не указали метод main, либо написали слово неправильно (например, Main вместо main).
Java Programs
Java Basic Programs |
---|
Java Program to Add two Numbers |
Java Program to Check Even or Odd Number |
Java Program to add two binary numbers |
Java Program to add two complex numbers |
Java Program to Multiply two Numbers |
Java Program to check Leap Year |
Java Program to check whether input character is vowel or consonant |
Java Program to calculate compound interest |
Java Program to calculate simple interest |
Java Program to find quotient and remainder |
Java Program to calculate power of a number |
Java Strings Programs |
---|
Java Program to Convert char to String and String to Char |
Java Program to find duplicate characters in a String |
Java Program to check Palindrome String using Stack, Queue, For and While loop |
Java Program to sort strings in alphabetical order |
Java Program to reverse words in a String |
Java Program to perform bubble sort on Strings |
Java program to find occurrence of a character in a String |
Java program to count vowels and consonants in a String |
Java Arrays Programs |
---|
Java Program to Calculate average of numbers using Array |
Java Program to Add the elements of an Array |
Java Program to reverse an array |
Java Program to sort an array in ascending order |
Java Program to convert char Array to String |
Java Program to Add Two Matrix Using Multi-dimensional Arrays |
Java Recursion Programs |
---|
Java Program to Reverse a number using for, while loop and recursion |
Java Program to check Palindrome string using Recursion |
Java Program to Reverse a String using Recursion |
Java Program to find Factorial of a number using Recursion |
Java Programs on Numbers |
---|
Java Program to display first 100 prime numbers |
Java Program to display prime numbers between 1 and 100 or 1 and n |
Java program to break integer into digits |
Java Program to check Prime Number |
Java Program to check if a given number is perfect square |
Java Program to find square root of a number without sqrt method |
Java Program to print Armstrong numbers between a given range |
Java Program to Find Sum of Natural Numbers |
Java Program to check if a number is Positive or Negative |
Java Program to generate Random Number |
Java Program to check Armstrong number |
Java Program to find GCD of two numbers |
Java Program to find Largest of three numbers |
Java Program to swap two numbers using bitwise operator |
Java Program to find smallest of three numbers using ternary operator |
Java Program to find largest of three numbers using ternary operator |
Java Program to display alternate prime numbers |
Java Program to display even numbers from 1 to n or 1 to 100 |
Java Program to display odd numbers from 1 to n or 1 to 100 |
Java Program to Find average of 3 numbers |
Java Program to Find HCF and LCM of Two Numbers |
Java Input/Output Programs |
---|
Java Program to read number from Standard Input |
Java Program to Get IP Address |
Java Program to get Input From User |
Java Programs on Geometrical Calculations |
---|
Java Program to Calculate Area of Rectangle |
Java Program to Calculate Area of Square |
Java Program to Calculate the area of Triangle |
Java Program to Calculate Area and Circumference of Circle |
Java Sorting/Searching Programs |
---|
Java Program for bubble Sort Ascending or Descending Order |
Java Program for Linear Search |
Java Program for Binary Search |
Java Program for Selection Sorting |
Java Conversion Programs |
---|
Java Octal to Decimal conversion |
Java Program to Convert Decimal to Octal |
Java hexadecimal to decimal conversion |
Java Program to convert decimal to hexadecimal |
Java binary to octal conversion |
Java String to boolean |
Java program to convert boolean to String |
Java int to char conversion |
Java char to int conversion |
Java char to string conversion |
Java long to int conversion |
Java int to long conversion |
Java Program to Convert Decimal to Binary |
Java Program to convert binary to Decimal |
Java Program to find ASCII value of a character |
Java program for String to int conversion |
Java program to convert int to String |
Java program for string to double conversion |
Java program to convert double to String |
Java program to convert String to long |
Java program to convert long to String |
Other Java Programs |
---|
Java Program to print Floyd’s triangle |
Java program to print Pascal triangle |
Java Program to display Fibonacci series using loops |
Java Program to find Factorial using loops |
Java Program to make a calculator using switch case |
Java Program to Calculate grades of Student |
Java Program to perform Arithmetic Operation using Method Overloading |
Java Program to find Area of Geometric figures using method overloading |
SEARCHING FOR TYPES
When compiling a source file, the compiler often needs information about a type whose definition did not appear in the source files given on the command line. The compiler needs type information for every class or interface used, extended, or implemented in the source file. This includes classes and interfaces not explicitly mentioned in the source file but which provide information through inheritance.
For example, when you subclass java.applet.Applet, you are also using Applet’s ancestor classes: java.awt.Panel, java.awt.Container, java.awt.Component, and java.lang.Object.
When the compiler needs type information, it looks for a source file or class file which defines the type. The compiler searches for class files first in the bootstrap and extension classes, then in the user class path (which by default is the current directory). The user class path is defined by setting the CLASSPATH environment variable or by using the -classpath command line option. (For details, see Setting the Class Path).
If you set the option, the compiler searches the indicated path for source files; otherwise the compiler searches the user class path for both class files and source files.
You can specify different bootstrap or extension classes with the -bootclasspath and -extdirs options; see below.
A successful type search may produce a class file, a source file, or both. If both are found, you can use the option to instruct the compiler which to use. If newer is given, the compiler will use the newer of the two files. If source is given, it will use the source file. The default is newer.
If a type search finds a source file for a required type, either by itself, or as a result of the setting for -Xprefer, the compiler will read the source file to get the information it needs. In addition, it will by default compile the source file as well. You can use the option to specify the behavior. If none is given, no class files will be generated for the source file. If class is given, class files will be generated for the source file.
The compiler may not discover the need for some type information until after annotation processing is complete. If the type information is found in a source file and no -implicit option is given, the compiler will give a warning that the file is being compiled without being subject to annotation processing. To disable the warning, either specify the file on the command line (so that it will be subject to annotation processing) or use the -implicit option to specify whether or not class files should be generated for such source files.
Extract AST Data
We can get an AST generated by the Java compiler through the TaskEvent.getCompilationUnit(). Its details can be examined through the TreeVisitor interface.
Note that only a Tree element, for which the accept() method is called, dispatches events to the given visitor.
For example, when we execute ClassTree.accept(visitor), only visitClass() is triggered; we can’t expect that, say, visitMethod() is also activated for every method in the given class.
We can use TreeScanner to overcome the problem:
In this example, it’s necessary to call super.visitXxx(node, value) to recursively process the current node’s children.
Testing the Plugin
We need to be able to test our plugin. It involves the following:
- compile the test source
- run the compiled binaries and ensure that they behave as expected
For this, we need to introduce a few auxiliary classes.
SimpleSourceFile exposes the given source file’s text to the Javac:
SimpleClassFile holds the compilation result as a byte array:
SimpleFileManager ensures the compiler uses our bytecode holder:
Finally, all of that is bound to the in-memory compilation:
After that, we need only to run the binaries:
A test might look like this:
Here we’re compiling a Test class with a service() method that has a parameter annotated with @Positive. Then, we’re running the Test class by setting a double value of -1 for the method parameter.
As a result of running the compiler with our plugin, the test will throw an IllegalArgumentException for the negative parameter.
JDoodle
JDoodle is an easy and quick way to compile and run source code in many programming languages including Java. Even more, JDoodle provides a terminal to work with MySql and MongoDB, peer programming tools, an API to execute code remotely, and an embedding feature for a blog or website.
Its UI has a user-friendly editor and input fields including:
- Command line arguments
- Interactive mode
- JDK versions 8 to 10 are available
- Attaching external libraries directly from the Maven repository. All we need is to specify the group, artifact ids and the version of the library.
Additionally, we can open, save, and download the source file.
Furthermore, the tool displays the compilation and execution along with CPU time in seconds. The memory usage is shown in kilobytes.
Important to note, that JDoodle allows having only one file. So it isn’t the best choice for multiple package projects or learning programming concepts like encapsulation and inheritance.
DESCRIPTION
The javac tool reads class and interface definitions, written in the Java programming language, and compiles them into bytecode class files. It can also process annotations in Java source files and classes.
There are two ways to pass source code file names to javac:
- For a small number of source files, simply list the file names on the command line.
- For a large number of source files, list the file names in a file, separated by blanks or line breaks. Then use the list file name on the javac command line, preceded by an @ character.
Source code file names must have suffixes, class file names must have suffixes, and both source and class files must have root names that identify the class. For example, a class called would be written in a source file called and compiled into a bytecode class file called .
Inner class definitions produce additional class files. These class files have names combining the inner and outer class names, such as .
You should arrange source files in a directory tree that reflects their package tree. For example, if you keep all your source files in C:\workspace, the source code for should be in C:\workspace\com\mysoft\mypack\MyClass.java.
By default, the compiler puts each class file in the same directory as its source file. You can specify a separate destination directory with -d (see , below).
PROGRAMMATIC INTERFACE
javac supports the new Java Compiler API defined by the classes and interfaces in the package.
Example
To perform a compilation using arguments as you would give on the command line, you can use the following:
JavaCompiler javac = ToolProvider.getSystemJavaCompiler(); int rc = javac.run(null, null, null, args);
This will write any diagnostics to the standard output stream, and return the exit code that javac would give when invoked from the command line.
You can use other methods on the interface to handle diagnostics, control where files are read from and written to, and so on.
Old Interface
Note: This API is retained for backwards compatibility only; all new code should use the Java Compiler API, described above.
The class provides two static methods to invoke the compiler from a program:
public static int compile(String[] args); public static int compile(String[] args, PrintWriter out);
The parameter represents any of the command line arguments that would normally be passed to the javac program and are outlined in the above section.
The parameter indicates where the compiler’s diagnostic output is directed.
The return value is equivalent to the exit value from javac.
Note that all other classes and methods found in a package whose name starts with (informally known as sub-packages of ) are strictly internal and subject to change at any time.
Модуляризация проекта
Пока что ничего нового, но давайте начнем модуляризацию нашего проекта. Для этого создадим модульный дескриптор (всегда называется и размещается в корневой директории ):
Команда для компиляции модуля в Java 9 отличается от того, что мы видели раньше. Использование старой команды с добавлением модуля к списку файлов приводит к ошибке:
Чтобы понять, почему наш код не компилируется, необходимо понять, что такое безымянные модули.
Любой класс, который загружается не из именованного модуля, автоматически выполняет часть безымянного модуля. В примере выше перед созданием модульного дескриптора наш код не был частью какого-либо модуля, следовательно, он был ассоциирован с безымянным модулем. Безымянный модуль — это механизм совместимости. Проще говоря, это позволяет разработчику использовать в приложениях Java 9 код, который не был модуляризирован. По этой причине код, относящийся к безымянному модулю, имеет правила сродни Java 8 и ранее: он может видеть все пакеты, экспортируемые из других модулей, и все пакеты безымянного модуля.
Когда модульный дескриптор добавляется к модулю, его код больше не является частью безымянного модуля и не может видеть код других модулей, пока не импортирует их. В случае выше модуль не требует никаких модулей, поэтому модуль библиотеки Greeting для него не виден. Он может видеть только пакеты модуля .
Модули в Java 9, за исключением неуловимого безымянного модуля описанного выше, должны объявлять, какие другие модули им необходимы. В случае с модулем единственным требованием является библиотека Greeting. Но, как вы могли догадаться, эта библиотека (как и другие библиотеки, не поддерживающие Java 9) не является модулем Java 9. Как же нам включить её в проект?
В таком случае вам нужно знать имя jar-файла. Если у вас есть зависимость от библиотеки, которая не была конвертирована в модуль Java 9, вам надо знать, какой jar-файл вызывается для этой библиотеки, потому что Java 9 переведёт имя файла в валидный модуль.
Это называется автоматический модуль.
Так же, как и безымянные модули, автоматические модули могут читать из других модулей, и все их пакеты являются экспортируемыми. Но, в отличие от безымянных модулей, на автоматические можно ссылаться из явных модулей.
Чтобы узнать имя автоматического модуля, компилятор конвертирует неальфанумерические, поэтому что-то вроде превратится в имя модуля .
У нас есть библиотека с именем . Давайте переименуем jar-файл в :
Это более стандартное имя файла, и теперь мы можем сказать Java включить автоматический модуль с приемлемым именем . И можем вызывать его из модуля:
Модули не добавлены в . Как и обычные jar-файлы, они используют новый флаг . Теперь мы можем скомпилировать наши модули следующей командой:
Чтобы запустить командой мы можем использовать новый флаг , который принимает либо имя модуля, либо шаблон :
И мы получим вывод .
Для создания и использования в качестве исполняемого jar-файла выполните следующие команды:
Следующим шагом будет модуляризация библиотек, которые используются нашим приложением.
Conclusion
In this tutorial, we explored the various IDEs/compilers and online compilers that we can use for Java programming.
We walked through the detailed information about IDE – features, pros, and cons, where it was developed, it’s pricing, how it looks, languages and platform supported, etc. Now we know how important the IDE is for developers and how it can make the development easier.
IDE gives the developer a platform to polish their coding skills with code completion, code suggestion, and error highlighting features. It increases efficiency with faster coding and minimal efforts. It allows collaboration among developers to work together on a single platform. Good project management feature.
IntelliJ IDEA, Eclipse, and NetBeans are the top three IDEs that are used extensively for Java programming today. Similarly, we can use the top 5 online compilers that we discussed for not so advanced Java programming.
Small Scale and Learning Universities: BlueJ, JGrasp, Greenfoot, DrJava are some of the Java IDE that is best for this small scale due to its cost and community support.
Medium and Large Scale Industries: Eclipse, IntelliJ Idea, NetBeans, JDeveloper are good for large scale due to their advanced features and performance.
In our subsequent tutorials, we will learn Eclipse Java IDE in detail as this is the most widely used and popular IDE among Java programmers.
=>> Contact us to suggest a listing here.
Setup
First, we need to add JDK’s tools.jar as a dependency for our project:
Every compiler extension is a class which implements com.sun.source.util.Plugin interface. Let’s create it in our example:
Let’s create it in our example:
For now, we’re just printing “Hello” to ensure that our code is successfully picked up and included in the compilation.
Our end goal will be to create a plugin that adds runtime checks for every numeric argument marked with a given annotation, and throw an exception if the argument doesn’t match a condition.
There’s one more necessary step to make the extension discoverable by Javac: it should be exposed through the ServiceLoader framework.
To achieve this, we need to create a file named com.sun.source.util.Plugin with content which is our plugin’s fully qualified class name (com.baeldung.javac.SampleJavacPlugin) and place it in the META-INF/services directory.
After that, we can call Javac with the -Xplugin:MyPlugin switch:
Note that we must always use a String returned from the plugin’s getName() method as a -Xplugin option value.
Модуляризация библиотек
Для модуляризации библиотеки нельзя сделать ничего лучше, чем использовать — инструмент для статистического анализа, который является частью Java SE.
Например, команда, которая позволяет увидеть зависимости нашей небольшой библиотеки, выглядит так:
А вот результат её выполнения:
Как и ожидалось, библиотека зависит только от модуля.
Мы знаем, что зависит от модуля . Давайте попробуем использовать , чтобы он подтвердил нам это. Для этого нужно удалить файлы и и затем запустить :
Результат:
Команда:
Результат:
Хорошо, но можно лучше. Мы можем попросить автоматически сгенерировать модульный дескриптор для набора jar-файлов. Просто укажите ему, куда сохранять сгенерированные файлы (например, в папку ), и где находятся jar-файлы:
Команда создаст два файла: и со следующим содержимым:
Теперь мы можем добавить сгенерированный дескриптор для нашей библиотеки в её исходный код, переупаковать её, и у нас получится полностью модульное приложение:
Теперь у нас есть полностью модуляризированные библиотека и приложение. После удаления сгенерированных и бинарных файлов, структура нашего приложения выглядит следующим образом:
Обратите внимание, что для получения хороших данных от вы должны предоставить местоположение всех jar-файлов, которые используются в приложении, чтобы он мог составить полный граф модуля. Наиболее простым способом получить список всех jar-файлов, которые используются в библиотеке, является использование скрипта Gradle
Он выведет пути локальных jar-файлов для всех зависимостей библиотек, которые вы добавите в секцию зависимостей, и скачает их, если необходимо:
Наиболее простым способом получить список всех jar-файлов, которые используются в библиотеке, является использование скрипта Gradle. Он выведет пути локальных jar-файлов для всех зависимостей библиотек, которые вы добавите в секцию зависимостей, и скачает их, если необходимо:
Если у вас нет Gradle, вы можете использовать SdkMAN! для его установки:
Для получения списка зависимостей используйте следующую команду:
Полученную информацию передайте для анализа и автоматической генерации метаданных.
Это файл, который выводит для :
Plugin Lifecycle
A plugin is called by the compiler only once, through the init() method.
To be notified of subsequent events, we have to register a callback. These arrive before and after every processing stage per source file:
- PARSE – builds an Abstract Syntax Tree (AST)
- ENTER – source code imports are resolved
- ANALYZE – parser output (an AST) is analyzed for errors
- GENERATE – generating binaries for the target source file
There are two more event kinds – ANNOTATION_PROCESSING and ANNOTATION_PROCESSING_ROUND but we’re not interested in them here.
For example, when we want to enhance compilation by adding some checks based on source code info, it’s reasonable to do that at the PARSE finished event handler: