如何在读取java源文件时查找变量的类型

use*_*014 2 java parsing

假设我有一个source.java与下面相同的 java 源文件 ( )。

1  package demo;
2
3  public class Source {
4
5   public static void main(String[] args) {
6
7       String sample = "foo bar";
8       
9       System.out.println(sample.length());
10
11     }
12  }
Run Code Online (Sandbox Code Playgroud)

现在我想编写一个java代码,逐行读取这个源文件,当它遇到第9行中的变量时,它会告诉我样本变量属于sample哪个类(即)。java.lang.String我怎样才能做到这一点?我已经看到下面的链接,它对我不起作用,因为它在同一源文件中打印类型名称。

打印 Java 变量的类型

小智 6

为了阅读一个独立的java源文件,你必须从头开始,逐行阅读,按照Java的语法解析文件的每个单词,......太多的工作要做。或者我推荐JavaParser

JavaParser读取原始 Java 源文件并将其解析为您可以检索信息的 java 对象。

这是您的问题的示例代码:

public String getSampleVariableType() throws Exception {
    // Use the raw text of file as input
    // `CompilationUnit` contains all information of your Java file.
    CompilationUnit compilationUnit = JavaParser.parse("package demo;\n" +
            "\n" +
            "public class Source {\n" +
            "    public static void main(String[] args) {\n" +
            "        String sample = \"foo bar\"; \n" +
            "        System.out.println(sample.length());\n" +
            "    }\n" +
            "}");

    // Find class by name
    ClassOrInterfaceDeclaration clazz = compilationUnit.getClassByName("Source")
                                                       .orElse(null);
    if (clazz == null) 
        throw new ClassNotFoundException();

    // Find method by name
    List<MethodDeclaration> methods = clazz.getMethodsByName("main");
    if (methods.size() == 0) 
        throw new MethodNotFoundException();

    // Get the content of method's body
    MethodDeclaration method = methods.get(0);
    BlockStmt block = method.getBody().orElse(null);
    if (block == null) 
        throw new MethodEmptyException();

    // Statement `String sample = "foo bar";` is a VariableDeclaration.
    // Find all VariableDeclaration in current method, filter as you want
    // and get its class type by using `getType()` method
    return block.findAll(VariableDeclarator.class).stream()
            .filter(v -> v.getName().asString().equals("sample"))
            .map(v -> v.getType().asString())
            .findFirst().orElse(null);
}
Run Code Online (Sandbox Code Playgroud)

结果是类型的简单名称:String

为了将结果表示为完全限定名称(即java.lang.String)。您可能需要查找全部ImportDeclaration并找到导入的名称:

public static String getFullyQualifiedName(CompilationUnit cu, String simpleName) {
    return cu.findAll(ImportDeclaration.class).stream()
         .filter(i -> i.getName().asString().matches(".*\\b" + simpleName + "\\b"))
         .map(i -> i.getName().asString())
         .findFirst().orElse("java.lang." + simpleName);
}
Run Code Online (Sandbox Code Playgroud)