javac warns that catch blocks are unreachable
rogerkeays opened this issue · comments
Test code
try {
assert new String(STARS, "UTF-8").equals("***");
} catch (UnsupportedEncodingException e) {} // okay, never thrown
compiler output
Test.java:18: warning: unreachable catch clause
} catch (UnsupportedEncodingException e) {} // okay, never thrown
^
thrown types have already been caught
other tests show that catch blocks are executed correctly:
for (int i = 0; i < 1; i++) {
try { throw new Exception(); } catch (Exception e) { if (1 == 1) break; }
assert false;
}
- this warning only appears for checked exceptions
- in github JDK, the source is Flow.FlowAnalyzer.checkCaughtType() (line 1693)
- this doesn't exist in older compilers, it is just Flow.checkCaughtType()
- we can override Flow.analyzeTree(), which creates the FlowAnalyzer, but the implementation differs too much between versions
- we can override Log.warning(), but the signature has changed between javac versions
Log.warning() is stable since java 9, so we can override Log.warning:
// suppress invalid warnings
@Override
public void warning(DiagnosticPosition pos, Warning warningKey) {
if (!warningKey.key().startsWith("compiler.warn.unreachable.catch")) {
super.warning(pos, warningKey);
}
}
and update the context in the plugin init:
Object log = instance(reload(UncheckedLog.class, context), context);
inject(JavaCompiler.class, "log", log, context);
inject(Flow.class, "chk", chk, context);
inject(Flow.class, "log", log, context);