diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/lombok/NonNull.java | 13 | ||||
-rw-r--r-- | src/core/lombok/core/configuration/NullCheckExceptionType.java | 24 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java | 37 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/HandleNonNull.java | 37 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleNonNull.java | 25 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/JavacHandlerUtil.java | 56 |
6 files changed, 109 insertions, 83 deletions
diff --git a/src/core/lombok/NonNull.java b/src/core/lombok/NonNull.java index caf6ed05..ba8c24a4 100644 --- a/src/core/lombok/NonNull.java +++ b/src/core/lombok/NonNull.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2013 The Project Lombok Authors. + * Copyright (C) 2009-2019 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,16 +30,7 @@ import java.lang.annotation.Target; /** * If put on a parameter, lombok will insert a null-check at the start of the method / constructor's body, throwing a * {@code NullPointerException} with the parameter's name as message. If put on a field, any generated method assigning - * a value to this field will also produce these nullchecks. - * <p> - * Note that any annotation named {@code NonNull} with any casing and any package will result in nullchecks produced for - * generated methods (and the annotation will be copied to the getter return type and any parameters of generated methods), - * but <em>only</em> this annotation, if present on a parameter, will result in a null check inserted into your otherwise - * handwritten method. - * - * WARNING: If the java community ever does decide on supporting a single {@code @NonNull} annotation (for example via JSR305), then - * this annotation will <strong>be deleted</strong> from the lombok package. If the need to update an import statement scares - * you, you should use your own annotation named {@code @NonNull} instead of this one. + * a value to this field will also produce these null-checks. */ @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE}) @Retention(RetentionPolicy.CLASS) diff --git a/src/core/lombok/core/configuration/NullCheckExceptionType.java b/src/core/lombok/core/configuration/NullCheckExceptionType.java index c4bb71f2..d226c0a8 100644 --- a/src/core/lombok/core/configuration/NullCheckExceptionType.java +++ b/src/core/lombok/core/configuration/NullCheckExceptionType.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2018 The Project Lombok Authors. + * Copyright (C) 2014-2019 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,27 +22,27 @@ package lombok.core.configuration; -@ExampleValueString("[NullPointerException | IllegalArgumentException]") +@ExampleValueString("[NullPointerException | IllegalArgumentException | Assertion]") public enum NullCheckExceptionType { ILLEGAL_ARGUMENT_EXCEPTION { - public String toExceptionMessage(String fieldName) { - return fieldName + " is marked @NonNull but is null"; - } - @Override public String getExceptionType() { return "java.lang.IllegalArgumentException"; } }, NULL_POINTER_EXCEPTION { - @Override public String toExceptionMessage(String fieldName) { - return fieldName + " is marked @NonNull but is null"; - } - - public String getExceptionType() { + @Override public String getExceptionType() { return "java.lang.NullPointerException"; } + }, + ASSERTION { + @Override public String getExceptionType() { + return null; + } }; - public abstract String toExceptionMessage(String fieldName); + public String toExceptionMessage(String fieldName) { + return fieldName + " is marked non-null but is null"; + } + public abstract String getExceptionType(); } diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 78b11873..010dc9d8 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -66,6 +66,7 @@ import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference; +import org.eclipse.jdt.internal.compiler.ast.AssertStatement; import org.eclipse.jdt.internal.compiler.ast.Block; import org.eclipse.jdt.internal.compiler.ast.CastExpression; import org.eclipse.jdt.internal.compiler.ast.CharLiteral; @@ -1786,27 +1787,39 @@ public class EclipseHandlerUtil { if (isPrimitive(variable.type)) return null; AllocationExpression exception = new AllocationExpression(); setGeneratedBy(exception, source); - int partCount = 1; + + SingleNameReference varName = new SingleNameReference(variable.name, p); + setGeneratedBy(varName, source); + NullLiteral nullLiteral = new NullLiteral(pS, pE); + setGeneratedBy(nullLiteral, source); + + int equalOperator = exceptionType == NullCheckExceptionType.ASSERTION ? OperatorIds.NOT_EQUAL : OperatorIds.EQUAL_EQUAL; + EqualExpression equalExpression = new EqualExpression(varName, nullLiteral, equalOperator); + equalExpression.sourceStart = pS; equalExpression.statementEnd = equalExpression.sourceEnd = pE; + setGeneratedBy(equalExpression, source); + + StringLiteral message = new StringLiteral(exceptionType.toExceptionMessage(new String(variable.name)).toCharArray(), pS, pE, 0); + setGeneratedBy(message, source); + + if (exceptionType == NullCheckExceptionType.ASSERTION) { + Statement assertStatement = new AssertStatement(message, equalExpression, pS); + setGeneratedBy(assertStatement, source); + return assertStatement; + } + String exceptionTypeStr = exceptionType.getExceptionType(); + int partCount = 1; for (int i = 0; i < exceptionTypeStr.length(); i++) if (exceptionTypeStr.charAt(i) == '.') partCount++; long[] ps = new long[partCount]; Arrays.fill(ps, 0L); exception.type = new QualifiedTypeReference(fromQualifiedName(exceptionTypeStr), ps); setGeneratedBy(exception.type, source); - exception.arguments = new Expression[] { - new StringLiteral(exceptionType.toExceptionMessage(new String(variable.name)).toCharArray(), pS, pE, 0) - }; - setGeneratedBy(exception.arguments[0], source); + exception.arguments = new Expression[] {message}; + ThrowStatement throwStatement = new ThrowStatement(exception, pS, pE); setGeneratedBy(throwStatement, source); - SingleNameReference varName = new SingleNameReference(variable.name, p); - setGeneratedBy(varName, source); - NullLiteral nullLiteral = new NullLiteral(pS, pE); - setGeneratedBy(nullLiteral, source); - EqualExpression equalExpression = new EqualExpression(varName, nullLiteral, OperatorIds.EQUAL_EQUAL); - equalExpression.sourceStart = pS; equalExpression.statementEnd = equalExpression.sourceEnd = pE; - setGeneratedBy(equalExpression, source); + Block throwBlock = new Block(0); throwBlock.statements = new Statement[] {throwStatement}; throwBlock.sourceStart = pS; throwBlock.sourceEnd = pE; diff --git a/src/core/lombok/eclipse/handlers/HandleNonNull.java b/src/core/lombok/eclipse/handlers/HandleNonNull.java index 1672618d..77c77e1e 100644 --- a/src/core/lombok/eclipse/handlers/HandleNonNull.java +++ b/src/core/lombok/eclipse/handlers/HandleNonNull.java @@ -21,27 +21,18 @@ */ package lombok.eclipse.handlers; -import static lombok.core.handlers.HandlerUtil.*; +import static lombok.core.handlers.HandlerUtil.handleFlagUsage; import static lombok.eclipse.Eclipse.isPrimitive; import static lombok.eclipse.handlers.EclipseHandlerUtil.*; import java.util.Arrays; -import lombok.ConfigurationKeys; -import lombok.NonNull; -import lombok.core.AST.Kind; -import lombok.core.AnnotationValues; -import lombok.core.HandlerPriority; -import lombok.eclipse.DeferUntilPostDiet; -import lombok.eclipse.EclipseAST; -import lombok.eclipse.EclipseAnnotationHandler; -import lombok.eclipse.EclipseNode; - import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Argument; +import org.eclipse.jdt.internal.compiler.ast.AssertStatement; import org.eclipse.jdt.internal.compiler.ast.Block; import org.eclipse.jdt.internal.compiler.ast.EqualExpression; import org.eclipse.jdt.internal.compiler.ast.Expression; @@ -56,6 +47,16 @@ import org.eclipse.jdt.internal.compiler.ast.TryStatement; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.mangosdk.spi.ProviderFor; +import lombok.ConfigurationKeys; +import lombok.NonNull; +import lombok.core.AST.Kind; +import lombok.core.AnnotationValues; +import lombok.core.HandlerPriority; +import lombok.eclipse.DeferUntilPostDiet; +import lombok.eclipse.EclipseAST; +import lombok.eclipse.EclipseAnnotationHandler; +import lombok.eclipse.EclipseNode; + @DeferUntilPostDiet @ProviderFor(EclipseAnnotationHandler.class) @HandlerPriority(value = 512) // 2^9; onParameter=@__(@NonNull) has to run first. @@ -191,9 +192,11 @@ public class HandleNonNull extends EclipseAnnotationHandler<NonNull> { } public char[] returnVarNameIfNullCheck(Statement stat) { - if (!(stat instanceof IfStatement)) return null; + boolean isIf = stat instanceof IfStatement; + if (!isIf && !(stat instanceof AssertStatement)) return null; - /* Check that the if's statement is a throw statement, possibly in a block. */ { + if (isIf) { + /* Check that the if's statement is a throw statement, possibly in a block. */ Statement then = ((IfStatement) stat).thenStatement; if (then instanceof Block) { Statement[] blockStatements = ((Block) then).statements; @@ -206,11 +209,15 @@ public class HandleNonNull extends EclipseAnnotationHandler<NonNull> { /* Check that the if's conditional is like 'x == null'. Return from this method (don't generate a nullcheck) if 'x' is equal to our own variable's name: There's already a nullcheck here. */ { - Expression cond = ((IfStatement) stat).condition; + Expression cond = isIf ? ((IfStatement) stat).condition : ((AssertStatement) stat).assertExpression; if (!(cond instanceof EqualExpression)) return null; EqualExpression bin = (EqualExpression) cond; int operatorId = ((bin.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT); - if (operatorId != OperatorIds.EQUAL_EQUAL) return null; + if (isIf) { + if (operatorId != OperatorIds.EQUAL_EQUAL) return null; + } else { + if (operatorId != OperatorIds.NOT_EQUAL) return null; + } if (!(bin.left instanceof SingleNameReference)) return null; if (!(bin.right instanceof NullLiteral)) return null; return ((SingleNameReference) bin.left).token; diff --git a/src/core/lombok/javac/handlers/HandleNonNull.java b/src/core/lombok/javac/handlers/HandleNonNull.java index 9a81ffff..49b987ce 100644 --- a/src/core/lombok/javac/handlers/HandleNonNull.java +++ b/src/core/lombok/javac/handlers/HandleNonNull.java @@ -21,13 +21,16 @@ */ package lombok.javac.handlers; -import static lombok.core.handlers.HandlerUtil.*; +import static lombok.core.handlers.HandlerUtil.handleFlagUsage; import static lombok.javac.Javac.*; +import static lombok.javac.JavacTreeMaker.TreeTag.treeTag; +import static lombok.javac.JavacTreeMaker.TypeTag.typeTag; import static lombok.javac.handlers.JavacHandlerUtil.*; import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.tree.JCTree.JCAnnotation; +import com.sun.tools.javac.tree.JCTree.JCAssert; import com.sun.tools.javac.tree.JCTree.JCBinary; import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCExpression; @@ -45,13 +48,11 @@ import com.sun.tools.javac.util.List; import lombok.ConfigurationKeys; import lombok.NonNull; +import lombok.core.AST.Kind; import lombok.core.AnnotationValues; import lombok.core.HandlerPriority; -import lombok.core.AST.Kind; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; -import static lombok.javac.JavacTreeMaker.TypeTag.*; -import static lombok.javac.JavacTreeMaker.TreeTag.*; @ProviderFor(JavacAnnotationHandler.class) @HandlerPriority(value = 512) // 2^9; onParameter=@__(@NonNull) has to run first. @@ -161,14 +162,16 @@ public class HandleNonNull extends JavacAnnotationHandler<NonNull> { } /** - * Checks if the statement is of the form 'if (x == null) {throw WHATEVER;}, + * Checks if the statement is of the form 'if (x == null) {throw WHATEVER;}' or 'assert x != null;', * where the block braces are optional. If it is of this form, returns "x". * If it is not of this form, returns null. */ public String returnVarNameIfNullCheck(JCStatement stat) { - if (!(stat instanceof JCIf)) return null; + boolean isIf = stat instanceof JCIf; + if (!isIf && !(stat instanceof JCAssert)) return null; - /* Check that the if's statement is a throw statement, possibly in a block. */ { + if (isIf) { + /* Check that the if's statement is a throw statement, possibly in a block. */ JCStatement then = ((JCIf) stat).thenpart; if (then instanceof JCBlock) { List<JCStatement> stats = ((JCBlock) then).stats; @@ -180,11 +183,15 @@ public class HandleNonNull extends JavacAnnotationHandler<NonNull> { /* Check that the if's conditional is like 'x == null'. Return from this method (don't generate a nullcheck) if 'x' is equal to our own variable's name: There's already a nullcheck here. */ { - JCExpression cond = ((JCIf) stat).cond; + JCExpression cond = isIf ? ((JCIf) stat).cond : ((JCAssert) stat).cond; while (cond instanceof JCParens) cond = ((JCParens) cond).expr; if (!(cond instanceof JCBinary)) return null; JCBinary bin = (JCBinary) cond; - if (!CTC_EQUAL.equals(treeTag(bin))) return null; + if (isIf) { + if (!CTC_EQUAL.equals(treeTag(bin))) return null; + } else { + if (!CTC_NOT_EQUAL.equals(treeTag(bin))) return null; + } if (!(bin.lhs instanceof JCIdent)) return null; if (!(bin.rhs instanceof JCLiteral)) return null; if (!CTC_BOT.equals(typeTag(bin.rhs))) return null; diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 9e6c8c00..509a7397 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -40,36 +40,15 @@ import java.util.regex.Pattern; import javax.lang.model.element.Element; -import lombok.AccessLevel; -import lombok.ConfigurationKeys; -import lombok.Data; -import lombok.Getter; -import lombok.core.AST.Kind; -import lombok.core.AnnotationValues; -import lombok.core.LombokImmutableList; -import lombok.core.AnnotationValues.AnnotationValue; -import lombok.core.CleanupTask; -import lombok.core.TypeResolver; -import lombok.core.configuration.NullCheckExceptionType; -import lombok.core.configuration.TypeName; -import lombok.core.handlers.HandlerUtil; -import lombok.delombok.LombokOptionsFactory; -import lombok.experimental.Accessors; -import lombok.experimental.Tolerate; -import lombok.javac.Javac; -import lombok.javac.JavacNode; -import lombok.javac.JavacTreeMaker; -import lombok.permit.Permit; - import com.sun.tools.javac.code.BoundKind; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Scope; import com.sun.tools.javac.code.Symbol; -import com.sun.tools.javac.code.Symtab; -import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; +import com.sun.tools.javac.code.Symtab; +import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.MethodType; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCAnnotation; @@ -83,6 +62,7 @@ import com.sun.tools.javac.tree.JCTree.JCExpressionStatement; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCIdent; import com.sun.tools.javac.tree.JCTree.JCImport; +import com.sun.tools.javac.tree.JCTree.JCLiteral; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; import com.sun.tools.javac.tree.JCTree.JCModifiers; @@ -103,6 +83,28 @@ import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.Options; +import lombok.AccessLevel; +import lombok.ConfigurationKeys; +import lombok.Data; +import lombok.Getter; +import lombok.core.AST.Kind; +import lombok.core.AnnotationValues; +import lombok.core.AnnotationValues.AnnotationValue; +import lombok.core.CleanupTask; +import lombok.core.LombokImmutableList; +import lombok.core.TypeResolver; +import lombok.core.configuration.NullCheckExceptionType; +import lombok.core.configuration.TypeName; +import lombok.core.handlers.HandlerUtil; +import lombok.core.handlers.HandlerUtil.FieldAccess; +import lombok.delombok.LombokOptionsFactory; +import lombok.experimental.Accessors; +import lombok.experimental.Tolerate; +import lombok.javac.Javac; +import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; +import lombok.permit.Permit; + /** * Container for static utility methods useful to handlers written for javac. */ @@ -1484,8 +1486,14 @@ public class JavacHandlerUtil { if (isPrimitive(varDecl.vartype)) return null; Name fieldName = varDecl.name; + + JCLiteral message = maker.Literal(exceptionType.toExceptionMessage(fieldName.toString())); + if (exceptionType == NullCheckExceptionType.ASSERTION) { + return maker.Assert(maker.Binary(CTC_NOT_EQUAL, maker.Ident(fieldName), maker.Literal(CTC_BOT, null)), message); + } + JCExpression exType = genTypeRef(variable, exceptionType.getExceptionType()); - JCExpression exception = maker.NewClass(null, List.<JCExpression>nil(), exType, List.<JCExpression>of(maker.Literal(exceptionType.toExceptionMessage(fieldName.toString()))), null); + JCExpression exception = maker.NewClass(null, List.<JCExpression>nil(), exType, List.<JCExpression>of(message), null); JCStatement throwStatement = maker.Throw(exception); JCBlock throwBlock = maker.Block(0, List.of(throwStatement)); return maker.If(maker.Binary(CTC_EQUAL, maker.Ident(fieldName), maker.Literal(CTC_BOT, null)), throwBlock, null); |