【问题标题】:automatically add curly brackets to all if/else/for/while etc. in a java code-base自动将大括号添加到 java 代码库中的所有 if/else/for/while 等
【发布时间】:2015-02-10 01:04:31
【问题描述】:

我想减少大型遗留 Java 代码库中的声纳违规次数,似乎“快速获胜”是将所有这些条件语句更新为带有大括号。这似乎是一件容易的事情,我不明白为什么它不容易自动化。

有人知道可以执行这样的批量操作的工具吗?或者为什么在我花时间自己写东西之前做这样的事情可能是个坏主意?如果我自己写一个,最好的工具是什么?理想情况下是 Java 语言感知的东西,这样我就不必处理格式化极端情况等。

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

【问题讨论】:

  • 工具应如何确定右括号的放置位置?
  • @gefai:这很容易。闭括号必须放在下一条语句的后面,就像编译器会放置它一样。声明者被定界为 bei ;或换行。评论已被过滤掉。
  • 你为什么不干脆关闭声纳规则?这真的是您代码库中的大问题吗?

标签: java formatting sonarqube


【解决方案1】:

首先在检查设置中启用Control flow statement without braces

IntelliJ Idea -> 运行代码检查 -> 快速修复(至少在商业版中有效)

【讨论】:

  • 不错,我来看看。在这种情况下,我可以定位整个“模块”吗?
  • 是的。 IntelliJ 有很多快速修复检查。你也可以将viable.equals("constant")改为"constant".equals(vriable),自动避免NPE。
  • 是的,constant.equals(variable) 模式很漂亮.. 很惊讶人们不经常使用它!
  • 这就像尤达大师会说话。这看起来很奇怪。
  • 在较新的版本中,这是在Analyze -> Run Inspection By Name -> Run Code Inspection
【解决方案2】:

最简单的方法是使用Eclipse 并在整个项目上单击Clean-up。在Clean-up 配置文件中选择Code style 选项卡。在那里你可以选择Use blocks in if/while/for/do statements作为Always

【讨论】:

  • 所以这可以作为单个操作针对整个代码库运行吗?我可以在它做事的时候把它关掉去喝杯咖啡吗?如果是这样,听起来是正确的答案!
  • 这取决于代码有多大以及你喝咖啡需要多长时间。但是,是的,这是整个代码库的单一操作。
  • 这至少会是一个“发泄”
  • 如果这对您来说可靠,那么它似乎是一个简单的解决方案,除非您不擅长喝咖啡。如果它不起作用,我知道真正的语言感知工具可以轻松可靠地做到这一点。
  • 在重新格式化之前更新,并在进行进一步更改之前签入。这将简化必要时撤销更改。
【解决方案3】:

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

让我们考虑一下 Brian Agnew 的疑难案例:

// Case #1
if (x) doMethodA(); doMethodB();

其实就JLS和Java编译器而言,这个的意思是

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

所以当transformer将代码重写为:

if (x) { 
    doMethodA();
}
doMethodB();

它并没有改变代码的含义,而是纠正了一个可能导致某人误读代码的问题,错过一个潜在的错误这已经在代码中了;即如果第二次调用应该是有条件的......

// Case #2
if (x) 
    // doMethodA();
    doMethodB();

再一次,当它被重写时,你应该得到:

 if (x) {
    // doMethodA();
    doMethodB();
 }

这和原来的意思一样。此外,这很可能反映了程序员的意图……如果要相信缩进的话。但是考虑一下:

// Case #2a
if (x) 
    // doMethodA();
doMethodB();

当我们将其重写为

if (x) {
    // doMethodA();
    doMethodB();
}

代码的实际含义没有改变,不正确的缩进不再会误导。如果程序员决定取消第一次调用的注释,他可能没有意识到之前的注释已经产生了意想不到的后果。 (证据在我们已经“修复”的原始缩进中。)但是有一个潜在的解决方案;见下文。


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

现在,如果我们让转换器更智能,它可以检测原始缩进指示可能存在错误的一些情况(如上面的情况 #1 和 #2a)并标记它们以进行更仔细的代码检查.

【讨论】:

  • 我特别喜欢这个示例,因为它显示了“使用代码”而不是“查看”的问题。
【解决方案4】:

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

我可以看到一些直接困难的案例,例如

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

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

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

【讨论】:

  • 嗨,是的,出于这样的原因,我特别喜欢某种语言感知工具。我们确实有单元测试等,我们可能会通过某种团队审查流程来确认更改是否正常……
  • @robert 这不是语言感知工具的问题,而是人们编写编译器正确代码而不是策略正确代码的问题
【解决方案5】:

Robert 在评论中说:“@ira 我也有兴趣了解这个真正的语言感知工具!”

对不起,逗弄了。对于取笑的原因,请查看我的简历。

Untease:请参阅 http://www.semanticdesigns/Products/DMS/DMSToolkit.html 作为基础引擎和 http://www.semanticdesigns.com/Products/FrontEnds/JavaFrontEnd.html。这对组合构成了一个完全语言感知的源到源程序转换系统。

可以使用具有两个源到源转换规则的 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)驱动,并且不是在原始文本上运行,而是在抽象语法树上运行;这也使得独立于布局。 (了解“块”、“表达式”和“语句”是语法非终结符的规则可能很有用。

【讨论】:

  • 好的,明白了。似乎是一个不错的工具,我很惊讶没有更多的语言感知工具可用。我为这种事情搜索了很多,但没有任何结果(可能想做一些 SEO)。无论如何,以及上面的其他建议,我会看看这个,谢谢!
  • 记不清了 ..“java 搜索和替换” ..“java 正则表达式”等,正如你所期望的那样,它返回了使用 java 执行这些操作的信息 .. 相当拥挤的命名空间!
  • 这些短语非常模糊,并且真正专注于 Java 代码更改以外的内容。 Java 美化?改造?重构?是的,很难让 SEO 正确。
【解决方案6】:

如果您首先在编辑器设置中设置正确的编码样式,Intellij 2017 通过重新格式化代码支持此功能。

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

【讨论】:

    【解决方案7】:

    虽然这可能是一个快速的声纳胜利,但你正在做一些危险的事情。推荐的方法是仅在必须重新访问该代码时修复遗留代码。这些一揽子方法可能会导致非常微妙的错误。因为政策已经改变,您的管理团队需要了解这是一项艰巨的任务,并且应该保证所有未来的代码都按照标准开发。

    【讨论】:

    • 一个真正的语言感知工具会让这变得不危险。
    【解决方案8】:

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

    有趣。

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

    这个练习的价值主张(至少可以说)是可疑的。 “遗留代码库”通常是一种礼貌的说法,即代码应该被丢弃并重写......但你负担不起。但是,显然,您可以负担得起纠正丢失的大括号的费用,这不太可能对可维护性产生任何真正的影响。

    正如之前的答案所指出的那样。如果您正确地自动执行此样式校正:

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

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

    但如果您手动进行样式校正:

    • 您可能会注意到一些错误。这些可以添加到您的问题跟踪器中,以便进一步诊断和修复。

    • 您也有可能引入新的错误。如果我们假设现有的单元/系统不存在或质量低下(这是一个遗留代码库),那么这些新错误很有可能未被发现。

    现在概括 Sonar 检测到的与样式相关的错误。

    总而言之,修复遗留代码库中所有样式错误的整个过程(IMO)如果是自动化的,在很大程度上是浪费时间,如果是手动的,则可能存在风险。

    应该是可以协商的。您应该能够告诉管理层这些问题...

    【讨论】:

    • 这似乎更像是一个扩展评论,而不是实际尝试回答问题。不过,我同意这可能是XY problem
    • 试图解释为什么他可能不应该这样做。因此,为什么所有其他直接回答该问题的答案都是有问题的。对我来说,这是对问题的回答,尽管不是字面上的回答。
    猜你喜欢
    • 1970-01-01
    • 2021-03-15
    • 2012-02-02
    • 1970-01-01
    • 2013-12-18
    • 2019-01-08
    • 1970-01-01
    相关资源
    最近更新 更多