4

我有一个像下面这样的课程。

public class Login {
    private Keyword browser;
    private String page;
}

Keyword是不同包中的一个类。我想在使用javaparserKeyword 解析类时获取类的完全限定名。Login

4

8 回答 8

4

使用 JavaParser 无法做到这一点,因为 JavaParser 不解析符号。要将名称关键字解析为一个类,您需要做几件事: * 实现适当的范围规则(您需要查找内部类,然后查找同一文件中的其他类,然后考虑导入...) * 它取决于用于编译的类路径:更改它相同的类可能会以不同的方式解析

为此,应该编写一个符号解析器:它不是微不足道的而是可行的。如果您对该主题感兴趣,可以阅读我刚刚在 Clojure 中写的如何为 Java 构建符号求解器的帖子。这篇文章还包含一个代码链接,可在 GitHub 上免费获得。

来源:我是 JavaParser 贡献者

于 2015-05-20T20:37:09.230 回答
2

您可以使用 JavaParser 符号求解器:

<dependency>
    <groupId>com.github.javaparser</groupId>
    <artifactId>javaparser-symbol-solver-core</artifactId>
    <version>3.14.5</version>
</dependency>

然后使用以下配置解析代码:

CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), 
                                                     new JavaParserTypeSolver(sourceRoot));
final ParserConfiguration config = new ParserConfiguration()
                .setStoreTokens(true)
                .setSymbolResolver(new JavaSymbolSolver(combinedTypeSolver));
SourceRoot root = new SourceRoot(Paths.get("/path/to/project/"));
root.parse("", config, (Path localPath, Path absolutePath, ParseResult<CompilationUnit> result) -> {
                // Do something with the CompilationUnit
                return Result.DONT_SAVE;
            });

我们现在可以获得任何ReferenceType使用的完全限定标识符:

ResolvedType type = referenceType.resolve();
String qualifiedName = type.getQualifiedName();
于 2019-07-12T08:21:53.897 回答
1

到目前为止似乎没有人阅读过这个问题,但是如果您正在解析源代码,它要么在当前包中,要么是由 import 语句导入的。

我本来希望 Java 解析器编写者或用户知道这一点。

于 2014-03-27T10:13:05.193 回答
1

我写了一个可以基于ClassOrInterfaceDeclaration对象(JavaParser的最新版本)获取完全限定名的方法:

    private static String getFullyQualifiedName(ClassOrInterfaceDeclaration c2) {
        String name = "";
        ClassOrInterfaceDeclaration parentClass = c2.getParentNode().isPresent() ? getClass(c2.getParentNode().get()): null;
        if(parentClass!=null) {
            name+=getFullyQualifiedName(parentClass)+".";
        } else {
            CompilationUnit u = getCompilationUnit(c2);
            if(u!=null && u.getPackageDeclaration().isPresent()) {
                name+=u.getPackageDeclaration().get().getNameAsString()+".";
            }
        }
        return name+c2.getNameAsString();
    }

    private static ClassOrInterfaceDeclaration getClass(Node n1) {
        while (!(n1 instanceof ClassOrInterfaceDeclaration)) {
            if(n1.getParentNode().isPresent()) {
                n1 = n1.getParentNode().get();
            } else return null;
        }
        return (ClassOrInterfaceDeclaration)n1;
    }

    private static CompilationUnit getCompilationUnit(Node n1) {
        while (!(n1 instanceof CompilationUnit)) {
            if(n1.getParentNode().isPresent()) {
                n1 = n1.getParentNode().get();
            } else return null;
        }
        return (CompilationUnit)n1;
    }

ClassOrInterfaceType如果您获得该类的 ,则可以使用更简单的版本:

    private static String getFullyQualifiedName(ClassOrInterfaceType e) {
        String name = "";
        if(e.getScope().isPresent())
            name+=getFullyQualifiedName(e.getScope().get())+".";
        return name+e.getNameAsString();
    }

我希望这对任何人都有帮助!

于 2019-04-17T07:39:36.937 回答
0

如果您正在使用访问者,您似乎只能在源文件中获取开始和结束索引以获得类型名称。这不会让您获得完全限定的名称。

因此,您也应该visit(ImportDeclaration, A)在自定义访问者中实现该方法。然后,此方法必须存储导入声明,因此您可以稍后 - 当该方法visit(FieldDeclaration, A)被调用时 - 引用导入的包并组装完全限定名称。

于 2014-03-27T10:20:40.983 回答
0

JavaParser 不解析导入(无论如何,这通常不被认为是它的工作)。您必须手动逐步执行导入语句并搜索是否Keyword属于它们。请记住,Java 隐式执行 a import java.lang.*,否则您将无法解析诸如String.

Spring Roo 有一个包含方法的JavaParserUtilsgetJavaType(CompilationUnitServices compilationUnitServices, ClassOrInterfaceDeclaration cid)类。该类不是为 Roo 之外的使用而设计的,但您可以将其用作解决问题的模板。

于 2014-03-27T10:34:15.177 回答
-2

这可能是解决您问题的更好方法,

使用的实例。

在java中使用“实例”

于 2014-03-27T10:12:28.200 回答
-2

使用 Java 反射 (java.lang.reflect)

于 2014-03-27T10:13:53.950 回答