【问题标题】:JavaParser: How to retrieve all ParentNode names from MethodDeclaration?JavaParser:如何从 MethodDeclaration 中检索所有 ParentNode 名称?
【发布时间】:2019-01-02 14:12:25
【问题描述】:

我正在使用 JavaParser 库 (https://github.com/javaparser/javaparser) 来解析 Java 方法声明。我想从不同的包、类、作用域等中识别出不同的方法声明,以便准确识别每个方法声明。

例如:

这是一个名为MainClass.java的Java文件:

package com.company.packA.packB;

public class MainClass {
    void doTask(int x, int y) {
        //...
    }

    private class InnerClass {
        void doTask(int x, int y) {
            //...
        }
    }
}

class AnotherClassSameFile {
    void doTask(int x, int y) {
        //...
    }
}

请注意,上面的示例包含 三个 void doTask(int x, int y) 方法:

  1. com.company.packA.packBMainClassdoTask(int x, int y)
  2. com.company.packA.packBMainClassInnerClassdoTask(int x, int y)
  3. com.company.packA.packBAnotherClassSameFiledoTask(int x, int y)

要识别具有相同方法签名的不同方法声明,我需要遍历所有父节点,直到根节点。

到目前为止,我已经使用 JavaParser 库尝试了这段代码(简化):

class MethodStruct {    // the second example will be:
    String parentNodes; // com.company.packA.packB#MainClass#InnerClass
    String returnType;  // void
    String methodName;  // doTask
    String parameters;  // int,int
}

class JavaParserTest {
    // this is the method to be called from outside
    static List<MethodStruct> getMethodStructs(Reader reader) {
        CompilationUnit cu = JavaParser.parse(reader);

        List<MethodStruct> methodStructs = new LinkedList<>();
        cu.accept(new MethodVisitor(), methodStructs);

        return methodStructs;
    }

    static class MethodVisitor extends VoidVisitorAdapter<List<MethodStruct>> {
        @Override
        public void visit(MethodDeclaration methodDeclaration, List<MethodStruct> methodStructs) {
            super.visit(methodDeclaration, methodStructs);

            // adding individual methodStruct into the list
            methodStructs.add(getMethodStruct(methodDeclaration));
        }

        static MethodStruct getMethodStruct(MethodDeclaration methodDeclaration) {
            return new MethodStruct(
                    getParents(methodDeclaration),
                    methodDeclaration.getTypeAsString(),
                    methodDeclaration.getNameAsString(),
                    getParameterAsString(methodDeclaration.getParameters()));
        }

        // it is the method to be concerned for my question
        static String getParents(MethodDeclaration methodDeclaration) {
            StringBuilder parents = new StringBuilder();

            Node currentNode = methodDeclaration;
            while (currentNode.getParentNode().isPresent()) {
                // goto parent node
                currentNode = currentNode.getParentNode().get();

                //TODO: I'm stuck here. Help me please!
                //TODO: How to identify each node whether
                //      it is a package, innerClass, etc?
            }

            // convert StringBuilder into String and return the String
            return parents.toString();
        }

        static String getParameterAsString(NodeList<Parameter> parameters) {
            // easy task! convert parameter string list
            // into a single string (comma separated)
        }
    }
}

我在定义getParents(MethodDeclaration methodDeclaration) 方法时遇到了困难。我该如何解决它(即识别每个父节点)?我找不到任何有用的 Node 类方法来实现我的目标。我可能错过了JavaParser 库中的某些内容。

【问题讨论】:

    标签: java abstract-syntax-tree javaparser


    【解决方案1】:

    您应该尝试使用walk 方法来查找具体方法声明的所有范围:

    static String getParents(fina MethodDeclaration methodDeclaration) {
        final StringBuilder parents = new StringBuilder();
    
        methodDeclaration.walk(Node.TreeTraversal.PARENTS, node -> {
            if (node instanceof ClassOrInterfaceDeclaration) {
                path.insert(0, ((ClassOrInterfaceDeclaration) node).getNameAsString());
                path.insert(0, '$');
            }
            if (node instanceof ObjectCreationExpr) {
                path.insert(0, ((ObjectCreationExpr) node).getType().getNameAsString());
                path.insert(0, '$');
            }
            if (node instanceof MethodDeclaration) {
                path.insert(0, ((MethodDeclaration) node).getNameAsString());
                path.insert(0, '#');
            }
            if (node instanceof CompilationUnit) {
                final Optional<PackageDeclaration> pkg = ((CompilationUnit) node).getPackageDeclaration();
                if (pkg.isPresent()) {
                    path.replace(0, 1, ".");
                    path.insert(0, pkg.get().getNameAsString());
                }
            }
        });
    
        // convert StringBuilder into String and return the String
        return parents.toString();
    }
    

    【讨论】:

      猜你喜欢
      • 2018-08-26
      • 2013-09-08
      • 1970-01-01
      • 2020-09-16
      • 2021-01-19
      • 1970-01-01
      • 1970-01-01
      • 2012-08-01
      • 1970-01-01
      相关资源
      最近更新 更多