In the JDK, a set of related compilation APIs can be initiated in Java to initiate the compilation process, parse the Java source file, and then obtain its syntax tree, which can be/library/java/javavirtualmachines/in the JDK's Tools.jar (OS X) Found in Jdk_version/contents/home/lib), but this is not a public API in Oracle and OPENJDK releases, so there is no official formal documentation for this set of APIs. However, there are a number of projects that use this API to do a lot of things, such as the well-known Lombok use this API in the annotation processing phase of the source code to modify the syntax tree, the end result is equivalent to directly in the source file inserted new code!
Because this API is currently missing documentation, it is difficult to use, for example, to parse all the variables in the source code and print it out:
public class Javaparser {private static final String path = "User.java";
Private Javacfilemanager FileManager;
Private Javactool Javactool;
Public Javaparser () {The context context = the new context ();
FileManager = new Javacfilemanager (context, True, Charset.defaultcharset ());
Javactool = new Javactool (); public void Parsejavafiles () {iterable<!--? extends javafileobject--> files = filemanager.getjavafileobjects
(path);
Javacompiler.compilationtask compilationtask = Javactool.gettask (null, filemanager, NULL, NULL, NULL, files);
Javactask Javactask = (javactask) compilationtask;
try {iterable<!--? extends compilationunittree--> result = Javactask.parse ();
for (Compilationunittree Tree:result) {tree.accept (New sourcevisitor (), NULL);
} catch (IOException e) {e.printstacktrace (); } static class Sourcevisitor extends Treescanner<void, void= "" > {private String currentpackagename = null
; @Override PubliC Void Visitcompilationunit (compilationunittree node, Void avoid) {return Super.visitcompilationunit (node, avoid); @Override public Void visitvariable (variabletree node, Void avoid) {formatptrln ("Variable name:%s, type:%s",
Kind:%s, Package:%s, Node.getname (), Node.gettype (), Node.getkind (), currentpackagename);
return null;
} public static void Formatptrln (String format, Object ... args) {System.out.println (String.Format (format, args));
public static void Main (string[] args) {new Javaparser (). Parsejavafiles ();
}}</void,>
Where the User.java code is as follows:
Package com.ragnarok.javaparser;
Import com.sun.istack.internal.Nullable;
Import Java.lang.Override;
public class User {
@Nullable
private String foo = "123123";
Private Foo A;
public void Usermethod () {}
static class Foo {
private String foostring = "123123";
public void Foomethod () {}}}
The results of the above Javaparser are as follows:
Variable:foo, annotaion:nullable
variable name:foo, type:string, kind:variable, Package:com.ragnarok.javaparse R
Variable name:a, Type:foo, kind:variable, Package:com.ragnarok.javaparser
Here we first parse the source file through Javacompiler.compilationtask, then use the custom Sourcevisitor (inherited from Treescanner) to access the structure of the source code, in the Sourcevisitor class, through the overload visit Variable to parse a compilation unit (a single source code file). To access all of the variables here, we can see that we have no way to get the fully qualified name of the variable type (including the package name), can only get the corresponding simple name, therefore, the type of determination needs to be determined by the external implementation, For example, you can track the fully qualified name of all classes by recursively searching the entire source code directory by recording the package name in which the class resides, looking for whether the import contains the corresponding type, and so on.
In addition to the Visitvariable method in Treescanner, there are a number of other visitxyz methods, for example, you can traverse all import, method definition, annotation, and more specifically, see the source code for this in OPENJDK.
Here's another example, overload the Visitclass method, access all the inner classes and the class itself:
@Override public
Void Visitclass (classtree node, Void avoid) {
Formatptrln ("Class name:%s", Node.getsimplename ());
for [Tree Member:node.getMembers ()] {
if (member instanceof Variabletree) {
variabletree variable = (variabletre e) member;
list<!--? Extends annotationtree--> annotations = Variable.getmodifiers (). Getannotations ();
if (annotations.size () > 0) {
formatptrln ("variable:%s, Annotaion:%s", Variable.getname (), Annotations.get (0). Getannotationtype ());
} else {
formatptrln ("Variable:%s", Variable.getname ());
}}} Return Super.visitclass (node, avoid);
This simply prints the class name and the name of the variable, type, annotation type, executes the code above, and the results are as follows:
Class Name:user
Variable:foo, annotaion:nullable
variable:a
class Name:foo
variable:foostring
You can see that we print out the class name and the variables in the class. In the Visitclass method, we can get all the members in the class by GetMembers method, including variables, methods, annotation, etc., corresponding to different types, for example, the variable corresponds to the Variabletree type, method is the corresponding Methodtree type.
Generally speaking, although the actual use is not particularly complex, but because of the lack of documentation, the use of a large number of obstacles, and currently introduced only a small part of the API, follow-up I will continue to study the API related functions.
The above is the JDK parser to parse Java source code data collation, follow-up continue to supplement the relevant information, thank you for your support of this site!