Java TreeコンパイラAPIを使用して識別子のタイプ宣言を見つけるにはどうすればよいですか?
-
28-10-2019 - |
質問
私は変数/識別子の名前を持っています、たとえば、 x
, 、 そしてその JCCompilationUnit
と Scope
. 。タイプを見つける方法はありますか x
?
解決
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;
}
私は完全に書くことになりました メソッドを解決するクラス. 。それを継承するか、Treemaker(およびその他のパラメーター)を渡すことができます。誰かがそれが価値があると感じた場合、パッチは大歓迎です。
他のヒント
Scope
オブジェクトにはメソッドがあります getLocalElements()
, 反復することができます。その後、各要素はその名前で尋ねることができ、これが正しいものである場合(そしてそれも変数です)、そのタイプを取得できます。
これは、テストされていない概念です。
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);
}
編集: ええ、本当にテストされていません(noはありません getType()
方法)。
だから、aから取得する方法 Element
そのタイプから(または可変エレメント)?
Trees
クラスにはいくつかのユーティリティ方法があり、 Tree
また TreePath
から Element
, 、したがって、aを取得できます VariableTree
(これは変数宣言から来たので)。 VariableTree
今があります getType()
メソッド、aを返します Tree
- しかし、実際にはこれはの1つです PrimitiveTypeTree
, ParametrizedTypeTree
, ArrayTypeTree
と IdentifierTree
(単純な参照タイプとタイプ変数の場合)。したがって、タイプを印刷したい場合は、これで十分かもしれません。そうでなければ、再び Trees
クラスこのタイプのタイプミラーを入手できます。
(フォーマットされたソースコードを出力する新しいドキュレットを書き込もうとしたときに、私は一度似たことをしました。これらすべてのAPIの間でひどい反転。)