从 AST 获取方法时的错误声明
Erronous Declaration when getting method from AST
我正在尝试使用 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;
}
有人知道我该如何解决这个问题吗?
即使输入文件中存在解析错误,createAstFromFile
函数也会 return "half" AST。所以你得到一个 compilationUnit
节点,但在它的正下方有一个 error
节点,其中包含有关解析错误的信息。
顶部compilationUnit
节点似乎也有一个字段messages
,它列出了当前文件的所有错误。
Java 编译器在该特定文件中发现了两个解析错误:
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>))])
要解决这个问题,我会在 Eclipse 中打开 MetricsTest class 并使用编辑器支持来修复文件。当文件修复后,您再次尝试 createAstFromFile 函数,它应该会再次起作用。
确保您清楚自己正在解析的内容的一种方法是使用 IO 库中的 readFile
函数。很可能您只将文件的一部分发送到 java 解析器,它只能处理完整的文件。
如果您将此添加到您的 for 循环中,您可以检测是否是这种情况:
println("Parsing \'<readFile(m)>\'");
您可能将此:|java+method:///MetricsTest/testMethod()|(23,1,<1,0>,<1,0>))
作为 URI 传递给 createAstFromFile,而这只是 MetricsTest.java
文件的一部分。我猜这就是问题所在。
要解决这个问题,您可以从 M3 模型中的 decls
关系中查找真正的源位置,然后使用 .top
覆盖整个文件。另一种方法是为 MetricsTest
class 构造一个 java+compilationUnit
URI,并将其提供给 createAstFromFile
函数,或者从 containment
关系中查找。
我最后做的是为每个文件创建一个 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;
}
我正在尝试使用 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;
}
有人知道我该如何解决这个问题吗?
即使输入文件中存在解析错误,createAstFromFile
函数也会 return "half" AST。所以你得到一个 compilationUnit
节点,但在它的正下方有一个 error
节点,其中包含有关解析错误的信息。
顶部compilationUnit
节点似乎也有一个字段messages
,它列出了当前文件的所有错误。
Java 编译器在该特定文件中发现了两个解析错误:
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>))])
要解决这个问题,我会在 Eclipse 中打开 MetricsTest class 并使用编辑器支持来修复文件。当文件修复后,您再次尝试 createAstFromFile 函数,它应该会再次起作用。
确保您清楚自己正在解析的内容的一种方法是使用 IO 库中的 readFile
函数。很可能您只将文件的一部分发送到 java 解析器,它只能处理完整的文件。
如果您将此添加到您的 for 循环中,您可以检测是否是这种情况:
println("Parsing \'<readFile(m)>\'");
您可能将此:|java+method:///MetricsTest/testMethod()|(23,1,<1,0>,<1,0>))
作为 URI 传递给 createAstFromFile,而这只是 MetricsTest.java
文件的一部分。我猜这就是问题所在。
要解决这个问题,您可以从 M3 模型中的 decls
关系中查找真正的源位置,然后使用 .top
覆盖整个文件。另一种方法是为 MetricsTest
class 构造一个 java+compilationUnit
URI,并将其提供给 createAstFromFile
函数,或者从 containment
关系中查找。
我最后做的是为每个文件创建一个 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;
}