如何检测if(true)和其他重构问题? [英] How to detect if(true) and other refactoring issues?

查看:121
本文介绍了如何检测if(true)和其他重构问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java中,当使用现代 IDE时,通常会内联变量值并执行繁重的重构,例如,可以转换此源代码。

It is common in java, when using "modern" IDEs, to inline variable values and perform heavy refactoring that can, as an example, transform this source code

boolean test = true;
//...
if(test) {
    //...
}

进入此代码

if(true) {
    //...
}

显然,可以简化此代码,但是Eclipse无法执行

Obviously, this code can be simplified, but Eclipse won't perform that simplification for me.

那么,有什么方法(使用Eclipse或什至更好的maven)可以检测并(可能)简化该代码? (如果这样的工具能够检测到其他错误的构造,例如empty for循环,显然会更好。)

So, is there any way (using Eclipse or - even better - maven) that can detect and (possibly) simplify that code ? (it would be obviously way better if such a tool was able to detect other wrong constructs like empty for loops, ...)

推荐答案

您想要的是一个程序转换系统(PTS)。

What you want is a Program Transformation system (PTS).

这些工具可读取源代码,构建编译器数据结构(几乎总是至少包含AST),对编译器数据结构进行自定义分析和修改,然后重新生成源文本(用于修改后的程序)。

These are tools that read source code, build compiler data structures (almost always including at least an AST), carry out customized analysis and modification of the compiler data structures, and then regenerate source text (for the modified program) from those modified data structures.

许多PTS允许您将更改的代码直接以源到源的形式表示为规则,表示为这种规则语言的目的是让您更轻松地表达复杂的代码转换。

Many of the PTS will allow you express changes to code directly in source-to-source form as rules, expressed in terms of the language syntax, metavariables, etc. The point of such a rule language is to let you express complex code transformations more easily.

我们的DMS软件再造工具包就是这样的PTS 。您可以使用以下简单规则轻松地使用包含布尔常量的布尔表达式简化代码:

Our DMS Software Reengineering Toolkit is such a PTS. You can easily simplify code with boolean expressions containing boolean constants with the following simple rules:

default domain Java~v7;

simplify_not_true(): primary -> primary
     " ! true" -> "false";

simplify_not_false(): primary -> primary
     " ! false" -> "true";

simplify_not_not(x: primary): primary -> primary
     " ! ! \x " ->  "\x";

simplify_and_right_true(x: term): conjunction -> conjunction ;
   " \x && true " ->  "\x";

simplify_and_left_true(x: term): conjunction -> conjunction ;
   " true && \x " ->  "\x";

simplify_and_left_false(x: term): conjunction -> conjunction ;
   " false && \x " ->  "false";

simplify_and_right_false(x: term): conjunction -> conjunction ;
   " \x && false " ->  "false"
   if no_side_effects_or_exceptions(x);  -- note additional semantic check here

simplify_or_right_false(x: term): disjunction -> disjunction ;
   " \x || false " ->  "\x";

simplify_or_left_false(x: term): disjunction -> disjunction ;
   " false || \x " ->  "\x";

simplify_or_right_true(x: term): disjunction -> disjunction ;
   " \x || true " ->  "true"
   if no_side_effects_or_exceptions(x);

simplify_or_left_true(x: term): disjunction -> disjunction ;
   " true || \x " ->  "true";

(语法名称 term, primary, conjunction, disjunction直接

(The grammar names "term", "primary", "conjunction", "disjunction" are directly from the BNF used to drive Java source code parsing.)

这些规则将一起使用包含已知布尔常量
的布尔表达式,有时将它们简化为

These rules together will take boolean expressions involving known boolean constants, and simplify them down sometimes to simply "true" or "false".

要消除表达式为布尔常量的if条件,可以这样写:

To eliminate if-conditionals whose expressions are boolean constants one would write these:

 simplify_if_true(b: block): statement -> statement
    " if (true) \b" -> " \b ";

 simplify_if_false(b: block): statement -> statement
    " if (false) \b" -> ";"  -- null statement

加上布尔简化,这两个规则将摆脱显然为true或true的条件显然是错误的条件。

Together with boolean simplification, these two rules would get rid of conditionals for obviously true or obviously false conditionals.

要执行的操作比较复杂,因为您希望将信息从程序中的一个地方传播到另一个可能远离的地方。 。为此,您需要进行数据流分析,显示值可以从其赋值到达的地方:

To do what you want is bit more complicated, because you wish to propagate information from one place in the program, to another place possibly "far away". For that you need what amounts to a data flow analysis, showing where values can reach from their assignments:

default domain Java~v7;

rule propagate_constant_variables(i:IDENTIFIER): term -> term
     " \i " -> construct_reaching_constant()
     if constant_reaches(i);

此规则取决于提供数据流事实的内置分析和自定义
接口检查此数据的函数 constant_reaches。
(DMS在C,C ++,Java和COBOL中具有此功能,并支持在其他语言中使用它;据我所知,维基百科文章中提到的其他PTS都没有这些可用的事实)。它还依赖于自定义构造函数 contruct_reaching_constant来构建包含到达常数的原始树节点。这些将使用DMS的底层元编程语言进行编码,并且需要数十行代码。同样,前面讨论的特殊条件 no_side_effects_or_exceptions;这可能会更加复杂,因为有关副作用的问题可能需要对整个程序进行分析。

This rule depends on a built-in analysis providing data flow facts and a custom interface function "constant_reaches" that inspects this data. (DMS has this for C, C++, Java and COBOL and support for doing it for other languages; to my knowledge, none of the other PTS mentioned in the Wikipedia article have these flow facts available). It also depends on a custom contructor "contruct_reaching_constant" to build a primitive tree node containing a reaching constant. These would be coded in DMS's underlying metaprogramming langauge and require a few tens of lines of code. Similarly the special condition discussed earlier "no_side_effects_or_exceptions"; this can be a lot more complex as the question about side effects may require an analysis of the full program.

有些Clang等工具可以将C ++代码转换为某些代码在一定程度上,但是Clang没有PTS那样的重写规则,它实际上是一个带有附加挂钩的编译器。

There are tools such a Clang that can transform C++ code to some extent, but Clang does not have rewrite rules as PTS do, it is really a compiler with additional hooks.

这篇关于如何检测if(true)和其他重构问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆