在java代码库中自动为所有if / else / for / while等添加花括号
我希望减少大型遗留Java代码库中声纳违规的数量,似乎“快速获胜”将更新所有这些条件语句以具有大括号。 这似乎是一件容易的事情,我不明白为什么它不容易自动化。
有没有人知道可以像这样执行批量操作的工具? 或者为什么做这样的事情可能是一个坏主意,然后我花时间自己写点什么? 如果我自己写一个什么是最好的工具? 理想情况下,这是一种Java语言感知的东西,所以我不必处理格式化案例等。
顺便说一句,这条规则是不可协商的,所以这确实是最好的方法。
最简单的方法是使用Eclipse并在整个项目中单击“ Clean-up
。 在Clean-up
配置文件配置中,选择Code style
选项卡。 在那里,您可以选择Use blocks in if/while/for/do statements
为Always
。
首先在检查设置中启用Control flow statement without braces
。
IntelliJ Idea – >运行代码检查 – >快速修复(至少在商业版中有效)
虽然建议对遗留代码保持谨慎,但检测遗留代码中的错误也是一件好事……或者至少使错误更容易被发现。
让我们来看看Brian Agnew的疑难案例:
// Case #1 if (x) doMethodA(); doMethodB();
实际上,就JLS和Java编译器而言,这意味着
if (x) doMethodA(); doMethodB();
因此,当变换器将代码重写为:
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)并标记它们以进行更密切的代码检查。
这让我感到非常危险。 你有全面的unit testing覆盖率吗?
我可以看到一些立即困难的案例,例如
if (x) doMethodA(); doMethodB();
和
if (x) // doMethodA(); doMethodB();
是两个想到的,不能天真地处理(你应该有语言意识来解决这些问题)。 我不会尝试自动执行这样的任务,除非你有语言感知和可靠的工具,而是强制执行一个策略,当你因为其他原因更改代码时修改代码,并且可以在那个阶段通过unit testing断言代码覆盖在更改代码之前。
罗伯特在评论中说:“@ iira我也有兴趣听到这种真正的语言识别工具!”
对不起,挑逗。 为了挑逗的原因,检查我的生物。
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完全是从forms语法(在这种情况下是Java)中驱动的,并且不是在原始文本上操作,而是在抽象语法树上操作; 这也使得独立于布局。 (理解“阻止”,“表达”和“语句”是语法非终结符的规则可能很有用。
虽然它可能是一个快速的声纳胜利,但你正在做一些危险的事情。 建议的方法是仅在必须重新访问该代码时修复遗留代码。 这些一揽子方法可能会导致非常微妙的错误。 由于策略已经改变,您的管理团队需要了解这是一项艰巨的任务,并且应该保证所有未来的代码都是按照标准开发的。
如果您首先在编辑器设置中设置正确的编码样式,Intellij 2017将使用重新格式代码支持此function。
File -> Settings -> Editor -> Code Style -> Java -> Wrapping and Braces