【问题标题】:How get line from parsed java source from Eclipse JDT Parser?如何从 Eclipse JDT Parser 解析的 java 源代码中获取行?
【发布时间】:2016-10-13 15:25:36
【问题描述】:

在我的硬盘中,我有以下来源:

package DAO;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.CountDownLatch;


public abstract class A {
public class A4{
    public String teste4(int i){
        return (new String("teste"));
    }
}
public class A3{
    public String teste3(int i){
        return (new String("teste"));
    }
    public A4 teste33(int i){
        return (new A4());
    }       
}
public class A2{
    public A3 teste2(int i){
        return (new A3());
    }
}
public class A1{
    public A2 teste1(int i){
        return (new A2());
    }
}


  public int[] toIntArray(List<Integer> list) {
     A1 q=new A1();

     Integer t=q.teste1(
                (new A1()).
                teste1(0).
                teste2(0).
                teste33(0).
                teste4(0).
                length() ).
            teste2(0).
            teste3(0).
            length();
  } 
}

请注意,在这个文件(A.java)中,我们有很多空行,一个命令不一定写在同一行,换句话说,它可能分布在很多行中(参见方法“toIntArray”的最后一行) . 当我用 AST 解析这个源代码时,“CompilationUnit”的“toString”显示以下结构(AST Struct):

package DAO;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.CountDownLatch;
public abstract class A {
public class A4 {
    public String teste4(    int i){
      return (new String("teste"));
    }
  }
public class A3 {
    public String teste3(    int i){
      return (new String("teste"));
    }
    public A4 teste33(    int i){
      return (new A4());
    }
  }
public class A2 {
    public A3 teste2(    int i){
      return (new A3());
    }
  }
public class A1 {
    public A2 teste1(    int i){
      return (new A2());
    }
  }
  public int[] toIntArray(  List<Integer> list){
    A1 q=new A1();
    Integer t=q.teste1((new A1()).teste1(0).teste2(0).teste33(0).teste4(0).length()).teste2(0).teste3(0).length();
  }
}

请注意,在这种情况下,所有空行都被删除,命令“Integer t=q.teste1....”被写入同一行。对我来说很好。因此,在访问“MethodInvocation”时,我想获取这些调用的行号。为此,我在我的 astVisitors 中创建了以下来源:

public boolean visit(final CompilationUnit node) {
this.CompilationUnit=node;
}
public boolean visit(final MethodInvocation node) {
Integer LineInFile=this.CompilationUnit.getLineNumber(node.getStartPosition());
}

但是命令“getLineNumber”在我的硬盘驱动器的源文件中返回行号,而不是在 AST Struct 中。在这种情况下,对于“q.teste1((new.....”) 行,命令“getLineNumber”返回第 44 行和第 45 行,但希望它只返回第 44 行。 那么,如何获取“AST Struct”中的行号呢?

【问题讨论】:

  • 为什么要“AST Struct”中的“行号”而不是外部文件?外部文件是用户唯一关心、看到或会识别的东西。她对 AST 结构的兴趣为零,更不用说知道它的存在了。那么这有什么意义呢?

标签: java eclipse parsing abstract-syntax-tree eclipse-jdt


【解决方案1】:

CompilationUnit.toString 方法只是使用 NaiveASTFlattener 类对内部 AST 进行粗略的格式化。

AST 的实际内部结构只是诸如BlockCommentStatement 之类的大量类实例......因此,AST 本身没有行号。 AST 知道的唯一行号是原始源代码中的行。

【讨论】:

  • 在这种情况下,就行而言,预期以下返回:44、45、46、....53。
  • teste1 的方法调用只是第 44 到 45 行。该语句的其余部分是其他方法的调用。
【解决方案2】:

我们可以从将 AST 扩展为“抽象语法树”开始,它强调我们与源级别(=具体)语法没有(直接)联系。您可以将其称为“模型”,它捕获语义相关方面,同时省略诸如空格之类的意外细节。一种语言甚至可以在不更改抽象语法等的情况下重命名其关键字。

为了方便用户,CompilationUnit 额外存储了行尾的位置,因此它可以将 AST 节点映射回其在源代码中的原始位置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-24
    • 1970-01-01
    • 1970-01-01
    • 2011-07-26
    相关资源
    最近更新 更多