我有一個變量/標識符的名稱,如x
,以及JCCompilationUnit
和Scope
。有沒有辦法找到x
的類型?如何使用Java Tree Compiler API找到標識符的類型聲明?
2
A
回答
3
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;
}
我最後寫一個完整的class with resolving methods。繼承它,或傳遞TreeMaker(和其他參數),它可以變成靜態的。如果有人覺得它值得,那麼補丁是值得歡迎的。
1
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);
}
編輯:呀,真是未經測試(有沒有getType()
方法)。
那麼,如何從Element
(或VariableElement)中獲取它的類型呢?
的Trees
類有一些實用方法允許從Element
一個Tree
或TreePath
的檢索,因此,我們可以得到一個VariableTree
(因爲這是來自一個變量聲明)。 VariableTree
現在有一個getType()
方法,它返回Tree
- 但實際上這是PrimitiveTypeTree
,ParametrizedTypeTree
,ArrayTypeTree
和IdentifierTree
(對於簡單引用類型以及類型變量)之一。所以,如果你只想打印類型,這可能就足夠了。否則,再次使用Trees
類,我們現在可以獲得此類型的TypeMirror。
(我做了類似的事情,一旦當我試圖寫一個新的Doclet這也將輸出格式化的源代碼。所有這些API之間可怕的翻轉。)
相關問題
- 1. 如何找出Java中標識符的聲明類型?
- 2. 'USB_Close':標識符未找到...'len':未聲明的標識符...
- 3. 使用未聲明的標識符的
- 4. 已聲明的未聲明標識符?
- 5. 使用未聲明的標識符 'didReceiveMemoryWarning'
- 6. 使用未聲明的標識符AFHTTPClient
- 7. 使用未聲明的標識符
- 8. 使用未聲明的標識符NSLinkAttributeName
- 9. 使用未聲明的標識符'IKImageBrowserNSURLRepresentationType'
- 10. 使用未聲明的標識符'arr'
- 11. 使用未聲明的標識符'completionCallback'
- 12. 使用未聲明的標識符C++
- 13. 使用未聲明的標識符soundfileURLRef
- 14. '使用未聲明的標識符'completedWithResult''
- 15. 使用未聲明的標識符?
- 16. 「使用未聲明的標識符'AppDelegate'
- 17. 使用未聲明的標識符'FBSDKAppEventNameFBSDKSmartLoginService'
- 18. 使用未聲明的標識符'NSEntityDescription'
- 19. 使用未聲明的標識符'segue'
- 20. 使用未聲明的標識符「FlurryAPI」
- 21. Xcode「使用未聲明的標識符」
- 22. Xcode使用未聲明的標識符
- 23. 使用未聲明的標識符'a'
- 24. 使用未聲明的標識符Amazons3client
- 25. 使用未聲明的標識符
- 26. 使用未聲明的標識符「cellForRowAtIndexPath」
- 27. 使用未聲明的標識符'calculateAge'
- 28. 使用未聲明的標識符:ASIdentifierManager
- 29. FBSDKGraphRequest使用未聲明的標識符
- 30. 使用未聲明的標識符
稍微相關的錯誤我提出了嘗試:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7017477(考慮投票) – simpatico 2011-02-11 09:54:46