自动将花括号添加到java代码库中的所有if/else/for/while等

自动将花括号添加到java代码库中的所有if/else/for/while等,java,formatting,sonarqube,Java,Formatting,Sonarqube,我想减少大型遗留java代码库中sonar违规的数量,而将所有这些条件语句更新为大括号似乎是一个“快速胜利”。这似乎是一件容易做到的事情,我不明白为什么它不容易自动化 有人知道有一种工具可以执行这样的批量操作吗?或者为什么在我自己去写东西之前做这样的事情可能是个坏主意?如果我自己写一本,那么最好的工具是什么?理想情况下,它应该是java语言感知的,这样我就不必处理格式化角落案例之类的事情 顺便说一句,该规则是不可协商的,因此这确实是最好的方法。最简单的方法是使用并在整个项目上单击清理。在清理配置

我想减少大型遗留java代码库中sonar违规的数量,而将所有这些条件语句更新为大括号似乎是一个“快速胜利”。这似乎是一件容易做到的事情,我不明白为什么它不容易自动化

有人知道有一种工具可以执行这样的批量操作吗?或者为什么在我自己去写东西之前做这样的事情可能是个坏主意?如果我自己写一本,那么最好的工具是什么?理想情况下,它应该是java语言感知的,这样我就不必处理格式化角落案例之类的事情


顺便说一句,该规则是不可协商的,因此这确实是最好的方法。

最简单的方法是使用并在整个项目上单击
清理
。在
清理
配置文件配置中,选择
代码样式
选项卡。在那里,您可以选择if/while/for/do语句中的
使用块作为
始终

这让我觉得可能非常危险。你有全面的单元测试覆盖范围吗

我可以看到一些很难立即解决的案例

if (x) doMethodA(); doMethodB();


有两个问题让人想到,不能天真地处理(你应该有语言意识来解决这些问题)。除非你有语言意识和可靠的工具,否则我不会尝试自动化这样一项任务,而是强制执行一项策略,当你出于其他原因更改代码时,你可以修改代码,并且可以在更改代码之前通过单元测试断言代码覆盖率。

虽然这可能是sonar的快速胜利,但你正在做一些危险的事情。建议的方法是仅在必须重新访问遗留代码时修复该代码。这些笼统的方法可能会导致非常微妙的错误。由于政策已发生变化,您的管理团队需要了解这是一项艰巨的任务,并应确保所有未来的代码都按照标准进行开发。

首先在检查设置中启用
无括号的控制流语句


IntelliJ Idea->Run Code Inspection->Quick Fix(至少在商业版本中有效)

虽然建议谨慎使用遗留代码,但检测遗留代码中的错误也是一件好事。。。或者至少让bug更容易被发现

让我们来考虑Brian Agnew的疑难案件:

// Case #1
if (x) doMethodA(); doMethodB();
事实上,就JLS和Java编译器而言,这意味着

因此,当转换器将代码重写为:

if (x) { 
    doMethodA();
}
doMethodB();
它不是改变代码的含义,而是纠正一个可能导致某人误读代码、错过代码中已经存在的潜在错误的问题;i、 e.如果第二次呼叫是有条件的

// Case #2
if (x) 
    // doMethodA();
    doMethodB();
同样,当重写时,您应该得到:

 if (x) {
    // doMethodA();
    doMethodB();
 }
这和原作的意思是一样的。此外,这很可能反映了程序员的意图。。。如果压痕是可信的。但是考虑一下:

// Case #2a
if (x) 
    // doMethodA();
doMethodB();
当我们把它改写为

if (x) {
    // doMethodA();
    doMethodB();
}
代码的实际含义不会改变,错误的缩进也不会再误导用户。如果程序员决定取消对第一个调用的注释,他可能没有意识到前面的注释有一个意外的结果。(原始压痕中的证据表明我们已经“修复了”。)但有一个潜在的解决方案;见下文


如果我们假设代码转换工具在正确理解Java的语法和语义的情况下运行,那么它不会破坏任何尚未破坏的东西,并且(在一定程度上)会使任何现有的破坏对阅读代码的人来说更加明显。对我来说,这是一个零风险的胜利,即使对于遗留代码也是如此

现在,如果我们让transformer变得更智能,它可以检测到一些原始缩进指示可能存在错误的情况(如上面的案例1和案例2a),并标记它们以便更仔细地检查代码。

Robert在评论中说:“@ira我也有兴趣听到这个真正有语言意识的工具!”

对不起,我开玩笑了。关于这个笑话的原因,请查看我的简历

未经检验:视为基础发动机。这对组合构成了一个完全支持语言的源到源程序转换系统

我们可以使用DMS完成这项任务,DMS有两个源到源转换规则:

  rule curlies_for_then_statement:(c:expression, s: statement}: 
             statement->statement
       " if (\c) \s " -> "if (\c) { \s } ";


  rule curlies_for_else_statement:(c:expression, b: block, s: statement}:
              statement->statement
       " if (\c) \b else \s " -> "if (\c) \b else { \s } ";

这是可靠的,因为DMS完全由形式语法驱动(在本例中为Java),并且不是对原始文本进行操作,而是对抽象语法树进行操作;这也使得在独立的布局。(理解“block”、“expression”和“statement”是语法非终结符的规则可能很有用。

Intellij 2017通过重新格式化代码来支持这一点,前提是您首先在编辑器设置中设置了正确的编码样式

File -> Settings -> Editor -> Code Style -> Java -> Wrapping and Braces

顺便说一句,这个规则是不可协商的,所以这确实是最好的方法

有趣

您有一个充满样式错误的遗留代码库,必须修复样式错误是不可协商的

这个练习的价值主张(至少可以说)是可疑的。“遗留代码库”通常是一种礼貌的说法,表示应该扔掉并重写代码……但你负担不起。然而,显然,你可以花费钱纠正缺少的大括号,这不太可能对可维护性产生任何实际影响

正如前面的答案所指出的。如果您正确地自动化了此样式更正:

  • 它实际上不会修复任何bug,但也不会引入任何新bug

  • 它可能会删除作为现有bug标志的“线索”(例如可疑的缩进)

但如果手动执行样式更正:

  • 您可能会注意到一些bug。这些bug可以添加到您的问题跟踪器中,以便
      rule curlies_for_then_statement:(c:expression, s: statement}: 
                 statement->statement
           " if (\c) \s " -> "if (\c) { \s } ";
    
    
      rule curlies_for_else_statement:(c:expression, b: block, s: statement}:
                  statement->statement
           " if (\c) \b else \s " -> "if (\c) \b else { \s } ";
    
    File -> Settings -> Editor -> Code Style -> Java -> Wrapping and Braces