Code analyzer catching errors

by Alexander Kogtenkov (modified: 2017 Mar 26)

At the time of this writing the code analyzer tool listed in EiffelStudio as Eiffel Inspector (in menu View | Tools) is not mature enough for everyday use, but it moves in this direction, and several issues that it detects should be sufficiently good starting from 17.05 release.

Still, until recently I was looking at it mostly as at a tool to check code style: that all features have comments, that these comments are terminated with a period or a question mark, that there are no redundant parentheses or nested conditional instructions that can be combined into a single one and alike.

From time to time I also got Variable is assigned a value that is never used. Usually there were two scenarios. In the first one the value was not used indeed, so the assignment instruction or the creation instruction where this variable was a target, were subject to removal from the code. In the second one there was either a call to a query with a side effect: not_used := x.do_something_and_return_a_value_not_used_here
or a creation instruction where all work was performed in a creation procedure: create helper.do_all_the_work (something)
The assignment instruction was easily replaced with x.do_something_and_return_a_value_not_used_here.do_nothing
provided that the returned value was attached (and that was true in most cases).

The creation instruction was replaced with ;(create {HELPER_CLASS}.do_all_the_work (something)).do_nothing
As you can see, this was mostly code style again, nothing fancy. Until the warning was reported for the code of a FSM (finite state machine) that looked like inspect state ... when preliminary_state then ... -- process input if something_bad_happens then ... -- set data to predefined values state := error_state -- (*) end state := normal_state when normal_state then ... -- process input if something_bad_happens then ... -- set data to predefined values state := error_state end ...
The line of interest is marked with -- (*). The new value of the variable state set at this line is immediately discarded by the assignment after the conditional instruction. However, the code did not fall into either of the scenarios described earlier: the right-hand side did not have any side effect, still the instruction was not useless because there was an error to be reported.

Looking at the code for normal_state I realized that this is most probably is a variant of copy-paste coding with a slight variation that from preliminary_state the machine should go to normal_state. Except that it should also go to error_state if something bad happens.

Clearly, the issue was in incorrect order of the assignment instructions: state := normal_state should have come before the conditional instruction that tests that everything went fine.

Although there were no examples that demonstrated the issue, I was able to construct one to confirm that there was a bug indeed. Correcting the order of the instructions fixed it and the fix will be included in the forthcoming EiffelStudio 17.05.

The interesting part of the story is that the bug was found just by running the code analysis tool, not in the field, not by experiencing the issue in practice before fixing it.

Have you ever used the tool? If not, it might be worth giving it a try when EiffelStudio 17.05 is out.