5

私はコードを持っています

private static class MyVisitor extends VoidVisitorAdapter<Object> {
    @Override
    public void visit(MethodCallExpr exp, Object arg) {
        System.out.println("Scope: "  + exp.getScope());
        System.out.println("Method: " + exp.getName());
        if(exp.getArgs() != null)
            for(Expression e : exp.getArgs()) {
                System.out.println("\tArgument: " + e.toString());

            }
        System.out.println();
    }
}

CompilationUnit cu = JavaParser.parse(new File("Test.java"));

for(TypeDeclaration type : cu.getTypes()) {
    for(BodyDeclaration dec : type.getMembers()) {
        if(dec instanceof MethodDeclaration) {
            MethodDeclaration mdec = (MethodDeclaration) dec;
            BlockStmt block = mdec.getBody();
            for(Statement stmt : block.getStmts()) {
                MyVisitor visitor = new MyVisitor();
                s.accept(visitor, null);
            }
        }
    }
}

2 つの問題があります。

  1. ステートメントを式に変換する方法は? 確認したいのは、そのメソッド呼び出しです。この方法で互換性のない型であることを確認しようとしましif(stmt instanceof MethodCallExp)たが、エラーが発生しました。今使っているコードを入力しました。それがチェックを実行する1つの方法ですか?
  2. System.out.println("Scope: " + exp.getScope());オブジェクト/パッケージ/パッケージ+クラス名が表示されます。しかし、その型を取得する方法は? たとえば、コードに対してSystem.out.println("Hello world"); 出力する必要があります

タイプ: java.io.PrintStream

4

2 に答える 2

0
  1. ステートメントと式の間に 1 対 1 の関係はありません。たとえば、ExpressionStmt には Expression が 1 つしか含まれていませんが、WhileStmt には条件 Expression と、さらに Statement を構成する本体が含まれています。
  2. getScope() 呼び出しによって返される FieldAccessExpr に含まれる型情報はありません。JavaParser は、型を取得する簡単な方法を提供していないようです。Node 階層とそのタイプを使用すると、対応する Reflection クラスを使用して目標を達成できます。あなたの例では、最上位のスコープ(タイプはNameExprになります)を見つけてクラスオブジェクトを取得し(システムはjava.lang.Systemの略であることを認識します)、次のノード(タイプはFieldAccessExprになります)のフィールドを取得しますクラスの次のタイプを取得できます。
    Class.forName("java.lang.System").getField("out").getType();
    上記のコード例では、メソッド本体内のすべてのステートメントにビジターを渡します。ループの外で訪問者を作成すると、以前のステートメントで見た情報を記憶することができます。このようにして、変数宣言を格納するフィールドをビジターに追加できます。
    final HashMap varNameToType = new HashMap();
    以下のように変数宣言を保存できます。メソッド呼び出しに到達したら、スコープを使用して、マップを介して型を取得しようとすることができます。マップに Type が含まれていない場合は、変数が JDK クラスの一部である可能性があるため、Reflection を使用する必要がある場合があります。これがすべてのケースをカバーすることを示唆しているわけではありません。たとえば、親クラスのフィールドにアクセスする場合、コード内の自分の位置にそのフィールドに関する情報がありません。そのためには、別のコンパイル ユニットを調べる必要がある場合があります。
@Override
public void visit(
        final VariableDeclarationExpr n,
        final Object arg) {
    final Type varType = n.getType();
    n.getVars().forEach(vd ->
        varNameToType.put(vd.getId().getName(),varType)
    );
}
于 2015-04-20T12:19:45.967 に答える