Dans JDK, il existe un ensemble d'API de compilation connexe qui peut lancer le processus de compilation dans Java, analyser les fichiers source Java et obtenir son arborescence de syntaxe. Cet ensemble complet d'API est inclus dans les outils.jar de JDK (peut être trouvé dans / bibliothèque / java / javavirtualmachines / jdk_version / contenu / home / lib sous OSX), mais ce n'est pas un API public dans les versions Oracle et OpenJDK, il n'y a donc pas de documentation officielle pour expliquer cet ensemble d'API. Cependant, de nombreux projets ont utilisé cette API pour faire beaucoup de choses. Par exemple, le célèbre Lombok a utilisé cette API pour modifier l'arborescence de syntaxe dans le code source pendant l'étape de traitement de l'annotation. Le résultat final équivaut à l'insertion du nouveau code directement dans le fichier source!
Étant donné que cet ensemble d'API manque actuellement de documents pertinents, il est difficile à utiliser. Par exemple, analysez toutes les variables du code source et imprimez-les:
classe publique javaparser {private static final String path = "user.java"; JavacfileManager du soldat FileManager; Javactool privé Javactool; public javaparser () {context context = new context (); FileManager = New JavacFileManager (Context, True, Charset.defaultCharset ()); javactool = new Javactool (); } public void parsejavafiles () {iTable <! -? étend javafileObject -> files = fileManager.getJavaFileObjects (path); Javacompiler.compilationtask compilationTask = javactool.gettask (null, filemanager, null, null, null, fichiers); Javactask javactask = (javactask) compilationTask; Essayez {itéable <! -? étend la compilation UnitTree -> result = javactask.parse (); for (compilationUniTtree arbre: result) {arbre.accept (new SourceVisitor (), null); }} catch (ioException e) {e.printStackTrace (); }} classe statique SourceVisitor étend TreesCanner <void, void = ""> {private String currentPackageName = null; @Override public void VisitCompilationUnit (Node de compilation UnitTree, void éviter) {return super.VisitCompilationUnit (nœud, éviter); } @Override public void VisitVariable (nœud variaBletree, void éviter) {formatPtrln ("Nom de la variable:% S, type:% s, kind:% s, package:% s", node.getName (), node.getType (), Node.getkind (), actuelpackagename); retourner null; }} public static void formatPtrln (format de chaîne, objet ... args) {System.out.println (string.format (format, args)); } public static void main (String [] args) {new Javaparser (). Parsejavafiles (); }} </ void,>Le code de l'utilisateur.java est le suivant:
Package com.ragnarok.javaparser; import com.sun.istack.internal.nullable; import java.lang.Override; classe publique User {@Nullable private String foo = "123123"; privé foo a; public void userMethod () {} classe statique foo {private String Foostring = "123123"; public void foomeThod () {}}}Le résultat de l'exécution du javaparser ci-dessus est le suivant:
Variable: FOO, annotaion: nullablevariable Name: foo, type: String, kind: variable, pack
Ici, nous analysons d'abord le fichier source via javacompiler.compilationTask, puis utilisons la source personnalisée (héritée de TreesCanner) pour accéder à la structure du code source. Dans la classe SourceVisitor, nous surchargeons VisitVariable pour analyser une unité de compilation (fichier de code source unique) et accéder à toutes les variables. On peut voir ici que nous ne pouvons pas obtenir le nom entièrement qualifié de ce type de variable (y compris le nom du package) et ne peut obtenir que le nom simple correspondant. Par conséquent, la détermination du type nécessite une implémentation externe pour la déterminer par elle-même. Par exemple, vous pouvez enregistrer le nom du package où se trouve la classe, rechercher récursivement l'ensemble du répertoire de code source pour suivre le nom entièrement qualifié de toutes les classes et trouver si l'importation contient le type correspondant, etc.
En plus de la méthode VisitVariable, TreesCanner contient également un grand nombre d'autres méthodes VisitXyz. Par exemple, vous pouvez parcourir toutes les importations, les définitions de méthode, l'annotation, etc. Pour plus spécifique, vous pouvez afficher le code source à ce sujet dans OpenJDK.
Ici, nous prendrons un autre exemple, surcharger la méthode VisitClass pour accéder à toutes les classes intérieures et à la classe elle-même:
@OverRidePublic void VisitClass (nœud classtree, void éviter) {formatPtrln ("Nom de classe:% s", node.getsimpLename ()); pour (arborescence: node.getMembers ()) {if (instance de membre Of VariaBleTree) {VariaBleTree Variable = (VariaBleTree) membre; Liste <! -? étend annotationTree -> annotations = variable.getModificaires (). getAnnotations (); if (annotations.size ()> 0) {formatPtrln ("variable:% s, annotaion:% s", variable.getName (), annotations.get (0) .getAntoTationType ()); } else {formatPtrln ("variable:% s", variable.getName ()); }}} return super.VisitClass (nœud, éviter); }Ici, nous imprimons simplement le nom de classe et le nom de la variable, le type et le type d'annotation. Exécutez le code ci-dessus, et le résultat est le suivant:
Nom de la classe: UServariable: Foo, Annotaion: NullableVariable: Nom de la classe: Foovariable: Foostring
On peut voir que nous avons imprimé le nom de classe et les variables de la classe. Dans la méthode VisitClass, nous pouvons obtenir tous les membres de la classe via la méthode GetMembers, y compris les variables, les méthodes, l'annotation, etc., qui correspondent à différents types. Par exemple, les variables correspondent au type de variable et la méthode correspond au type de méthode.
En général, bien que l'utilisation ne soit pas particulièrement compliquée en fait, elle a provoqué de grands obstacles en raison du manque de documentation. Et ce que nous introduisons n'est qu'une petite partie de cette API. Je continuerai à étudier les fonctions connexes de cette API à l'avenir.
Ce qui précède est une compilation des données de l'analyse de JDK pour analyser le code source Java. Nous continuerons d'ajouter des informations pertinentes à l'avenir. Merci pour votre soutien à ce site!