如何获得最终的包名?
How to get final package name?
我有密码
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);
}
}
}
}
我有两个问题:
- 如何将语句转换为表达式?我想检查的是方法调用。我试图通过这种方式检查它们是否是不兼容的类型:
if(stmt instanceof MethodCallExp)
但出现错误。我输入了我现在使用的代码。这是执行检查的一种方法吗?
System.out.println("Scope: " + exp.getScope());
将显示 object/package/package+class 名称。但是如何得到它的类型呢?
例如代码 System.out.println("Hello world");
应该输出
Type: java.io.PrintStream
- 语句和表达式之间没有 1:1 关系。例如。 ExpressionStmt 只包含一个 Expression,但是 WhileStmt 包含一个条件 Expression 和一个包含另一个 Statement 的主体。
- getScope() 调用返回的 FieldAccessExpr 中不包含类型信息。 JavaParser 似乎没有提供获取类型的简单方法。使用节点层次结构及其类型,您可以使用相应的反射 classes 来实现您的目标。对于您的示例,这意味着找到最顶层的范围(类型将是 NameExpr)并获取 Class 对象(认识到 System 是 java.lang.System 的缩写),对于下一个节点(类型将是 FieldAccessExpr)您将获得 class 的字段,然后可以获得类型:
Class.forName("java.lang.System").getField("out").getType();
在上面的代码示例中,您将访问者传递给方法主体中的每个语句。
如果您在循环外创建访问者,它将能够记住之前语句中看到的信息。
这样,您可以向访问者添加一个字段来存储变量声明:final HashMap varNameToType = new HashMap();</pre>
您可以像下面这样存储变量声明。
当您进行方法调用时,您可以使用作用域尝试通过映射获取类型。如果映射不包含类型,您可能需要使用反射,因为变量可能是 JDK classes 的一部分。我并不是说这涵盖了所有情况。例如。当您访问父 class 的字段时,您不会在代码中的位置获得有关该字段的任何信息 - 您可能需要为此查看不同的编译单元。
@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)
);
}
如果您不需要坚持 JavaParser
,也许您可以按照 Android lint 工具的方式解决它。 EcjParserTest.java。它在引擎盖下使用 Lombok
。
在第 380
行,它在测试中比较了与您想要的输出相似的输出 [ExpressionStatement], type: void, resolved method: println java.io.PrintStream
。
我没有深入了解,但它看起来是一个很有希望的起点
我有密码
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);
}
}
}
}
我有两个问题:
- 如何将语句转换为表达式?我想检查的是方法调用。我试图通过这种方式检查它们是否是不兼容的类型:
if(stmt instanceof MethodCallExp)
但出现错误。我输入了我现在使用的代码。这是执行检查的一种方法吗? System.out.println("Scope: " + exp.getScope());
将显示 object/package/package+class 名称。但是如何得到它的类型呢? 例如代码System.out.println("Hello world");
应该输出
Type: java.io.PrintStream
- 语句和表达式之间没有 1:1 关系。例如。 ExpressionStmt 只包含一个 Expression,但是 WhileStmt 包含一个条件 Expression 和一个包含另一个 Statement 的主体。
- getScope() 调用返回的 FieldAccessExpr 中不包含类型信息。 JavaParser 似乎没有提供获取类型的简单方法。使用节点层次结构及其类型,您可以使用相应的反射 classes 来实现您的目标。对于您的示例,这意味着找到最顶层的范围(类型将是 NameExpr)并获取 Class 对象(认识到 System 是 java.lang.System 的缩写),对于下一个节点(类型将是 FieldAccessExpr)您将获得 class 的字段,然后可以获得类型:
在上面的代码示例中,您将访问者传递给方法主体中的每个语句。 如果您在循环外创建访问者,它将能够记住之前语句中看到的信息。 这样,您可以向访问者添加一个字段来存储变量声明:Class.forName("java.lang.System").getField("out").getType();
final HashMap varNameToType = new HashMap();</pre>
您可以像下面这样存储变量声明。 当您进行方法调用时,您可以使用作用域尝试通过映射获取类型。如果映射不包含类型,您可能需要使用反射,因为变量可能是 JDK classes 的一部分。我并不是说这涵盖了所有情况。例如。当您访问父 class 的字段时,您不会在代码中的位置获得有关该字段的任何信息 - 您可能需要为此查看不同的编译单元。
@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)
);
}
如果您不需要坚持 JavaParser
,也许您可以按照 Android lint 工具的方式解决它。 EcjParserTest.java。它在引擎盖下使用 Lombok
。
在第 380
行,它在测试中比较了与您想要的输出相似的输出 [ExpressionStatement], type: void, resolved method: println java.io.PrintStream
。
我没有深入了解,但它看起来是一个很有希望的起点