Eclipse has specific junit/guava knowledge in code analysis
While checking my work project for warnings I noticed that Eclipse spotted some dead code after a JUnit assertNotNull
. Some testing and discussion on twitter with Roy van Rijn led me to tinker a bit with Eclipse's dead code analysis. First the code in question:
Appointment appointment1 = null;
Appointment appointment2 = null;
for(Appointment appointment : appointments) {
if(appointment.getSomething() == 1)
appointment1 = appointment;
if(appointment.getSomething() == 2)
appointment2 = appointment;
}
assertNotNull(appointment1);
assertNotNull(appointment2);
if(appointment1 == null || appointment2 == null) {
throw IllegalStateException();
}
Eclipse generates a warning on line 11 stating that both appointment1 and appointment2 are both never null at that point. This led me to believe that Eclipse has specific knowledge of JUnit, a point that Roy contests.
Roy's assertion was that Eclipse did a full code path analysis of the call sequence, as JUnit ultimately throws an exception in this case, which could be proven by static analysis.
A short test shows that in fact Eclipse does treat assertNotNull
as a special case, and does not perform a full call sequence analysis:
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
public class Test {
public void deadCodeAfterAssertNotNull() {
assertNotNull(null);
fail("");
}
public void noDeadCodeAfterFail() {
fail("");
assertNotNull(null);
}
}
Eclipse generates a warning for dead code at line 7, but not at line 12, however assertNotNull
ultimately calls fail(String)
. Thus my conclusion that Eclipse does in fact have a special case for detecting assertNotNull
.
Update: It appears that the static analysis checker also has built in support for Guava's Preconditions
:
public void deadCodeAfterGuavaAssertion() {
Preconditions.checkNotNull(null);
System.out.println("Dead code");
}
The compiler flags line 3 as dead code. However:
public void noDeadCodeAfterMyFail() {
myFail();
System.out.println("No dead code");
}
private final void myFail() {
throw new RuntimeException();
}
Does not make Eclipse's compiler conclude that line 3 is dead code.