Il y a quelques problèmes ici. Vous pouvez soit être intéressé par en connaissant le type Java du récepteur d'invocation de méthode ou simplement en sachant que la classe sur la méthode est invoquée. Les informations Java sont plus informatives car elles vous donnent également des types génériques, par ex. List<String>
tandis que les éléments ne vous fournissaient que la classe, par ex. List<E>
.
Obtenir l'élément
Pour obtenir l'élément de la classe la méthode est invoquée, vous pouvez faire les éléments suivants:
MethodInvocationTree node = ...;
Element method =
TreeInfo.symbol((JCTree)node.getMethodSelect());
TypeElement invokedClass = (TypeElement)method.getEnclosingElement();
cas d'angle:
1. invokedClass peut être une super-classe du type de récepteur. Donc, en cours d'exécution l'extrait sur new ArrayList<String>.equals(null)
retournerait AbstractList
plutôt que ArrayList
, puisque equals() est mis en œuvre dans AbstractList
pas ArrayList
.
2. Lors de la gestion des appels de réseau, par ex. new int[].clone()
, vous obtiendriez obtenir TypeElement
de la classe Array
.
Obtenir le type réel
Pour obtenir le type, il n'y a aucun moyen direct pour déterminer ce que le type de récepteur est . Il y a une certaine complexité dans la gestion des invocations de méthodes dans des classes internes où le récepteur n'est pas donné explicitement (par exemple, contrairement à OuterClass.this.toString()
). Voici un exemple d'implémentation:
MethodInvocationTree node = ...;
TypeMirror receiver;
if (methodSel.getKind() == Tree.Kind.MEMBER_SELECT) {
ExpressionTree receiver = ((MemberSelectTree)methodSel).getExpression();
receiverType = ((JCTree)receiver).type;
} else if (methodSel.getKind() == Tree.Kind.IDENTIFIER) {
// need to resolve implicit this, which is described in
// JLS3 15.12.1 and 15.9.2
// A bit too much work that I don't want to work on now
// Look at source code of
// Attr.visitApply(JCMethodInvocation)
// resolveImplicitThis(DiagnosticPosition, Env, Type)
} else
throw new AssertionError("Unexpected type: " + methodSel.getKind());
Note:
Le type receiver
doit être TypeMirror
pas DeclaredType
malheureusement. Lors de l'appel new int[5].clone()
, receiver
serait un ArrayType
de int[]
, ce qui est plus informatif que la précédente méthode .
Obtenir à exécuter
Les deux méthodes précédentes exigent le compilateur pour résoudre les informations de type pour les classes. Dans les circonstances habituelles, le compilateur résout uniquement les types pour les déclarations de méthode mais pas les corps. Par conséquent, les méthodes décrites précédemment retourneront null
à la place.
Pour avoir le compilateur résoudre les informations de type, vous pouvez faire l'une des façons suivantes:
1. Utilisez la classe AbstractTypeProcessor
qui vient de s'ajouter au dépôt du compilateur pour JDK 7. Vérifiez les travaux sur JSR 308 et leur compilateur. Alors que le travail est principalement sur les types annotés, il pourrait être utile pour. Le compilateur vous permet d'utiliser la classe fournie d'une manière compatible avec Java arrière 5.
Cette approche vous permet d'écrire des processeurs qui s'invoquaient juste comme vos processeurs actuels.
2. Utilisez plutôt JavacTask
et appelez JavacTask.analyze()
. Regardez la méthode principale de this javac test pour voir comment pour invoquer votre visiteur sur les classes. Cette approche fait de votre processeur un outil d'analyse plutôt qu'un plug-in pour le compilateur, car vous devez l'appeler directement plutôt que d'avoir un processus normal.
Merci pour la réponse. Toutefois, la ligne: Méthode d'élément = TreeInfo.symbol ((JCTree) node.getMethodSelect()); renvoie null pour moi. \t TypeMiroir m = trees.getTypeMirror (chemin); renvoie également la valeur null, de même que \t TypeElement e = (TypeElement) trees.getElement (chemin); Est-ce que je fais une erreur de débutant et que j'oublie d'initialiser quelque chose, ou d'appeler/de passer outre la mauvaise méthode, ou de sous-classer quelque chose de mal? Merci encore pour votre aide ... – runT1ME
Je viens de mettre à jour l'entrée pour expliquer pourquoi les méthodes renvoient null et comment adresser cela – notnoop
FYI, AbstractTypeProcessor n'est plus disponible dans les versions JDK 7, puisque le support pour JSR 308 a été abandonné. –