Question

J'ai le nom d'une variable / identifiant, par exemple, x, et le JCCompilationUnit et Scope .Existe-t-il un moyen de trouver le type de x?

Était-ce utile?

La solution

 public Symbol getSymbol(CompilationUnitTree cut, JCStatement stmt, List<JCExpression> typeParams, Name varName, List<JCExpression> args) {
    java.util.List<Type> typeSyms = getArgTypes(typeParams, cut, stmt);
    java.util.List<Type> argsSyms = getArgTypes(args, cut, stmt);
    final Scope scope = getScope(cut, stmt);
    Symbol t = contains(scope, typeSyms, varName, argsSyms); //first lookup scope for all public identifiers
    TypeElement cl = scope.getEnclosingClass();
    while (t == null && cl != null) { //lookup hierarchy for inacessible identifiers too
        t = contains(elementUtils.getAllMembers(cl), typeSyms, varName, argsSyms);
        final TypeMirror superclass = cl.getSuperclass();
        if (superclass != null) {
            cl = (TypeElement) ((Type) superclass).asElement();
        }
    }
    return t;
}

public Symbol getSymbol(Name varName, Symbol accessor, CompilationUnitTree cut, JCStatement stmt) {
    if (varName.contentEquals("class")) {
        Symbol javaLangClassSym = getSymbol(cut, stmt, null, elementUtils.getName("java.lang.Class"), null);
        JCIdent id = tm.Ident(javaLangClassSym);
        JCExpression mName = tm.Select(id, elementUtils.getName("forName"));
        JCLiteral idLiteral = tm.Literal(accessor.toString());
        JCMethodInvocation mi = tm.Apply(List.<JCExpression>nil(), mName, List.<JCExpression>of(idLiteral));
        Symbol s = getSymbol(mi, cut, stmt);
        return s;
    }
    accessor = getTypeSymbol(accessor);
    java.util.List<Symbol> enclosedElements = getEnclosedElements(accessor, cut, stmt);
    Symbol s = contains(enclosedElements, null, varName, null);
    return s;
}

J'ai fini par écrire un classe avec méthodes de résolution .En héritant, ou en passant dans TreeMaker (et d'autres paramètres), il peut être rendu statique.Si quelqu'un le trouve utile, un correctif est le bienvenu.

Autres conseils

Le Scope a une méthode getLocalElements(), qui peut être itéré. Chaque élément peut alors être demandé par son nom, et quand c'est le bon (et c'est aussi une variable), vous pouvez obtenir son type.

Voici le concept, non testé:

private final static Set<ElementKind> variableKinds =
       Collections.unmodifiableSet(EnumSet.of(ElementKind.FIELD, ElementKind.ENUM_CONSTANT,
                                              ElementKind.PARAMETER, ElementKind.LOCAL_VARIABLE));

public Type getTypeOfVariable(Scope scope, String varName)
{
   for(Element e : scope.getLocalElements()) {
       if(variableKinds.contains(e.getKind()) && e.getName().equals(varName)) {
           return e.getType();
       }
   }
   throw new NoSuchElementException("No variable " + varName + " in " + scope);
}

Modifier: Oui, vraiment non testé (il n'y a pas de méthode getType()).

Alors, comment obtenir un Element (ou VariableElement) à partir de son type?

La classe Trees a des méthodes utilitaires permettant de récupérer un Tree ou TreePath à partir du Element, et ainsi nous pouvons obtenir un VariableTree (puisque cela vient d'une déclaration de variable). Le VariableTree a maintenant une méthode getType(), qui retourne un Tree - mais en fait c'est l'un des PrimitiveTypeTree, ParametrizedTypeTree, ArrayTypeTree et IdentifierTree (pour les types de référence simples ainsi que les variables de type). Donc, si vous ne souhaitez imprimer que le texte, cela peut suffire. Sinon, encore une fois avec la classe Trees, nous pouvons maintenant obtenir un TypeMirror pour ce type.

(J'ai fait quelque chose de similaire une fois lorsque j'ai essayé d'écrire un nouveau Doclet qui afficherait également le code source formaté. Terrible basculement entre toutes ces API.)

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