gpt4 book ai didi

java - 为自定义语法创建自定义代码分析规则,并进行测试: howto?

转载 作者:行者123 更新时间:2023-12-02 04:55:49 27 4
gpt4 key购买 nike

基于最小的 C 解析器示例,并使用以下依赖项:

compile(group: "org.codehaus.sonar.sslr", name: "sslr", version: "1.20");
compile(group: "org.codehaus.sonar.sslr", name: "sslr-testing-harness",
version: "1.20");
compile(group: "org.codehaus.sonar.sslr", name: "sslr-examples",
version: "1.20");

我用完全无用的标记创建了一个完全无用的语法,并运行了一个完全无用的 main() ,它工作得很好(警告:大量代码):

// Operators.java
@ParametersAreNonnullByDefault
public enum Operators
implements TokenType
{
ADD("+");

private final String value;

Operators(final String value)
{
this.value = value;
}


@Override
public String getName()
{
return name();
}

@Override
public String getValue()
{
return value;
}

@Override
public boolean hasToBeSkippedFromAst(final AstNode node)
{
return false;
}
}

// NumLiteral.java
@ParametersAreNonnullByDefault
public enum NumLiteral
implements TokenType
{
LITERAL;

@Override
public String getName()
{
return name();
}

@Override
public String getValue()
{
return name();
}

@Override
public boolean hasToBeSkippedFromAst(final AstNode node)
{
return false;
}
}

// ExampleLexer.java
public final class ExampleLexer
{
private ExampleLexer()
{
throw new Error("nice try!");
}

public static Lexer create()
{
return Lexer.builder()
.withChannel(regexp(NumLiteral.LITERAL, "\\d++"))
.withChannel(new PunctuatorChannel(Operators.values()))
.build();
}
}

// ExampleGrammar.java
public enum ExampleGrammar
implements GrammarRuleKey
{
EXPRESSION,
;

public static Grammar create()
{
final LexerfulGrammarBuilder builder = LexerfulGrammarBuilder.create();

builder.rule(EXPRESSION).is(builder.sequence(NumLiteral.LITERAL,
Operators.ADD, NumLiteral.LITERAL));

builder.setRootRule(EXPRESSION);

return builder.build();
}
}

// ExampleParser.java
public final class ExampleParser
{
private ExampleParser()
{
throw new Error("nice try!");
}

public static Parser<Grammar> create()
{
return Parser.builder(ExampleGrammar.create())
.withLexer(ExampleLexer.create())
.build();
}
}

// ExampleToolkit.java
public final class ExampleToolkit
{
private static final class ExampleConfigurationModel
extends AbstractConfigurationModel
{
@Override
public Parser doGetParser()
{
return ExampleParser.create();
}

@Override
public List<Tokenizer> doGetTokenizers()
{
return Collections.emptyList();
}

@Override
public List<ConfigurationProperty> getProperties()
{
return Collections.emptyList();
}
}

public static void main(final String... args)
{
final ConfigurationModel model = new ExampleConfigurationModel();
final Toolkit toolkit = new Toolkit("foo", model);
toolkit.run();
}
}

这显示了一个窗口,我可以输入文本,它可以正确标记等。

但是,为了让这个东西不再那么无用,现在我想对这一切实现一个规则。我做了程序一:

public final class ExampleRule
extends SquidCheck<Grammar>
{
@Override
public void init()
{
subscribeTo(NumLiteral.LITERAL);
}

@Override
public void visitNode(final AstNode astNode)
{
}
}

规则的代码还没写;但这不是重点。

重点是:我该如何测试规则?

这意味着我需要能够:

  • 用语法解析输入;
  • 将我的测试规则注册到标记化解析结果;
  • 检查我的规则是否按照我想要的方式运行。

不幸的是, Sonar 文档在这三点上都很糟糕;虽然已有语言的现有代码,但不存在指导您完成自己完成此操作的过程的文档。

那么,如何测试上述内容,更重要的是,如何进行测试,以便在扩展语法本身时可以扩展测试?

最佳答案

由于文档充其量是粗制滥造,我决定查看源代码,发现你只是使用

AstNode a = ExampleParser.create().parser("source code to parse");

或者

AstNode a = ExampleParser.create().parser(new File("path/to/source"));

现在您可以直接在AstNode上使用您的ExampleRule.visitNode你到了上面。但这样做的问题是它不会像预期的 API 那样递归,因为您需要使用 AstWalker.walkAndVisit这隐藏在实现中。

现在在旧版本中,为了遍历您的 AstNode,您需要使用 AstScanner 类来为您执行上述步骤。您可以像这样设置 AstScanner:

SquidAstVisitorContextImpl<Grammar> savci = new SquidAstVisitorContextImpl<Grammar>(new SourceProject("Custom Grammar"));
AstScanner.Builder b = AstScanner.builder(savci);

b.setBaseParser(ExampleParser.create());
b.setCommentAnalyser(new CommentAnalyser {
@override
public bool isBlank(String line) {
return true;
}
@override
public String getContents(String comment) {
return "";
}
});
b.setFileMetric(FILES); // I am not sure what a 'Metric' is as both the documentation and source are unclear on that, you may have to experiment with this value.

b.withSquidAstVisitor(new ExampleRule());

AstScanner<Grammar> as = b.build();
as.scanFile(new File("path/to/source"));

然后,要检查扫描仪收集的内容,您只需使用 as.getIndex() 返回 org.sonar.squid.api.SourceCodeSearchEngine 的实例。我会提供有关该部分的更多信息,但我目前没有时间这样做,我可能会稍后编辑我的答案并跟进。

对于最新版本,似乎像传统访问者模式一样正确遍历 ast 的唯一方法是使用 AstWalker类。

由于我对 Sonar 这个框架不够熟悉,所以我对其测试工具了解不多,尽管这对于一些粗略的测试例程来说应该足够了。

关于java - 为自定义语法创建自定义代码分析规则,并进行测试: howto?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28784948/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com