如何从PMD的Java AST中获取参数及自定义类的限定类型名称以实现跨库方法统一寻址
你想要构建跨库的方法一致寻址方式,需要获取类和方法参数的限定名称(比如示例中的VariousArgumentTypes.mixedArguments(int, int[], java.lang.String, VariousArgumentTypes$InnerType[])),但使用PMD的getType()等相关方法时始终返回null,调用getBinaryName()还会触发NullPointerException。这个问题的核心原因是PMD默认仅进行语法解析,未启用类型解析功能,导致无法获取类型相关的语义信息。
下面是具体的解决方法:
1. 启用PMD的类型解析功能
PMD的类型解析需要显式开启,不同使用场景的配置方式略有不同:
代码中直接解析的场景
如果你是通过Java代码直接调用PMD解析AST,需要在初始化JavaParser时启用类型解析:
import net.sourceforge.pmd.lang.java.ast.JavaParser; import net.sourceforge.pmd.lang.java.JavaVersion; // 初始化解析器并启用类型解析 JavaParser parser = JavaParser.createParser(JavaVersion.LATEST); parser.setTypeResolution(true); // 之后用该解析器处理你的源代码即可
Maven项目场景
如果是在Maven中使用PMD插件,需要在插件配置中添加<useTypeResolution>true</useTypeResolution>,确保PMD在解析时启用类型解析:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-pmd-plugin</artifactId> <version>3.19.0</version> <!-- 使用适配PMD 6.49.0的插件版本 --> <configuration> <useTypeResolution>true</useTypeResolution> <!-- 其他配置 --> </configuration> </plugin>
另外,如果需要解析第三方库(比如java.lang.String、java.util.Set)的类型,要确保这些依赖已经加入项目的类路径,PMD才能正确获取它们的类型信息。
2. 正确获取方法参数的限定名
启用类型解析后,param.getType()会返回有效的TypeMirror对象,通过它就能获取到参数类型的限定名。对于数组类型,需要额外处理组件类型:
ASTFormalParameters params = methodDeclaration.getFormalParameters(); for (ASTFormalParameter param : params) { TypeMirror type = param.getType(); if (type != null) { String qualifiedTypeName; // 处理数组类型 if (type instanceof ArrayType) { ArrayType arrayType = (ArrayType) type; qualifiedTypeName = arrayType.getComponentType().getQualifiedName() + "[]"; } else { qualifiedTypeName = type.getQualifiedName(); } System.out.println(qualifiedTypeName); } }
这段代码会输出符合你需求的限定名,比如基本类型int、数组int[]、Java标准库类java.lang.String、内部类VariousArgumentTypes$InnerType[]等。
3. 正确获取类的二进制名
启用类型解析后,ASTAnyTypeDeclaration.getBinaryName()就能正常返回类的二进制名了,包括内部类的情况(比如VariousArgumentTypes$InnerType),不会再触发NullPointerException。
补充说明
PMD的默认解析模式只做语法分析,仅生成语法树结构,不关联类型语义信息。只有启用类型解析后,PMD才会在解析过程中构建类型系统,此时那些依赖类型信息的API才能正常工作。
内容的提问来源于stack exchange,提问作者trk

