Java 使用EclipseJDT查找特定节点中可见的所有标识符
我正在开发EclipseJDT的一个插件,它解析Java文件并提供对它们的自动更正。我使用Eclipse的API来分析AST 我试图编写一个方法来计算一个方法的有效性-一个在该方法范围内可见的所有标识符的列表。另一种方式是可以从Eclipse中的特定点自动完成的标识符列表 例如:Java 使用EclipseJDT查找特定节点中可见的所有标识符,java,eclipse,eclipse-plugin,abstract-syntax-tree,Java,Eclipse,Eclipse Plugin,Abstract Syntax Tree,我正在开发EclipseJDT的一个插件,它解析Java文件并提供对它们的自动更正。我使用Eclipse的API来分析AST 我试图编写一个方法来计算一个方法的有效性-一个在该方法范围内可见的所有标识符的列表。另一种方式是可以从Eclipse中的特定点自动完成的标识符列表 例如: import ... public class MyClass { private static final int a = 3; private boolean b; float some
import ...
public class MyClass {
private static final int a = 3;
private boolean b;
float someMethod(String s) {
int c = 3;
(X);
}
}
(X)
中的环境由标识符a
、b
、c
和s
组成
如何在Eclipse中计算方法的环境?必须从要解析的类中获取
ICompilationUnit
。
然后,您可以为所需的节点类型创建访问者
,如MethodDeclaration
public class MainMethodVisitor extends ASTVisitor {
List<MethodDeclaration> methods = new ArrayList<MethodDeclaration>();
@Override
public boolean visit(MethodDeclaration node) {
... //do stuff with the node
有了方法节点,您可以使用node.parameters()
访问其参数,以获得s
。您必须找出类的成员变量是什么类型的节点(a
,b
)。
我认为,最后要做的事情是访问method节点内部的VariableDeclaration
,以获得c
这就是我要帮助你的全部。希望能有所帮助。这里有一些工作代码解决了给定的简单示例,但需要扩展以获得更复杂的代码:
- 范围,e。g<代码>整数a=1;{int b=2;}(X)(环境:
)a
- 继承权
- 带或不带通配符的静态导入,例如。g<代码>导入静态java.lang.Integer.MAX_值或
导入静态java.lang.Integer.*代码>
node.resolveBinding()
遍历AST并访问交叉连接
公共类环境{
公共静态void main(字符串[]args){
String code=“公共类MyClass{\n”+
“专用静态最终整数a=3;\n”+
“专用布尔b;\n”+
“\n”+
“float someMethod(字符串s){\n”+
“int c=3;\n”+
“/(X);\n”+
“}\n”+
"}";
for(IBinding binding:of(code,code.indexOf(“(X)”)){
System.out.println(binding.getName());
}
}
公共静态列表(字符串代码,整数偏移){
最终列表环境=新的ArrayList();
createAst(代码).accept(新ASTVisitor(真){
公共布尔访问(VariableDeclarationFragment节点){
if(offset
或者,字段(包括常量)可以通过node.getFields()
在visit(TypeDeclaration节点)
处收集,或者通过AST前面的node.parameters()
在visit(MethodDeclaration节点)
处收集方法的参数
ICompilationUnit unit;
//...
CompilationUnit parse = parse(unit);
MainMethodVisitor visitor = new MainMethodVisitor();
parse.accept(visitor);
public class Environment {
public static void main(String[] args) {
String code = "public class MyClass {\n" +
" private static final int a = 3;\n" +
" private boolean b;\n" +
"\n" +
" float someMethod(String s) {\n" +
" int c = 3;\n" +
" // (X);\n" +
" }\n" +
"}";
for (IBinding binding : of(code, code.indexOf("(X)"))) {
System.out.println(binding.getName());
}
}
public static List<IBinding> of(String code, int offset) {
final List<IBinding> environment = new ArrayList<>();
createAst(code).accept(new ASTVisitor(true) {
public boolean visit(VariableDeclarationFragment node) {
if (offset < node.getStartPosition()) return false;
environment.add(node.resolveBinding());
return true;
}
public boolean visit(SingleVariableDeclaration node) {
if (offset < node.getStartPosition()) return false;
environment.add(node.resolveBinding());
return true;
}
});
return environment;
}
private static CompilationUnit createAst(String code) {
// parser
ASTParser parser = ASTParser.newParser(AST.JLS10);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setResolveBindings(true);
parser.setBindingsRecovery(true);
parser.setStatementsRecovery(true);
// options
final Hashtable<String, String> options = JavaCore.getOptions();
options.put("org.eclipse.jdt.core.compiler.source", "1.8");
parser.setCompilerOptions(options);
// sources and classpath
String[] sources = new String[] { /* source folders */ };
String[] classpath = new String[] { /* JARs */};
String[] encodings = new String[sources.length];
Arrays.fill(encodings, StandardCharsets.UTF_8.name());
parser.setEnvironment(classpath, sources, encodings, true);
parser.setUnitName("code");
parser.setSource(code.toCharArray());
// abstract syntax tree
return (CompilationUnit) parser.createAST(null);
}
}