現在、ASTVisitorを使用して基本的なコールツリーを作成する学術プロジェクトに取り組んでいます。EclipseでASTVisitorでオーバーロードされたメソッドを解決するJDT
この目的のために、メソッドの呼び出しをその宣言に関連付ける必要があります。
EDIT:この問題はJUnit-Testsにのみ現れますが、スタンドアロンプラグインには表示されません。 ASTVisitorsの単体テスト・ワークフローと関係しているように見えます。その理由をさらに調査し、答えをここに掲載します。
以下のコードは、呼び出しと関連する宣言コンソールに出力し、最小限の訪問者を示す:
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.MethodInvocation;
/**
* Visits all method invocations and prints the declaration of the caller to
* console.
*/
public class InvocationLoggerASTVisitor extends ASTVisitor {
@Override
public boolean visit(MethodInvocation methodInvocation) {
if (methodInvocation.resolveMethodBinding() != null) {
IMethodBinding declarationOfInvokedMethod = methodInvocation
.resolveMethodBinding().getMethodDeclaration();
System.out.println(String.format(
"invocation of \"%s\" is resolved to declaration \"%s\"",
methodInvocation, declarationOfInvokedMethod));
}
return super.visit(methodInvocation);
}
}
訪問者がいくつかの試験のシナリオのために働きます。 しかし、不思議なことに、オーバーロードされたメソッドを含むコンパイルユニットにそれを適用すると、いくつかの呼び出しが間違った宣言に関連付けられます。
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashSet;
@SuppressWarnings({ "unchecked", "rawtypes" })
public class OverloadedMethodsAndRawTypes implements ICallGraphTestSource {
void f(HashSet objects) {
f(new ArrayDeque(objects));
}
void f(ArrayDeque objects) {
f(new ArrayList(objects));
}
void f(ArrayList objects) {
f(new HashSet(objects));
}
}
このコンパイル単位を訪問し、コンソール出力は次のとおりです:私はこの出力期待
invocation of "f(new ArrayDeque(objects))" is resolved to declaration "void f(HashSet) "
invocation of "f(new ArrayList(objects))" is resolved to declaration "void f(HashSet)"
invocation of "f(new HashSet(list))" is resolved to declaration "void f(HashSet) "
:は、次のコードを訪れることができます
invocation of "f(new ArrayDeque(objects))" is resolved to declaration "void f(ArrayDeque) "
invocation of "f(new ArrayList(objects))" is resolved to declaration "void f(ArrayList)"
invocation of "f(new HashSet(list))" is resolved to declaration "void f(HashSet) "
私は気づいたが、オーバーロードされたメソッドの呼び出しは、呼び出されたメソッド名に一致する最初に発生する宣言に常に解決されます。証明するために
、そのメソッドのオーバーロードのせいで、私は、メソッドのオーバーロードせずに同じコードを添付:
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashSet;
@SuppressWarnings({ "unchecked", "rawtypes" })
public class RawTypes implements ICallGraphTestSource {
void f_set(HashSet objects) {
f_deque(new ArrayDeque(objects));
}
void f_deque(ArrayDeque objects) {
f_list(new ArrayList(objects));
}
void f_list(ArrayList objects) {
f_set(new HashSet(objects));
}
}
訪問したとき、それは正しい出力が得られます。
invocation of "f_deque(new ArrayDeque(objects))" is resolved to declaration "void f_deque(ArrayDeque) "
invocation of "f_list(new ArrayList(objects))" is resolved to declaration "void f_list(ArrayList) "
invocation of "f_set(new HashSet(list))" is resolved to declaration "void f_set(HashSet) "
マイASTParserが構成されています次のように:
public static ASTNode getAST(ICompilationUnit compilationUnit) {
ASTParser parser = ASTParser.newParser(AST.JLS3);
parser.setSource(compilationUnit);
parser.setResolveBindings(true);
parser.setBindingsRecovery(true);
parser.setProject(getJavaProject());
return parser.createAST(null);
}
EDIT:上記の設定はJUnit-Testsでは機能しませんが、スタンドアロン・プラグインとして機能します。この理由は、一時的なプロジェクトが作成されるgetJavaProject-Methodではその理由が必要です。
ここにはまだ質問がありますか? –
問題は解決されました。私は解決策として回答を投稿しました。 – mtsz
あなた自身の答えを受け入れることもできます。 :) –