Skip to content

Commit

Permalink
In delombok, we mark the AST as changed if we remove an annotation; t…
Browse files Browse the repository at this point in the history
…his fixes the issue where delombok would leave lombok annotations in the file if that annotation had no actual effect (such as @getter on a field if there is an explicit getX method for that field).

issue #443: delombok would screw up @SneakyThrows on methods or constructors with empty bodies. Now we generate warnings for this.
  • Loading branch information
rzwitserloot committed Mar 12, 2013
1 parent 9400f39 commit cb9b907
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 7 deletions.
24 changes: 20 additions & 4 deletions src/core/lombok/eclipse/handlers/HandleSneakyThrows.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
Expand Down Expand Up @@ -147,7 +149,21 @@ private void handleMethod(EclipseNode annotation, AbstractMethodDeclaration meth
return;
}

if (method.statements == null) return;
if (method.statements == null || method.statements.length == 0) {
boolean hasConstructorCall = false;
if (method instanceof ConstructorDeclaration) {
ExplicitConstructorCall constructorCall = ((ConstructorDeclaration) method).constructorCall;
hasConstructorCall = constructorCall != null && !constructorCall.isImplicitSuper() && !constructorCall.isImplicitThis();
}

if (hasConstructorCall) {
annotation.addWarning("Calls to sibling / super constructors are always excluded from @SneakyThrows; @SneakyThrows has been ignored because there is no other code in this constructor.");
} else {
annotation.addWarning("This method or constructor is empty; @SneakyThrows has been ignored.");
}

return;
}

Statement[] contents = method.statements;

Expand All @@ -160,9 +176,9 @@ private void handleMethod(EclipseNode annotation, AbstractMethodDeclaration meth
}

private Statement buildTryCatchBlock(Statement[] contents, DeclaredException exception, ASTNode source, AbstractMethodDeclaration method) {
int methodStart = method.bodyStart;
int methodEnd = method.bodyEnd;
long methodPosEnd = methodEnd << 32 | (methodEnd & 0xFFFFFFFFL);
int methodStart = method.bodyStart;
int methodEnd = method.bodyEnd;
long methodPosEnd = ((long) methodEnd) << 32 | (methodEnd & 0xFFFFFFFFL);

TryStatement tryStatement = new TryStatement();
setGeneratedBy(tryStatement, source);
Expand Down
19 changes: 17 additions & 2 deletions src/core/lombok/javac/handlers/HandleSneakyThrows.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,20 @@ private void handleMethod(JavacNode annotation, JCMethodDecl method, Collection<
return;
}

if (method.body == null) return;
if (method.body.stats.isEmpty()) return;
if (method.body == null || method.body.stats.isEmpty()) {
generateEmptyBlockWarning(methodNode, annotation, false);
return;
}

final JCStatement constructorCall = method.body.stats.get(0);
final boolean isConstructorCall = isConstructorCall(constructorCall);
List<JCStatement> contents = isConstructorCall ? method.body.stats.tail : method.body.stats;

if (contents == null || contents.isEmpty()) {
generateEmptyBlockWarning(methodNode, annotation, true);
return;
}

for (String exception : exceptions) {
contents = List.of(buildTryCatchBlock(methodNode, contents, exception, annotation.get()));
}
Expand All @@ -99,6 +106,14 @@ private void handleMethod(JavacNode annotation, JCMethodDecl method, Collection<
methodNode.rebuild();
}

private void generateEmptyBlockWarning(JavacNode methodNode, JavacNode annotation, boolean hasConstructorCall) {
if (hasConstructorCall) {
annotation.addWarning("Calls to sibling / super constructors are always excluded from @SneakyThrows; @SneakyThrows has been ignored because there is no other code in this constructor.");
} else {
annotation.addWarning("This method or constructor is empty; @SneakyThrows has been ignored.");
}
}

private boolean isConstructorCall(final JCStatement supect) {
if (!(supect instanceof JCExpressionStatement)) return false;
final JCExpression supectExpression = ((JCExpressionStatement) supect).expr;
Expand Down
1 change: 1 addition & 0 deletions src/core/lombok/javac/handlers/JavacHandlerUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ public static void deleteAnnotationIfNeccessary(JavacNode annotation, Class<? ex
return;
}

parentNode.getAst().setChanged();
deleteImportFromCompilationUnit(annotation, annotationType.getName());
}

Expand Down
6 changes: 5 additions & 1 deletion website/features/SneakyThrows.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ <h3>Small print</h3><div class="smallprint">
statement in a try/catch block with just <code>e.printStackTrace()</code> in the catch block. This is so spectacularly non-productive
compared to just sneakily throwing the exception onwards, that Roel and Reinier feel more than justified in claiming that the
checked exception system is far from perfect, and thus an opt-out mechanism is warranted.
</p>
</p><p>
If you put <code>@SneakyThrows</code> on a constructor, any call to a sibling or super constructor is <em>excluded</em> from the <code>@SneakyThrows</code> treatment. This is a
java restriction we cannot work around: Calls to sibling/super constructors MUST be the first statement in the constructor; they cannot be placed inside try/catch blocks.
</p><p>
<code>@SneakyThrows</code> on an empty method, or a constructor that is empty or only has a call to a sibling / super constructor results in no try/catch block and a warning.
</div>
</div>
<div class="footer">
Expand Down

0 comments on commit cb9b907

Please sign in to comment.