【问题标题】:Erronous Declaration when getting method from AST从 AST 获取方法时的错误声明
【发布时间】:2019-12-16 12:40:56
【问题描述】:

我正在尝试使用 AST 获取方法声明,因此我可以遍历它,查找某些语句。它以前工作过,但我不能让它工作了,我得到的声明在我看来就像有某种解析错误。我找不到有关如何解决此问题的信息:

{<|java+method:///MetricsTest/testMethod()|,compilationUnit([],[],src=|java+method:///MetricsTest/testMethod()|(0,30,<1,0>,<2,2>),decl=|java+compilationUnit:///MetricsTest/testMethod()|,messages=[error("Syntax error on token \"void\", @ expected",|java+method:///MetricsTest/testMethod()|(7,4,<1,0>,<1,0>)),error("Syntax error, insert \"enum Identifier\" to complete EnumHeader",|java+method:///MetricsTest/testMethod()|(23,1,<1,0>,<1,0>))])>}

我的(部分)代码如下:

public rel[loc, loc] getMethods(M3 model) {
    return { <x,y> | <x,y> <- model.containment
               , x.scheme=="java+class"
               , y.scheme=="java+method" || y.scheme=="java+constructor" 
               };
}

public rel[loc, Declaration] getMethodLocWithDeclaration(M3 model) {
    rel[loc, loc] methods = getMethods(model);
    rel[loc, Declaration] methodsWithAST = {};
    for(<loc c, loc m> <- methods) {
        methodsWithAST += <m, createAstFromFile(m, false)>;
    }

    return methodsWithAST;
}

有人知道我该如何解决这个问题吗?

【问题讨论】:

    标签: rascal


    【解决方案1】:

    即使输入文件中存在解析错误,createAstFromFile 函数也会返回“一半”的 AST。所以你会得到一个compilationUnit 节点,但紧接着它下面有一个error 节点,其中包含有关解析错误的信息。

    顶部的compilationUnit 节点似乎也有一个字段messages,它列出了当前文件的所有错误。

    Java 编译器在该特定文件中发现了两个解析错误:

    1. error("Syntax error on token \"void\", @ expected",|java+method:///MetricsTest/testMethod()|(7,4,&lt;1,0&gt;,&lt;1,0&gt;))
    2. error("Syntax error, insert \"enum Identifier\" to complete EnumHeader",|java+method:///MetricsTest/testMethod()|(23,1,&lt;1,0&gt;,&lt;1,0&gt;))])

    要解决这个问题,我会在 Eclipse 中打开 MetricsTest 类并使用编辑器支持来修复文件。当文件被修复并且您再次尝试 createAstFromFile 函数时,它应该会再次工作。

    确保您知道自己正在解析的内容的一种方法是使用 IO 库中的 readFile 函数。很可能您只将文件的一部分发送到 java 解析器,它只能处理完整的文件。

    如果您将其添加到您的 for 循环中,您可以检测是否是这种情况:

    println("Parsing \'<readFile(m)>\'");
    

    您很可能通过 |java+method:///MetricsTest/testMethod()|(23,1,&lt;1,0&gt;,&lt;1,0&gt;)) 作为 createAstFromFile 的 URI,这只是 MetricsTest.java 文件的一部分。我猜这就是问题所在。

    要解决这个问题,您可以从 M3 模型中的 decls 关系中查找真正的源位置,然后使用 .top 覆盖整个文件。另一种方法是为MetricsTest 类构造一个java+compilationUnit URI,并将其提供给createAstFromFile 函数,或者从containment 关系中查找。

    【讨论】:

    • 您完全正确,因为我正在解析该方法。我有一种以前有效的感觉,但在那种情况下我可能正在解析整个文件。我只需要看看特定的方法。那有什么用?
    • 首先解析整个文件,然后使用访问或/深度匹配找到其中的方法
    • getMethodASTEclipse 方法没有替代品吗?
    • 不,没有。还没有想过如何在所有情况下稳健地做到这一点。如果你有想法,我会全力以赴。
    • 我可以想象。到目前为止,我现在访问了整个文件 AST 并尝试将 \constructor 和 \method 匹配到 M3 方法位置。您知道一种可靠的方法吗?
    【解决方案2】:

    我最终做的是为每个文件创建一个 AST,访问该 AST,并且每当我找到构造函数或方法时,将 impl 添加到列表中。对于这个列表,我发现我可以使用 src 来找到实际的 loc ,我可以用它来做任何我想做的事情。就我而言,这将计算 LoC。

    public list[Statement] getMethodStatements(M3 model) {
        list[Statement] methodStatements = [];
    
        for(file <- files(model.containment)) {
            Declaration fileAST = createAstFromFile(file, false);
    
            visit(fileAST) {
                case \constructor(_,_,_,impl): {
                    methodStatements += impl;
                }
                case \method(_,_,_,_,impl): {
                    methodStatements += impl;
                }
            }
        }
    
        return methodStatements;
    }
    

    【讨论】:

      猜你喜欢
      • 2020-03-21
      • 2016-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-05
      • 1970-01-01
      • 2017-06-15
      相关资源
      最近更新 更多