Question

Je suis en train d'écrire des outils pour notre système de construction pour faire respecter certaines conventions d'appel strictes sur les méthodes appartenant à des classes contenant certaines annotations.

J'utilise l'API arbre compilateur ...

Ce que je me demande est en traversant le « arbre », comment pouvez-vous dire le type de classe / interface pour un MethodInvocation.

Je suis avec le sous-classement TreePathScanner:

@Override
public Object visitMethodInvocation(MethodInvocationTree node, Trees trees) {

}

J'espère Theres une façon de dire le type de la classe (ou interface) que vous essayez d'invoquer la méthode sur. Est-ce que je vais sur ce dans le mauvais sens? Merci pour toutes les idées ...

Était-ce utile?

La solution

Il y a quelques problèmes ici. Vous pouvez être intéressé par connaître le type Java du récepteur d'appel de méthode ou juste sachant la classe sur la méthode est invoquée. Java est plus d'informations d'information car il vous donne les types génériques ainsi, par exemple List<String> tandis que les éléments ne ferait que vous fournir la classe, par exemple List<E>.

Obtenir l'élément

Pour obtenir l'élément de la classe la méthode est invoquée, vous pouvez le faire ce qui suit:


  MethodInvocationTree node = ...;
  Element method =
        TreeInfo.symbol((JCTree)node.getMethodSelect());
  TypeElement invokedClass = (TypeElement)method.getEnclosingElement();

cas d'angle:

1. invokedClass pourrait être une superclasse du type de récepteur. Donc, en cours d'exécution l'extrait sur retournerait new ArrayList<String>.equals(null) Plutôt que AbstractList ArrayList, puisque equals () est mis en œuvre en ne new int[].clone() TypeElement.

2. Lors de la manipulation des invocations de matrice, par exemple Array, vous le feriez obtenir de la classe OuterClass.this.toString() receiver.

Obtenir le type réel

Pour obtenir le type, il n'y a aucun moyen direct pour déterminer ce que la type de récepteur est. Il y a une certaine complexité dans le traitement des invocations de méthode dans les classes internes où le récepteur n'est pas donné explicitement (Par exemple, contrairement à TypeMirror). Voici une 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 DeclaredType type doit être pas new int[5].clone() ArrayType malheureusement. Lors de l'appel int[], serait null un de AbstractTypeProcessor JavacTask, qui est plus informatif que le précédent méthode.

Comment à exécuter

Les deux méthodes précédentes exigent le compilateur pour résoudre le type informations pour les classes. Dans des circonstances habituelles, le compilateur seulement résoudre les types de déclarations de méthode mais pas les organismes. Par conséquent, les méthodes décrites précédemment retourneraient à la place JavacTask.analyze().

Pour que le compilateur résoudre les informations de type, vous pouvez faire l'une des de la manière suivante:

1. Utilisez la classe qui vient <=> se est ajouté à la dépôt de 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. Le compilateur vous permet d'utiliser la classe prévue dans une arrière de manière compatible avec Java 5.

Cette approche vous permet d'écrire des processeurs qui s'invoquaient juste comme vos processeurs actuels.

2. Utilisez plutôt appeler et <=> <=>. Regarder la principale méthode de ce test javac pour voir comment pour appeler votre visiteur sur les classes.

Cette approche rend votre processeur plus comme un outil d'analyse plutôt que d'un plug-in pour le compilateur, comme vous devez l'appeler directement plutôt que de l'avoir un processus régulier.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top