【问题标题】:SonarQube OpenEdge custom rule to verify &IF preprocessor with ProparseSonarQube OpenEdge 自定义规则使用 Proparse 验证 &IF 预处理器
【发布时间】:2020-08-14 20:45:09
【问题描述】:

我正在尝试创建一个自定义插件,基于 Riverside OpenEdge plugin 及其版本的 Proparse 来创建一个有效 &IF 预处理器的规则。

此规则需要验证应用程序是否使用了已弃用的 &GLOBAL-DEFINE 值,如下所示:

/* "A" is the deprecated value of "opts" so I want to create a new ISSUE here */
&IF "{&opts}" = "A" &THEN
    MESSAGE "DEPRECATED CODE".
&ENDIF

&IF "{&opts}" > "A" &THEN
    MESSAGE "OK CODE".
&ENDIF

对于我扩展的这条规则,我尝试做这样的事情:

if (unit.getMacroGraph().macroEventList.stream().noneMatch(macro -> macro instanceof NamedMacroRef
        && ((NamedMacroRef) macro).getMacroDef().getName().equalsIgnoreCase("opts"))) {
    return;
}

TokenSource stream = unit.lex();
ProToken tok = (ProToken) stream.nextToken();

while (tok.getNodeType() != ABLNodeType.EOF_ANTLR4) {
    if (tok.getNodeType() == ABLNodeType.AMPIF) {
        // Verify node.
        System.out.println(tok);
    }

    tok = (ProToken) stream.nextToken();
}

但我不知道它是否是最好的验证方法(我根据其他来源的代码做了)并且它不起作用,因为下一个节点是一个空的“QSSTRING”。我是 Proparse 世界的新手,感谢任何帮助。

【问题讨论】:

    标签: sonarqube openedge


    【解决方案1】:

    首先,您必须知道 Proparse 不能访问预处理器的每个细节。也就是说,unit.getMacroGraph() 方法可以让您访问预处理器的可见部分,所以这是一个很好的起点。 如果您正在寻找给定预处理器变量的用法,您可以搜索指向正确 MacroDef 对象(使用 NamedMacroRef#getMacroDef()#getName())的 NamedMacroRef 实例和正确的值。

    在老式的 for-each 循环中:

    for (MacroRef ref : unit.getMacroSourceArray()) {
      if ((ref instanceof NamedMacroRef)) {
        if ("opts".equalsIgnoreCase(((NamedMacroRef) ref).getMacroDef().getName())
            && "A".equalsIgnoreCase(((NamedMacroRef) ref).getMacroDef().getValue())) {
          System.out.println("OPTS variable usage with value 'A' at file " + ref.getFileIndex() + ":" + ref.getLine());
        }
      }
    }
    

    关于这个文件:

    &global-define opts a
    &IF "{&opts}" = "A" &THEN
        MESSAGE "DEPRECATED CODE".
    &ENDIF
    &undefine opts
    &global-define opts b
    &IF "{&opts}" > "A" &THEN
        MESSAGE "OK CODE".
    &ENDIF
    

    这给出了:

    OPTS variable usage with value 'A' at file 0:2
    

    所以你无法访问表达式引擎,但我认为当前的 API 已经足够你想做的事情了。

    然后您可以通过 OpenEdgeProparseCheck#reportIssue() 报告 SonarQube 的问题

    【讨论】:

    • 您好@gilles-querret,谢谢您的回复。这里的情况是我需要验证比较值= "A " 而不是变量本身的值。该变量位于值为“B”的包含中,因此使用该包含编译的源代码仅包含 opts 变量的值“B”。
    • 预处理器表达式未在 AST 中公开,预处理器令牌在被 TokenStream 的下一层消耗后被丢弃(即,您不能像使用空格一样通过 getHiddenTokensBefore 访问它们)。所以现在,您必须使用 lex() 方法(如您的代码示例中所示),并查找 ABLNodeType.AMPIF。您可以查看PostLexer中的代码。
    • 如果您喜欢生活在最前沿,您可以尝试分支feature/PreprocessorExpression,其中 &IF 表达式可用作隐藏标记(如空格)
    猜你喜欢
    • 2018-02-08
    • 1970-01-01
    • 2017-07-25
    • 2017-07-07
    • 2018-05-25
    • 2014-04-22
    • 2017-12-01
    • 2017-04-11
    • 2018-02-18
    相关资源
    最近更新 更多