En JDK, hay un conjunto de API de compilación relacionadas que pueden iniciar el proceso de compilación en Java, analizar archivos fuente de Java y obtener su árbol de sintaxis. Este conjunto completo de API se incluye en las herramientas. JAR OF JDK (se puede encontrar en/biblioteca/java/javavirtualmachines/jdk_version/contenido/home/libs bajo OSX), pero esta no es una API pública en Oracle y OpenJDK, por lo que no existe una documentación oficial para explicar este conjunto de API. Sin embargo, muchos proyectos han utilizado esta API para hacer muchas cosas. Por ejemplo, el famoso Lombok usó esta API para modificar el árbol de sintaxis en el código fuente durante la etapa de procesamiento de anotaciones. ¡El resultado final es equivalente a insertar un nuevo código directamente en el archivo fuente!
Dado que este conjunto de API actualmente carece de documentos relevantes, es difícil de usar. Por ejemplo, analice todas las variables en el código fuente e imprima:
clase pública javaparser {private static final string ruta = "user.java"; Javacfilemanager privado Filemanager; Javactool privado Javactool; public javaparser () {context context = new context (); Filemanager = new JavacFilemanager (context, true, charset.defaultcharset ()); javactool = new Javactool (); } public void parseJavafiles () {ITerable <!-? extiende javafileObject-> archivos = filemanager.getJavafileObjects (ruta); Javacompiler.compilationTask CompilationTask = javactool.getTask (Null, Filemanager, NULL, NULL, NULL, archivos); Javactask javactask = (Javactask) CompilationTask; Prueba {iterable <!-? extiende compilationUnittree-> resultado = javactask.parse (); for (compilationUnittree tree: result) {tree.accept (new SourceVisitor (), nulo); }} catch (ioException e) {E.PrintStackTrace (); }} La clase estática SourceVisitor extiende TreesCanner <void, void = ""> {String private CurrentPackageName = null; @Override public void visitCompilationUnit (compilationUnittree nodo, nulo evit) {return super.visitCompilationUnit (nodo, ev Eve); } @Override public void visitVariable (nodo VariAbletree, void evit) {formatPtrln ("Nombre variable: %s, type: %s, kind: %s, paquete: %s", node.getName (), node.gettype (), node.getkind (), currentPackageName); regresar nulo; }} public static void formatPtrln (formato de cadena, objeto ... args) {system.out.println (string.format (format, args)); } public static void main (string [] args) {new javaparser (). parseJavafiles (); }} </void,>El código de usuario.java es el siguiente:
paquete com.ragnarok.javaparser; import com.sun.istack.internal.nullable; import java.lang.override; Usuario de clase pública { @@nullable private String foo = "123123"; privado foo a; public void usermethod () {} clase estática foo {private string fooString = "123123"; public void foomethod () {}}}El resultado de ejecutar el Javaparser anterior es el siguiente:
Variable: Foo, Annotaion: NullableVariable Nombre: Foo, Tipo: Cadena, Kind: Variable, Paquete: com.ragnarok.javaparserver Nombre de variable: A, Tipo: Foo, Kind: Variable, Paquete: Com.Ragnarok.Javaparserer
Aquí primero analizamos el archivo de origen a través de Javacompiler.comPilationTask, y luego usamos el SourceVisitor personalizado (heredado de TreesCanner) para acceder a la estructura del código fuente. En la clase SourceVisitor, sobrecargamos VisitVariables para analizar una unidad de compilación (archivo de código fuente único) y acceder a todas las variables. Se puede ver aquí que no podemos obtener el nombre completamente calificado de este tipo de variable (incluido el nombre del paquete), y solo podemos obtener el nombre simple correspondiente. Por lo tanto, la determinación del tipo requiere la implementación externa para determinarla por sí misma. Por ejemplo, puede registrar el nombre del paquete donde se encuentra la clase, buscar recursivamente todo el directorio de código fuente para rastrear el nombre totalmente calificado de todas las clases y encontrar si la importación contiene el tipo correspondiente, etc.
Además del método VisitVariable, Treescanner también contiene una gran cantidad de otros métodos de visitxyz. Por ejemplo, puede atravesar todas las importaciones, definiciones de métodos, anotación, etc. Para más específico, puede ver el código fuente sobre esto en OpenJDK.
Aquí tomaremos otro ejemplo, sobrecargando el método VisitClass para acceder a todas las clases internas y la clase en sí:
@OverridePublic Void visitClass (classtree node, void evit) {formatptrln ("nombre de clase: %s", node.getSimplename ()); for (miembro del árbol: node.getMembers ()) {if (miembro instanceOf variaBletree) {variaBletree variable = (variAbletree) miembro; Lista <!-? extiende 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 (nodo, evita); }Aquí simplemente imprimimos el nombre de clase y el nombre de la variable, el tipo y el tipo de anotación. Ejecutar el código anterior, y el resultado es el siguiente:
Nombre de la clase: Uservariable: Foo, Annotaion: NullableVariable: Clase Nombre: Foovariable: Foostring
Se puede ver que hemos imprimido el nombre de la clase y las variables en la clase. En el método VisitClass, podemos obtener a todos los miembros de la clase a través del método GetMembers, incluidas variables, métodos, anotación, etc., que corresponden a diferentes tipos. Por ejemplo, las variables corresponden al tipo de variabletree, y el método corresponde al tipo de método.
En general, aunque el uso no es particularmente complicado de hecho, ha causado grandes obstáculos que usar debido a la falta de documentación. Y lo que estamos presentando es solo una pequeña parte de esta API. Continuaré estudiando las funciones relacionadas de esta API en el futuro.
Lo anterior es una compilación de los datos del analizador de JDK para analizar el código fuente de Java. Continuaremos agregando información relevante en el futuro. ¡Gracias por su apoyo para este sitio!