diff options
Diffstat (limited to 'src/core/lombok')
35 files changed, 833 insertions, 502 deletions
diff --git a/src/core/lombok/core/TransformationsUtil.java b/src/core/lombok/core/TransformationsUtil.java index 8959ad7a..8c7fbd3f 100644 --- a/src/core/lombok/core/TransformationsUtil.java +++ b/src/core/lombok/core/TransformationsUtil.java @@ -70,9 +70,11 @@ public class TransformationsUtil { * @param prefixes A list of prefixes, usually provided by the {@code Accessors} settings annotation, listing field prefixes. * @return The base name of the field. */ - private static CharSequence removePrefix(CharSequence fieldName, String[] prefixes) { + public static CharSequence removePrefix(CharSequence fieldName, String[] prefixes) { if (prefixes == null || prefixes.length == 0) return fieldName; + fieldName = fieldName.toString(); + outer: for (String prefix : prefixes) { if (prefix.length() == 0) return fieldName; @@ -176,6 +178,7 @@ public class TransformationsUtil { private static String toAccessorName(AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean, String booleanPrefix, String normalPrefix, boolean adhereToFluent) { + fieldName = fieldName.toString(); if (fieldName.length() == 0) return null; Accessors ac = accessors == null ? null : accessors.getInstance(); diff --git a/src/core/lombok/core/Version.java b/src/core/lombok/core/Version.java index bd83c1f8..bf2e199b 100644 --- a/src/core/lombok/core/Version.java +++ b/src/core/lombok/core/Version.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2011 The Project Lombok Authors. + * Copyright (C) 2009-2013 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 @@ -28,8 +28,9 @@ public class Version { // ** CAREFUL ** - this class must always compile with 0 dependencies (it must not refer to any other sources or libraries). // Note: In 'X.Y.Z', if Z is odd, its a snapshot build built from the repository, so many different 0.10.3 versions can exist, for example. // Official builds always end in an even number. (Since 0.10.2). - private static final String VERSION = "0.12.1"; - private static final String RELEASE_NAME = "Angry Butterfy"; + private static final String VERSION = "1.12.3"; + private static final String RELEASE_NAME = "Edgy Guinea Pig"; +// private static final String RELEASE_NAME = "Angry Butterfly"; private Version() { //Prevent instantiation diff --git a/src/core/lombok/core/debug/DebugSnapshotStore.java b/src/core/lombok/core/debug/DebugSnapshotStore.java index 64c91473..11192bd3 100644 --- a/src/core/lombok/core/debug/DebugSnapshotStore.java +++ b/src/core/lombok/core/debug/DebugSnapshotStore.java @@ -82,7 +82,7 @@ public class DebugSnapshotStore { } try { - File logFile = new File(System.getProperty("user.home", "."), String.format("lombok164-%d.err", System.currentTimeMillis())); + File logFile = new File(System.getProperty("user.home", "."), String.format("lombokdss-%d.err", System.currentTimeMillis())); OutputStream stream = new FileOutputStream(logFile); try { stream.write(out.toString().getBytes("UTF-8")); diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 9bd634f7..5e322c90 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -1125,6 +1125,37 @@ public class EclipseHandlerUtil { return true; } + public static char[] removePrefixFromField(EclipseNode field) { + String[] prefixes = null; + for (EclipseNode node : field.down()) { + if (annotationTypeMatches(Accessors.class, node)) { + prefixes = createAnnotation(Accessors.class, node).getInstance().prefix(); + break; + } + } + + if (prefixes == null) { + EclipseNode current = field.up(); + outer: + while (current != null) { + for (EclipseNode node : current.down()) { + if (annotationTypeMatches(Accessors.class, node)) { + prefixes = createAnnotation(Accessors.class, node).getInstance().prefix(); + break outer; + } + } + current = current.up(); + } + } + + if (prefixes != null && prefixes.length > 0) { + CharSequence newName = TransformationsUtil.removePrefix(field.getName(), prefixes); + if (newName != null) return newName.toString().toCharArray(); + } + + return ((FieldDeclaration) field.get()).name; + } + public static AnnotationValues<Accessors> getAccessorsForField(EclipseNode field) { for (EclipseNode node : field.down()) { if (annotationTypeMatches(Accessors.class, node)) { @@ -1562,9 +1593,9 @@ public class EclipseHandlerUtil { intLiteralFactoryMethod = intLiteralFactoryMethod_; } - private static boolean isAllUnderscores(char[] in) { + private static boolean isAllValidOnXCharacters(char[] in) { if (in == null || in.length == 0) return false; - for (char c : in) if (c != '_') return false; + for (char c : in) if (c != '_' && c != 'X' && c != 'x' && c != '$') return false; return true; } @@ -1597,31 +1628,31 @@ public class EclipseHandlerUtil { if (i > 0) System.arraycopy(pairs, 0, newPairs, 0, i); if (i < pairs.length - 1) System.arraycopy(pairs, i + 1, newPairs, i, pairs.length - i - 1); normalAnnotation.memberValuePairs = newPairs; - // We have now removed the annotation parameter and stored '@_({... annotations ...})', + // We have now removed the annotation parameter and stored '@__({... annotations ...})', // which we must now unbox. if (!(value instanceof Annotation)) { - errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))"); return Collections.emptyList(); } - Annotation atUnderscore = (Annotation) value; - if (!(atUnderscore.type instanceof SingleTypeReference) || - !isAllUnderscores(((SingleTypeReference) atUnderscore.type).token)) { - errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + Annotation atDummyIdentifier = (Annotation) value; + if (!(atDummyIdentifier.type instanceof SingleTypeReference) || + !isAllValidOnXCharacters(((SingleTypeReference) atDummyIdentifier.type).token)) { + errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))"); return Collections.emptyList(); } - if (atUnderscore instanceof MarkerAnnotation) { - // It's @getter(onMethod=@_). This is weird, but fine. + if (atDummyIdentifier instanceof MarkerAnnotation) { + // It's @Getter(onMethod=@__). This is weird, but fine. return Collections.emptyList(); } Expression content = null; - if (atUnderscore instanceof NormalAnnotation) { - MemberValuePair[] mvps = ((NormalAnnotation) atUnderscore).memberValuePairs; + if (atDummyIdentifier instanceof NormalAnnotation) { + MemberValuePair[] mvps = ((NormalAnnotation) atDummyIdentifier).memberValuePairs; if (mvps == null || mvps.length == 0) { - // It's @getter(onMethod=@_()). This is weird, but fine. + // It's @Getter(onMethod=@__()). This is weird, but fine. return Collections.emptyList(); } if (mvps.length == 1 && Arrays.equals("value".toCharArray(), mvps[0].name)) { @@ -1629,12 +1660,12 @@ public class EclipseHandlerUtil { } } - if (atUnderscore instanceof SingleMemberAnnotation) { - content = ((SingleMemberAnnotation) atUnderscore).memberValue; + if (atDummyIdentifier instanceof SingleMemberAnnotation) { + content = ((SingleMemberAnnotation) atDummyIdentifier).memberValue; } if (content == null) { - errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))"); return Collections.emptyList(); } @@ -1646,13 +1677,13 @@ public class EclipseHandlerUtil { if (expressions != null) for (Expression ex : expressions) { if (ex instanceof Annotation) result.add((Annotation) ex); else { - errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))"); return Collections.emptyList(); } } return result; } else { - errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))"); return Collections.emptyList(); } } diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 70110a9c..981d77dc 100644 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -113,7 +113,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { // non-final fields final, but @Value's handler hasn't done this yet, so we have to do this math ourselves. // Value will only skip making a field final if it has an explicit @NonFinal annotation, so we check for that. if (fd.initialization != null && valuePresent && !hasAnnotation(NonFinal.class, fieldNode)) continue; - namesOfParameters.add(fd.name); + namesOfParameters.add(removePrefixFromField(fieldNode)); typesOfParameters.add(fd.type); fields.add(fieldNode); } diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java index 1ae680d9..22285b2d 100644 --- a/src/core/lombok/eclipse/handlers/HandleConstructor.java +++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java @@ -230,7 +230,8 @@ public class HandleConstructor { int ctr = 0; for (EclipseNode field : fields) { - fieldNames.expressions[ctr] = new StringLiteral(field.getName().toCharArray(), pS, pE, 0); + char[] fieldName = removePrefixFromField(field); + fieldNames.expressions[ctr] = new StringLiteral(fieldName, pS, pE, 0); setGeneratedBy(fieldNames.expressions[ctr], source); ctr++; } @@ -273,15 +274,17 @@ public class HandleConstructor { for (EclipseNode fieldNode : fields) { FieldDeclaration field = (FieldDeclaration) fieldNode.get(); - FieldReference thisX = new FieldReference(field.name, p); + char[] rawName = field.name; + char[] fieldName = removePrefixFromField(fieldNode); + FieldReference thisX = new FieldReference(rawName, p); thisX.receiver = new ThisReference((int)(p >> 32), (int)p); - SingleNameReference assignmentNameRef = new SingleNameReference(field.name, p); + SingleNameReference assignmentNameRef = new SingleNameReference(fieldName, p); Assignment assignment = new Assignment(thisX, assignmentNameRef, (int)p); assignment.sourceStart = (int)(p >> 32); assignment.sourceEnd = assignment.statementEnd = (int)(p >> 32); assigns.add(assignment); long fieldPos = (((long)field.sourceStart) << 32) | field.sourceEnd; - Argument parameter = new Argument(field.name, fieldPos, copyType(field.type, source), Modifier.FINAL); + Argument parameter = new Argument(fieldName, fieldPos, copyType(field.type, source), Modifier.FINAL); Annotation[] nonNulls = findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN); Annotation[] nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN); if (nonNulls.length != 0) { diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java index 6990e609..3c8a7039 100644 --- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java @@ -221,7 +221,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH // The user code couldn't possibly (barring really weird subclassing shenanigans) be in a shippable state anyway; the implementations of these 3 methods are // all inter-related and should be written by the same entity. String msg = String.format("Not generating %s: One of equals, hashCode, and canEqual exists. " + - "You should either write all of these are none of these (in the latter case, lombok generates them).", + "You should either write all of these or none of these (in the latter case, lombok generates them).", equalsExists == MemberExistsResult.NOT_EXISTS && hashCodeExists == MemberExistsResult.NOT_EXISTS ? "equals and hashCode" : equalsExists == MemberExistsResult.NOT_EXISTS ? "equals" : "hashCode"); errorNode.addWarning(msg); diff --git a/src/core/lombok/eclipse/handlers/NonNullHandler.java b/src/core/lombok/eclipse/handlers/HandleNonNull.java index 5c58069c..634cb2d9 100644 --- a/src/core/lombok/eclipse/handlers/NonNullHandler.java +++ b/src/core/lombok/eclipse/handlers/HandleNonNull.java @@ -21,8 +21,19 @@ */ package lombok.eclipse.handlers; +import static lombok.eclipse.Eclipse.isPrimitive; +import static lombok.eclipse.handlers.EclipseHandlerUtil.*; + import java.util.Arrays; +import lombok.NonNull; +import lombok.core.AST.Kind; +import lombok.core.AnnotationValues; +import lombok.core.HandlerPriority; +import lombok.eclipse.DeferUntilPostDiet; +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; @@ -36,22 +47,15 @@ import org.eclipse.jdt.internal.compiler.ast.NullLiteral; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.Statement; +import org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement; import org.eclipse.jdt.internal.compiler.ast.ThrowStatement; +import org.eclipse.jdt.internal.compiler.ast.TryStatement; import org.mangosdk.spi.ProviderFor; -import lombok.NonNull; -import lombok.core.AST.Kind; -import lombok.core.AnnotationValues; -import lombok.eclipse.DeferUntilPostDiet; -import lombok.eclipse.EclipseAnnotationHandler; -import lombok.eclipse.EclipseNode; - -import static lombok.eclipse.Eclipse.*; -import static lombok.eclipse.handlers.EclipseHandlerUtil.*; - @DeferUntilPostDiet @ProviderFor(EclipseAnnotationHandler.class) -public class NonNullHandler extends EclipseAnnotationHandler<NonNull> { +@HandlerPriority(value = 512) // 2^9; onParameter=@__(@NonNull) has to run first. +public class HandleNonNull extends EclipseAnnotationHandler<NonNull> { @Override public void handle(AnnotationValues<NonNull> annotation, Annotation ast, EclipseNode annotationNode) { if (annotationNode.up().getKind() == Kind.FIELD) { // This is meaningless unless the field is used to generate a method (@Setter, @RequiredArgsConstructor, etc), @@ -82,6 +86,11 @@ public class NonNullHandler extends EclipseAnnotationHandler<NonNull> { if (isGenerated(declaration)) return; + if (declaration.isAbstract()) { + annotationNode.addWarning("@NonNull is meaningless on a parameter of an abstract method."); + return; + } + // Possibly, if 'declaration instanceof ConstructorDeclaration', fetch declaration.constructorCall, search it for any references to our parameter, // and if they exist, create a new method in the class: 'private static <T> T lombok$nullCheck(T expr, String msg) {if (expr == null) throw NPE; return expr;}' and // wrap all references to it in the super/this to a call to this method. @@ -98,16 +107,31 @@ public class NonNullHandler extends EclipseAnnotationHandler<NonNull> { declaration.statements = new Statement[] {nullCheck}; } else { char[] expectedName = arg.name; - for (Statement stat : declaration.statements) { - char[] varNameOfNullCheck = returnVarNameIfNullCheck(stat); - if (varNameOfNullCheck == null) break; - if (Arrays.equals(expectedName, varNameOfNullCheck)) return; + /* Abort if the null check is already there, delving into try and synchronized statements */ { + Statement[] stats = declaration.statements; + int idx = 0; + while (stats != null && stats.length > idx) { + Statement stat = stats[idx++]; + if (stat instanceof TryStatement) { + stats = ((TryStatement) stat).tryBlock.statements; + idx = 0; + continue; + } + if (stat instanceof SynchronizedStatement) { + stats = ((SynchronizedStatement) stat).block.statements; + idx = 0; + continue; + } + char[] varNameOfNullCheck = returnVarNameIfNullCheck(stat); + if (varNameOfNullCheck == null) break; + if (Arrays.equals(varNameOfNullCheck, expectedName)) return; + } } Statement[] newStatements = new Statement[declaration.statements.length + 1]; int skipOver = 0; for (Statement stat : declaration.statements) { - if (isGenerated(stat)) skipOver++; + if (isGenerated(stat) && isNullCheck(stat)) skipOver++; else break; } System.arraycopy(declaration.statements, 0, newStatements, 0, skipOver); @@ -118,6 +142,10 @@ public class NonNullHandler extends EclipseAnnotationHandler<NonNull> { annotationNode.up().up().rebuild(); } + private boolean isNullCheck(Statement stat) { + return returnVarNameIfNullCheck(stat) != null; + } + private char[] returnVarNameIfNullCheck(Statement stat) { if (!(stat instanceof IfStatement)) return null; diff --git a/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java b/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java index aa78ca3b..d3a95db8 100644 --- a/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java +++ b/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java @@ -30,6 +30,7 @@ import java.util.List; import lombok.SneakyThrows; import lombok.core.AnnotationValues; +import lombok.core.HandlerPriority; import lombok.eclipse.DeferUntilPostDiet; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; @@ -60,6 +61,7 @@ import org.mangosdk.spi.ProviderFor; */ @ProviderFor(EclipseAnnotationHandler.class) @DeferUntilPostDiet +@HandlerPriority(value = 1024) // 2^10; @NonNull must have run first, so that we wrap around the statements generated by it. public class HandleSneakyThrows extends EclipseAnnotationHandler<SneakyThrows> { private static class DeclaredException { diff --git a/src/core/lombok/eclipse/handlers/HandleSynchronized.java b/src/core/lombok/eclipse/handlers/HandleSynchronized.java index e4c58eab..f76f06ed 100644 --- a/src/core/lombok/eclipse/handlers/HandleSynchronized.java +++ b/src/core/lombok/eclipse/handlers/HandleSynchronized.java @@ -27,6 +27,7 @@ import java.lang.reflect.Modifier; import lombok.Synchronized; import lombok.core.AnnotationValues; +import lombok.core.HandlerPriority; import lombok.core.AST.Kind; import lombok.eclipse.DeferUntilPostDiet; import lombok.eclipse.EclipseAnnotationHandler; @@ -52,6 +53,7 @@ import org.mangosdk.spi.ProviderFor; */ @ProviderFor(EclipseAnnotationHandler.class) @DeferUntilPostDiet +@HandlerPriority(value = 1024) // 2^10; @NonNull must have run first, so that we wrap around the statements generated by it. public class HandleSynchronized extends EclipseAnnotationHandler<Synchronized> { private static final char[] INSTANCE_LOCK_NAME = "$lock".toCharArray(); private static final char[] STATIC_LOCK_NAME = "$LOCK".toCharArray(); diff --git a/src/core/lombok/javac/CapturingDiagnosticListener.java b/src/core/lombok/javac/CapturingDiagnosticListener.java index 45b4047a..a0ac6adc 100644 --- a/src/core/lombok/javac/CapturingDiagnosticListener.java +++ b/src/core/lombok/javac/CapturingDiagnosticListener.java @@ -52,7 +52,7 @@ public class CapturingDiagnosticListener implements DiagnosticListener<JavaFileO "^" + Pattern.quote(file.getAbsolutePath()) + "\\s*:\\s*\\d+\\s*:\\s*(?:warning:\\s*)?(.*)$", Pattern.DOTALL).matcher(msg); if (m.matches()) msg = m.group(1); - messages.add(new CompilerMessage(d.getLineNumber(), d.getColumnNumber(), d.getStartPosition(), d.getKind() == Kind.ERROR, msg)); + messages.add(new CompilerMessage(d.getLineNumber(), d.getStartPosition(), d.getKind() == Kind.ERROR, msg)); } public void suppress(int start, int end) { @@ -67,15 +67,12 @@ public class CapturingDiagnosticListener implements DiagnosticListener<JavaFileO /** Line Number (starting at 1) */ private final long line; - /** Preferably column, but if that is hard to calculate (e.g. in ecj), then position is acceptable. */ - private final long columnOrPosition; private final long position; private final boolean isError; private final String message; - public CompilerMessage(long line, long columnOrPosition, long position, boolean isError, String message) { + public CompilerMessage(long line, long position, boolean isError, String message) { this.line = line; - this.columnOrPosition = columnOrPosition; this.position = position; this.isError = isError; this.message = message; @@ -89,10 +86,6 @@ public class CapturingDiagnosticListener implements DiagnosticListener<JavaFileO return position; } - public long getColumnOrPosition() { - return columnOrPosition; - } - public boolean isError() { return isError; } @@ -107,7 +100,6 @@ public class CapturingDiagnosticListener implements DiagnosticListener<JavaFileO result = prime * result + (isError ? 1231 : 1237); result = prime * result + (int) (line ^ (line >>> 32)); result = prime * result + ((message == null) ? 0 : message.hashCode()); - result = prime * result + (int) (columnOrPosition ^ (columnOrPosition >>> 32)); return result; } @@ -121,12 +113,11 @@ public class CapturingDiagnosticListener implements DiagnosticListener<JavaFileO if (message == null) { if (other.message != null) return false; } else if (!message.equals(other.message)) return false; - if (columnOrPosition != other.columnOrPosition) return false; return true; } @Override public String toString() { - return String.format("%d:%d %s %s", line, columnOrPosition, isError ? "ERROR" : "WARNING", message); + return String.format("%d %s %s", line, isError ? "ERROR" : "WARNING", message); } } } diff --git a/src/core/lombok/javac/CompilerMessageSuppressor.java b/src/core/lombok/javac/CompilerMessageSuppressor.java new file mode 100644 index 00000000..a17e0c62 --- /dev/null +++ b/src/core/lombok/javac/CompilerMessageSuppressor.java @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2011-2013 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 + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.javac; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.lang.reflect.Field; +import java.util.LinkedList; +import java.util.Queue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.tools.DiagnosticListener; +import javax.tools.JavaFileObject; + +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.JCDiagnostic; +import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.javac.util.Log; + +/** + * During resolution, the resolver will emit resolution errors, but without appropriate file names and line numbers. If these resolution errors stick around + * then they will be generated AGAIN, this time with proper names and line numbers, at the end. Therefore, we want to suppress the logger. + */ +public final class CompilerMessageSuppressor { + private final Log log; + private static final Field errWriterField, warnWriterField, noticeWriterField, dumpOnErrorField, promptOnErrorField, diagnosticListenerField; + private static final Field deferDiagnosticsField, deferredDiagnosticsField, diagnosticHandlerField; + private static final ConcurrentMap<Class<?>, Field> handlerDeferredFields = new ConcurrentHashMap<Class<?>, Field>(); + private static final Field NULL_FIELD; + private PrintWriter errWriter, warnWriter, noticeWriter; + private Boolean dumpOnError, promptOnError; + private DiagnosticListener<?> contextDiagnosticListener, logDiagnosticListener; + private final Context context; + + // If this is true, the fields changed. Better to print weird error messages than to fail outright. + private static final boolean dontBother; + + private static final ThreadLocal<Queue<?>> queueCache = new ThreadLocal<Queue<?>>(); + + static { + errWriterField = getDeclaredField(Log.class, "errWriter"); + warnWriterField = getDeclaredField(Log.class, "warnWriter"); + noticeWriterField = getDeclaredField(Log.class, "noticeWriter"); + dumpOnErrorField = getDeclaredField(Log.class, "dumpOnError"); + promptOnErrorField = getDeclaredField(Log.class, "promptOnError"); + diagnosticListenerField = getDeclaredField(Log.class, "diagListener"); + + dontBother = + errWriterField == null || + warnWriterField == null || + noticeWriterField == null || + dumpOnErrorField == null || + promptOnErrorField == null || + diagnosticListenerField == null; + + + deferDiagnosticsField = getDeclaredField(Log.class, "deferDiagnostics"); + deferredDiagnosticsField = getDeclaredField(Log.class, "deferredDiagnostics"); + + // javac8 + diagnosticHandlerField = getDeclaredField(Log.class, "diagnosticHandler"); + + NULL_FIELD = getDeclaredField(JavacResolution.class, "NULL_FIELD"); + } + + static Field getDeclaredField(Class<?> c, String fieldName) { + try { + Field field = c.getDeclaredField(fieldName); + field.setAccessible(true); + return field; + } + catch (Throwable t) { + return null; + } + } + + public CompilerMessageSuppressor(Context context) { + this.log = Log.instance(context); + this.context = context; + } + + public boolean disableLoggers() { + contextDiagnosticListener = context.get(DiagnosticListener.class); + context.put(DiagnosticListener.class, (DiagnosticListener<?>) null); + if (dontBother) return false; + boolean dontBotherInstance = false; + + PrintWriter dummyWriter = new PrintWriter(new OutputStream() { + @Override public void write(int b) throws IOException { + // Do nothing on purpose + } + }); + + if (deferDiagnosticsField != null) try { + if (Boolean.TRUE.equals(deferDiagnosticsField.get(log))) { + queueCache.set((Queue<?>) deferredDiagnosticsField.get(log)); + Queue<?> empty = new LinkedList<Object>(); + deferredDiagnosticsField.set(log, empty); + } + } catch (Exception e) {} + + if (diagnosticHandlerField != null) try { + Object handler = diagnosticHandlerField.get(log); + Field field = getDeferredField(handler); + if (field != null) { + queueCache.set((Queue<?>) field.get(handler)); + Queue<?> empty = new LinkedList<Object>(); + field.set(handler, empty); + } + } catch (Exception e) {} + + if (!dontBotherInstance) try { + errWriter = (PrintWriter) errWriterField.get(log); + errWriterField.set(log, dummyWriter); + } catch (Exception e) { + dontBotherInstance = true; + } + + if (!dontBotherInstance) try { + warnWriter = (PrintWriter) warnWriterField.get(log); + warnWriterField.set(log, dummyWriter); + } catch (Exception e) { + dontBotherInstance = true; + } + + if (!dontBotherInstance) try { + noticeWriter = (PrintWriter) noticeWriterField.get(log); + noticeWriterField.set(log, dummyWriter); + } catch (Exception e) { + dontBotherInstance = true; + } + + if (!dontBotherInstance) try { + dumpOnError = (Boolean) dumpOnErrorField.get(log); + dumpOnErrorField.set(log, false); + } catch (Exception e) { + dontBotherInstance = true; + } + + if (!dontBotherInstance) try { + promptOnError = (Boolean) promptOnErrorField.get(log); + promptOnErrorField.set(log, false); + } catch (Exception e) { + dontBotherInstance = true; + } + + if (!dontBotherInstance) try { + logDiagnosticListener = (DiagnosticListener<?>) diagnosticListenerField.get(log); + diagnosticListenerField.set(log, null); + } catch (Exception e) { + dontBotherInstance = true; + } + + if (dontBotherInstance) enableLoggers(); + return !dontBotherInstance; + } + + private static Field getDeferredField(Object handler) { + Class<? extends Object> key = handler.getClass(); + Field field = handlerDeferredFields.get(key); + if (field != null) { + return field == NULL_FIELD ? null : field; + } + Field value = getDeclaredField(key, "deferred"); + handlerDeferredFields.put(key, value == null ? NULL_FIELD : value); + return getDeferredField(handler); + } + + public void enableLoggers() { + if (contextDiagnosticListener != null) { + context.put(DiagnosticListener.class, contextDiagnosticListener); + contextDiagnosticListener = null; + } + + if (errWriter != null) try { + errWriterField.set(log, errWriter); + errWriter = null; + } catch (Exception e) {} + + if (warnWriter != null) try { + warnWriterField.set(log, warnWriter); + warnWriter = null; + } catch (Exception e) {} + + if (noticeWriter != null) try { + noticeWriterField.set(log, noticeWriter); + noticeWriter = null; + } catch (Exception e) {} + + if (dumpOnError != null) try { + dumpOnErrorField.set(log, dumpOnError); + dumpOnError = null; + } catch (Exception e) {} + + if (promptOnError != null) try { + promptOnErrorField.set(log, promptOnError); + promptOnError = null; + } catch (Exception e) {} + + if (logDiagnosticListener != null) try { + diagnosticListenerField.set(log, logDiagnosticListener); + logDiagnosticListener = null; + } catch (Exception e) {} + + if (diagnosticHandlerField != null && queueCache.get() != null) try { + Object handler = diagnosticHandlerField.get(log); + Field field = getDeferredField(handler); + if (field != null) { + field.set(handler, queueCache.get()); + queueCache.set(null); + } + } catch (Exception e) {} + + if (deferDiagnosticsField != null && queueCache.get() != null) try { + deferredDiagnosticsField.set(log, queueCache.get()); + queueCache.set(null); + } catch (Exception e) {} + } + + public void removeAllBetween(JavaFileObject sourcefile, int startPos, int endPos) { + DiagnosticListener<?> listener = context.get(DiagnosticListener.class); + if (listener instanceof CapturingDiagnosticListener) { + ((CapturingDiagnosticListener) listener).suppress(startPos, endPos); + } + + Field field = null; + Object receiver = null; + if (deferDiagnosticsField != null) try { + if (Boolean.TRUE.equals(deferDiagnosticsField.get(log))) { + field = deferredDiagnosticsField; + receiver = log; + } + } catch (Exception e) {} + + if (diagnosticHandlerField != null) try { + Object handler = diagnosticHandlerField.get(log); + field = getDeferredField(handler); + receiver = handler; + } catch (Exception e) {} + + if (field == null || receiver == null) return; + + try { + ListBuffer<?> deferredDiagnostics = (ListBuffer<?>) field.get(receiver); + ListBuffer<Object> newDeferredDiagnostics = new ListBuffer<Object>(); + for (Object diag_ : deferredDiagnostics) { + if (!(diag_ instanceof JCDiagnostic)) { + newDeferredDiagnostics.add(diag_); + continue; + } + JCDiagnostic diag = (JCDiagnostic) diag_; + long here = diag.getStartPosition(); + if (here >= startPos && here < endPos && diag.getSource() == sourcefile) { + // We eliminate it + } else { + newDeferredDiagnostics.add(diag); + } + } + field.set(receiver, newDeferredDiagnostics); + } catch (Exception e) { + // We do not expect failure here; if failure does occur, the best course of action is to silently continue; the result will be that the error output of + // javac will contain rather a lot of messages, but this is a lot better than just crashing during compilation! + } + } +}
\ No newline at end of file diff --git a/src/core/lombok/javac/FindTypeVarScanner.java b/src/core/lombok/javac/FindTypeVarScanner.java index b1b8e525..7c7d9d50 100644 --- a/src/core/lombok/javac/FindTypeVarScanner.java +++ b/src/core/lombok/javac/FindTypeVarScanner.java @@ -88,7 +88,7 @@ public class FindTypeVarScanner extends AbstractTypeVisitor6<Void, Void> { @Override public Void visitTypeVariable(TypeVariable t, Void p) { Name name = null; try { - name = ((Type)t).tsym.name; + name = ((Type) t).tsym.name; } catch (NullPointerException e) {} if (name != null) typeVariables.add(name.toString()); subVisit(t.getLowerBound()); diff --git a/src/core/lombok/javac/Javac6BasedLombokOptions.java b/src/core/lombok/javac/Javac6BasedLombokOptions.java new file mode 100644 index 00000000..871e41c4 --- /dev/null +++ b/src/core/lombok/javac/Javac6BasedLombokOptions.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2013 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 + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.javac; + +import com.sun.tools.javac.main.OptionName; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Options; + +public class Javac6BasedLombokOptions extends LombokOptions { + public static Javac6BasedLombokOptions replaceWithDelombokOptions(Context context) { + Options options = Options.instance(context); + context.put(optionsKey, (Options)null); + Javac6BasedLombokOptions result = new Javac6BasedLombokOptions(context); + result.putAll(options); + return result; + } + + private Javac6BasedLombokOptions(Context context) { + super(context); + } + + @Override public void putJavacOption(String optionName, String value) { + put(OptionName.valueOf(optionName), value); + } +} diff --git a/src/core/lombok/javac/Javac8BasedLombokOptions.java b/src/core/lombok/javac/Javac8BasedLombokOptions.java new file mode 100644 index 00000000..3fdea890 --- /dev/null +++ b/src/core/lombok/javac/Javac8BasedLombokOptions.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2013 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 + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.javac; + +import com.sun.tools.javac.main.Option; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Options; + +public class Javac8BasedLombokOptions extends LombokOptions { + public static Javac8BasedLombokOptions replaceWithDelombokOptions(Context context) { + Options options = Options.instance(context); + context.put(optionsKey, (Options)null); + Javac8BasedLombokOptions result = new Javac8BasedLombokOptions(context); + result.putAll(options); + return result; + } + + private Javac8BasedLombokOptions(Context context) { + super(context); + } + + @Override public void putJavacOption(String optionName, String value) { + String optionText = Option.valueOf(optionName).text; + put(optionText, value); + } +} diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java index 36c51210..31bdc3a6 100644 --- a/src/core/lombok/javac/JavacAST.java +++ b/src/core/lombok/javac/JavacAST.java @@ -29,7 +29,6 @@ import java.util.List; import javax.annotation.processing.Messager; import javax.tools.Diagnostic; -import javax.tools.DiagnosticListener; import javax.tools.JavaFileObject; import lombok.core.AST; @@ -53,8 +52,6 @@ import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.JCDiagnostic; -import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; @@ -66,7 +63,7 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { private final Messager messager; private final JavacElements elements; - private final TreeMaker treeMaker; + private final JavacTreeMaker treeMaker; private final Symtab symtab; private final JavacTypes javacTypes; private final Log log; @@ -86,7 +83,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { this.messager = messager; this.log = Log.instance(context); this.elements = JavacElements.instance(context); - this.treeMaker = TreeMaker.instance(context); + this.treeMaker = new JavacTreeMaker(TreeMaker.instance(context)); this.symtab = Symtab.instance(context); this.javacTypes = JavacTypes.instance(context); clearChanged(); @@ -135,7 +132,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { } /** @return A TreeMaker instance that you can use to create new AST nodes. */ - public TreeMaker getTreeMaker() { + public JavacTreeMaker getTreeMaker() { treeMaker.at(-1); return treeMaker; } @@ -343,24 +340,13 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { if (node != null) nodes.add(node); } - private static final Field JAVAC7_DEFERRED_DIAGNOSTICS; - - static { - Field f = null; - try { - f = Log.class.getField("deferredDiagnostics"); - if (!ListBuffer.class.isAssignableFrom(f.getType())) throw new NoSuchFieldException("deferredDiagnostics does not have the expected type."); - } catch (NoSuchFieldException e) {} - JAVAC7_DEFERRED_DIAGNOSTICS = f; - } - /** * Attempts to remove any compiler errors generated by java whose reporting position is located anywhere between the start and end of the supplied node. */ void removeDeferredErrors(JavacNode node) { DiagnosticPosition pos = node.get().pos(); JCCompilationUnit top = (JCCompilationUnit) top().get(); - removeFromDeferredDiagnostics(pos.getStartPosition(), pos.getEndPosition(top.endPositions)); + removeFromDeferredDiagnostics(pos.getStartPosition(), Javac.getEndPosition(pos, top)); } /** Supply either a position or a node (in that case, position of the node is used) */ @@ -375,7 +361,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { if (pos == null) pos = astObject.pos(); } if (pos != null && attemptToRemoveErrorsInRange) { - removeFromDeferredDiagnostics(pos.getStartPosition(), pos.getEndPosition(top.endPositions)); + removeFromDeferredDiagnostics(pos.getStartPosition(), node.getEndPosition(pos)); } try { switch (kind) { @@ -400,32 +386,8 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { } private void removeFromDeferredDiagnostics(int startPos, int endPos) { - DiagnosticListener<?> listener = getContext().get(DiagnosticListener.class); - if (listener instanceof CapturingDiagnosticListener) { - ((CapturingDiagnosticListener) listener).suppress(startPos, endPos); - } - try { - if (JAVAC7_DEFERRED_DIAGNOSTICS != null) { - ListBuffer<?> deferredDiagnostics = (ListBuffer<?>) JAVAC7_DEFERRED_DIAGNOSTICS.get(log); - ListBuffer<Object> newDeferredDiagnostics = ListBuffer.lb(); - for (Object diag : deferredDiagnostics) { - if (!(diag instanceof JCDiagnostic)) { - newDeferredDiagnostics.add(diag); - continue; - } - long here = ((JCDiagnostic) diag).getStartPosition(); - if (here >= startPos && here < endPos) { - // We eliminate it - } else { - newDeferredDiagnostics.add(diag); - } - } - JAVAC7_DEFERRED_DIAGNOSTICS.set(log, newDeferredDiagnostics); - } - } catch (Exception e) { - // We do not expect failure here; if failure does occur, the best course of action is to silently continue; the result will be that the error output of - // javac will contain rather a lot of messages, but this is a lot better than just crashing during compilation! - } + JCCompilationUnit self = (JCCompilationUnit) top().get(); + new CompilerMessageSuppressor(getContext()).removeAllBetween(self.sourcefile, startPos, endPos); } /** {@inheritDoc} */ diff --git a/src/core/lombok/javac/JavacNode.java b/src/core/lombok/javac/JavacNode.java index 16c06430..6eef36eb 100644 --- a/src/core/lombok/javac/JavacNode.java +++ b/src/core/lombok/javac/JavacNode.java @@ -30,7 +30,6 @@ import lombok.core.AST.Kind; import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.model.JavacTypes; import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCClassDecl; @@ -52,6 +51,15 @@ public class JavacNode extends lombok.core.LombokNode<JavacAST, JavacNode, JCTre super(ast, node, children, kind); } + public int getEndPosition(DiagnosticPosition pos) { + JCCompilationUnit cu = (JCCompilationUnit) top().get(); + return Javac.getEndPosition(pos, cu); + } + + public int getEndPosition() { + return getEndPosition(node); + } + /** * Visits this node and all child nodes depth-first, calling the provided visitor's visit methods. */ @@ -165,7 +173,7 @@ public class JavacNode extends lombok.core.LombokNode<JavacAST, JavacNode, JCTre * * @see JavacAST#getTreeMaker() */ - public TreeMaker getTreeMaker() { + public JavacTreeMaker getTreeMaker() { return ast.getTreeMaker(); } diff --git a/src/core/lombok/javac/JavacResolution.java b/src/core/lombok/javac/JavacResolution.java index 0a21aa58..5631e62c 100644 --- a/src/core/lombok/javac/JavacResolution.java +++ b/src/core/lombok/javac/JavacResolution.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 The Project Lombok Authors. + * Copyright (C) 2011-2013 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,18 +22,12 @@ package lombok.javac; import static lombok.javac.Javac.*; +import static lombok.javac.JavacTreeMaker.TypeTag.typeTag; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.lang.reflect.Field; import java.util.ArrayDeque; -import java.util.LinkedList; import java.util.Map; -import java.util.Queue; import javax.lang.model.type.TypeKind; -import javax.tools.DiagnosticListener; import com.sun.tools.javac.code.BoundKind; import com.sun.tools.javac.code.Symbol.TypeSymbol; @@ -43,7 +37,6 @@ import com.sun.tools.javac.code.Type.ArrayType; import com.sun.tools.javac.code.Type.CapturedType; import com.sun.tools.javac.code.Type.ClassType; import com.sun.tools.javac.code.Type.WildcardType; -import com.sun.tools.javac.code.TypeTags; import com.sun.tools.javac.code.Types; import com.sun.tools.javac.comp.Attr; import com.sun.tools.javac.comp.AttrContext; @@ -57,191 +50,17 @@ import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; -import com.sun.tools.javac.util.Log; public class JavacResolution { private final Attr attr; - private final LogDisabler logDisabler; + private final CompilerMessageSuppressor messageSuppressor; public JavacResolution(Context context) { attr = Attr.instance(context); - logDisabler = new LogDisabler(context); - } - - /** - * During resolution, the resolver will emit resolution errors, but without appropriate file names and line numbers. If these resolution errors stick around - * then they will be generated AGAIN, this time with proper names and line numbers, at the end. Therefore, we want to suppress the logger. - */ - private static final class LogDisabler { - private final Log log; - private static final Field errWriterField, warnWriterField, noticeWriterField, dumpOnErrorField, promptOnErrorField, diagnosticListenerField; - private static final Field deferDiagnosticsField, deferredDiagnosticsField; - private PrintWriter errWriter, warnWriter, noticeWriter; - private Boolean dumpOnError, promptOnError; - private DiagnosticListener<?> contextDiagnosticListener, logDiagnosticListener; - private final Context context; - - // If this is true, the fields changed. Better to print weird error messages than to fail outright. - private static final boolean dontBother; - - private static final ThreadLocal<Queue<?>> queueCache = new ThreadLocal<Queue<?>>(); - - static { - boolean z; - Field a = null, b = null, c = null, d = null, e = null, f = null, g = null, h = null; - try { - a = Log.class.getDeclaredField("errWriter"); - b = Log.class.getDeclaredField("warnWriter"); - c = Log.class.getDeclaredField("noticeWriter"); - d = Log.class.getDeclaredField("dumpOnError"); - e = Log.class.getDeclaredField("promptOnError"); - f = Log.class.getDeclaredField("diagListener"); - z = false; - a.setAccessible(true); - b.setAccessible(true); - c.setAccessible(true); - d.setAccessible(true); - e.setAccessible(true); - f.setAccessible(true); - } catch (Throwable x) { - z = true; - } - - try { - g = Log.class.getDeclaredField("deferDiagnostics"); - h = Log.class.getDeclaredField("deferredDiagnostics"); - g.setAccessible(true); - h.setAccessible(true); - } catch (Throwable x) { - } - - errWriterField = a; - warnWriterField = b; - noticeWriterField = c; - dumpOnErrorField = d; - promptOnErrorField = e; - diagnosticListenerField = f; - deferDiagnosticsField = g; - deferredDiagnosticsField = h; - dontBother = z; - } - - LogDisabler(Context context) { - this.log = Log.instance(context); - this.context = context; - } - - boolean disableLoggers() { - contextDiagnosticListener = context.get(DiagnosticListener.class); - context.put(DiagnosticListener.class, (DiagnosticListener<?>) null); - if (dontBother) return false; - boolean dontBotherInstance = false; - - PrintWriter dummyWriter = new PrintWriter(new OutputStream() { - @Override public void write(int b) throws IOException { - // Do nothing on purpose - } - }); - - if (deferDiagnosticsField != null) try { - if (Boolean.TRUE.equals(deferDiagnosticsField.get(log))) { - queueCache.set((Queue<?>) deferredDiagnosticsField.get(log)); - Queue<?> empty = new LinkedList<Object>(); - deferredDiagnosticsField.set(log, empty); - } - } catch (Exception e) {} - - if (!dontBotherInstance) try { - errWriter = (PrintWriter) errWriterField.get(log); - errWriterField.set(log, dummyWriter); - } catch (Exception e) { - dontBotherInstance = true; - } - - if (!dontBotherInstance) try { - warnWriter = (PrintWriter) warnWriterField.get(log); - warnWriterField.set(log, dummyWriter); - } catch (Exception e) { - dontBotherInstance = true; - } - - if (!dontBotherInstance) try { - noticeWriter = (PrintWriter) noticeWriterField.get(log); - noticeWriterField.set(log, dummyWriter); - } catch (Exception e) { - dontBotherInstance = true; - } - - if (!dontBotherInstance) try { - dumpOnError = (Boolean) dumpOnErrorField.get(log); - dumpOnErrorField.set(log, false); - } catch (Exception e) { - dontBotherInstance = true; - } - - if (!dontBotherInstance) try { - promptOnError = (Boolean) promptOnErrorField.get(log); - promptOnErrorField.set(log, false); - } catch (Exception e) { - dontBotherInstance = true; - } - - if (!dontBotherInstance) try { - logDiagnosticListener = (DiagnosticListener<?>) diagnosticListenerField.get(log); - diagnosticListenerField.set(log, null); - } catch (Exception e) { - dontBotherInstance = true; - } - - if (dontBotherInstance) enableLoggers(); - return !dontBotherInstance; - } - - void enableLoggers() { - if (contextDiagnosticListener != null) { - context.put(DiagnosticListener.class, contextDiagnosticListener); - contextDiagnosticListener = null; - } - - if (errWriter != null) try { - errWriterField.set(log, errWriter); - errWriter = null; - } catch (Exception e) {} - - if (warnWriter != null) try { - warnWriterField.set(log, warnWriter); - warnWriter = null; - } catch (Exception e) {} - - if (noticeWriter != null) try { - noticeWriterField.set(log, noticeWriter); - noticeWriter = null; - } catch (Exception e) {} - - if (dumpOnError != null) try { - dumpOnErrorField.set(log, dumpOnError); - dumpOnError = null; - } catch (Exception e) {} - - if (promptOnError != null) try { - promptOnErrorField.set(log, promptOnError); - promptOnError = null; - } catch (Exception e) {} - - if (logDiagnosticListener != null) try { - diagnosticListenerField.set(log, logDiagnosticListener); - logDiagnosticListener = null; - } catch (Exception e) {} - - if (deferDiagnosticsField != null && queueCache.get() != null) try { - deferredDiagnosticsField.set(log, queueCache.get()); - queueCache.set(null); - } catch (Exception e) {} - } + messageSuppressor = new CompilerMessageSuppressor(context); } /* @@ -321,7 +140,7 @@ public class JavacResolution { } } - logDisabler.disableLoggers(); + messageSuppressor.disableLoggers(); try { EnvFinder finder = new EnvFinder(node.getContext()); while (!stack.isEmpty()) stack.pop().accept(finder); @@ -332,7 +151,7 @@ public class JavacResolution { attrib(copy, finder.get()); return mirrorMaker.getOriginalToCopyMap(); } finally { - logDisabler.enableLoggers(); + messageSuppressor.enableLoggers(); } } @@ -347,14 +166,14 @@ public class JavacResolution { } } - logDisabler.disableLoggers(); + messageSuppressor.disableLoggers(); try { EnvFinder finder = new EnvFinder(node.getContext()); while (!stack.isEmpty()) stack.pop().accept(finder); attrib(node.get(), finder.get()); } finally { - logDisabler.enableLoggers(); + messageSuppressor.enableLoggers(); } } @@ -390,7 +209,7 @@ public class JavacResolution { } public static JCExpression createJavaLangObject(JavacAST ast) { - TreeMaker maker = ast.getTreeMaker(); + JavacTreeMaker maker = ast.getTreeMaker(); JCExpression out = maker.Ident(ast.toName("java")); out = maker.Select(out, ast.toName("lang")); out = maker.Select(out, ast.toName("Object")); @@ -417,10 +236,10 @@ public class JavacResolution { // NB: There's such a thing as maker.Type(type), but this doesn't work very well; it screws up anonymous classes, captures, and adds an extra prefix dot for some reason too. // -- so we write our own take on that here. - TreeMaker maker = ast.getTreeMaker(); + JavacTreeMaker maker = ast.getTreeMaker(); - if (type.tag == CTC_BOT) return createJavaLangObject(ast); - if (type.tag == CTC_VOID) return allowVoid ? primitiveToJCTree(type.getKind(), maker) : createJavaLangObject(ast); + if (CTC_BOT.equals(typeTag(type))) return createJavaLangObject(ast); + if (CTC_VOID.equals(typeTag(type))) return allowVoid ? primitiveToJCTree(type.getKind(), maker) : createJavaLangObject(ast); if (type.isPrimitive()) return primitiveToJCTree(type.getKind(), maker); if (type.isErroneous()) throw new TypeNotConvertibleException("Type cannot be resolved"); @@ -434,8 +253,8 @@ public class JavacResolution { if (symbol.name.length() == 0) { // Anonymous inner class if (type instanceof ClassType) { - List<Type> ifaces = ((ClassType)type).interfaces_field; - Type supertype = ((ClassType)type).supertype_field; + List<Type> ifaces = ((ClassType) type).interfaces_field; + Type supertype = ((ClassType) type).supertype_field; if (ifaces != null && ifaces.length() == 1) { return typeToJCTree(ifaces.get(0), ast, allowCompound, allowVoid); } @@ -454,7 +273,7 @@ public class JavacResolution { upper = type.getUpperBound(); } if (allowCompound) { - if (lower == null || lower.tag == CTC_BOT) { + if (lower == null || CTC_BOT.equals(typeTag(lower))) { if (upper == null || upper.toString().equals("java.lang.Object")) { return maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null); } @@ -479,7 +298,7 @@ public class JavacResolution { String qName; if (symbol.isLocal()) { qName = symbol.getSimpleName().toString(); - } else if (symbol.type != null && symbol.type.getEnclosingType() != null && symbol.type.getEnclosingType().tag == TypeTags.CLASS) { + } else if (symbol.type != null && symbol.type.getEnclosingType() != null && typeTag(symbol.type.getEnclosingType()).equals(typeTag("CLASS"))) { replacement = typeToJCTree0(type.getEnclosingType(), ast, false, false); qName = symbol.getSimpleName().toString(); } else { @@ -504,7 +323,7 @@ public class JavacResolution { private static JCExpression genericsToJCTreeNodes(List<Type> generics, JavacAST ast, JCExpression rawTypeNode) throws TypeNotConvertibleException { if (generics != null && !generics.isEmpty()) { - ListBuffer<JCExpression> args = ListBuffer.lb(); + ListBuffer<JCExpression> args = new ListBuffer<JCExpression>(); for (Type t : generics) args.append(typeToJCTree(t, ast, true, false)); return ast.getTreeMaker().TypeApply(rawTypeNode, args.toList()); } @@ -512,12 +331,12 @@ public class JavacResolution { return rawTypeNode; } - private static JCExpression primitiveToJCTree(TypeKind kind, TreeMaker maker) throws TypeNotConvertibleException { + private static JCExpression primitiveToJCTree(TypeKind kind, JavacTreeMaker maker) throws TypeNotConvertibleException { switch (kind) { case BYTE: return maker.TypeIdent(CTC_BYTE); case CHAR: - return maker.TypeIdent(CTC_CHAR); + return maker.TypeIdent( CTC_CHAR); case SHORT: return maker.TypeIdent(CTC_SHORT); case INT: diff --git a/src/core/lombok/javac/LombokOptions.java b/src/core/lombok/javac/LombokOptions.java index 1a73a8cc..f1567e9d 100644 --- a/src/core/lombok/javac/LombokOptions.java +++ b/src/core/lombok/javac/LombokOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 The Project Lombok Authors. + * Copyright (C) 2010-2013 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 @@ -28,18 +28,10 @@ import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Options; -public class LombokOptions extends Options { +public abstract class LombokOptions extends Options { private boolean deleteLombokAnnotations = true; private final Set<JCCompilationUnit> changed = new HashSet<JCCompilationUnit>(); - public static LombokOptions replaceWithDelombokOptions(Context context) { - Options options = Options.instance(context); - context.put(optionsKey, (Options)null); - LombokOptions result = new LombokOptions(context); - result.putAll(options); - return result; - } - public boolean isChanged(JCCompilationUnit ast) { return changed.contains(ast); } @@ -54,7 +46,9 @@ public class LombokOptions extends Options { return (options instanceof LombokOptions) && ((LombokOptions) options).deleteLombokAnnotations; } - private LombokOptions(Context context) { + protected LombokOptions(Context context) { super(context); } + + public abstract void putJavacOption(String optionName, String value); } diff --git a/src/core/lombok/javac/apt/Processor.java b/src/core/lombok/javac/apt/Processor.java index 110acaad..5f28aa88 100644 --- a/src/core/lombok/javac/apt/Processor.java +++ b/src/core/lombok/javac/apt/Processor.java @@ -210,6 +210,7 @@ public class Processor extends AbstractProcessor { Field f = JavacProcessingEnvironment.class.getDeclaredField("processorClassLoader"); f.setAccessible(true); ClassLoader unwrapped = (ClassLoader) f.get(processingEnv); + if (unwrapped == null) return; ClassLoader wrapped = new WrappingClassLoader(unwrapped); f.set(processingEnv, wrapped); } catch (NoSuchFieldException e) { diff --git a/src/core/lombok/javac/handlers/HandleAccessors.java b/src/core/lombok/javac/handlers/HandleAccessors.java index 7aeec6bb..e2489bda 100644 --- a/src/core/lombok/javac/handlers/HandleAccessors.java +++ b/src/core/lombok/javac/handlers/HandleAccessors.java @@ -28,11 +28,13 @@ import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import lombok.core.AnnotationValues; +import lombok.core.HandlerPriority; import lombok.experimental.Accessors; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; @ProviderFor(JavacAnnotationHandler.class) +@HandlerPriority(65536) public class HandleAccessors extends JavacAnnotationHandler<Accessors> { @Override public void handle(AnnotationValues<Accessors> annotation, JCAnnotation ast, JavacNode annotationNode) { // Accessors itself is handled by HandleGetter/Setter; this is just to ensure that the annotation is removed diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 6422f5ed..8a826087 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -41,7 +41,6 @@ import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCTypeApply; import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; @@ -55,10 +54,12 @@ import lombok.experimental.Builder; import lombok.experimental.NonFinal; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; import lombok.javac.handlers.HandleConstructor.SkipIfConstructorExists; -import static lombok.javac.Javac.*; import static lombok.core.handlers.HandlerUtil.*; import static lombok.javac.handlers.JavacHandlerUtil.*; +import static lombok.javac.Javac.*; +import static lombok.javac.JavacTreeMaker.TypeTag.*; @ProviderFor(JavacAnnotationHandler.class) @HandlerPriority(-1024) //-2^10; to ensure we've picked up @FieldDefault's changes (-2048) but @Value hasn't removed itself yet (-512), so that we can error on presence of it on the builder classes. @@ -97,7 +98,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { if (parent.get() instanceof JCClassDecl) { tdParent = parent; JCClassDecl td = (JCClassDecl) tdParent.get(); - ListBuffer<JavacNode> allFields = ListBuffer.lb(); + ListBuffer<JavacNode> allFields = new ListBuffer<JavacNode>(); @SuppressWarnings("deprecation") boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation(lombok.experimental.Value.class, parent)); for (JavacNode fieldNode : HandleConstructor.findAllFields(tdParent)) { @@ -106,7 +107,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { // non-final fields final, but @Value's handler hasn't done this yet, so we have to do this math ourselves. // Value will only skip making a field final if it has an explicit @NonFinal annotation, so we check for that. if (fd.init != null && valuePresent && !hasAnnotation(NonFinal.class, fieldNode)) continue; - namesOfParameters.add(fd.name); + namesOfParameters.add(removePrefixFromField(fieldNode)); typesOfParameters.add(fd.vartype); allFields.append(fieldNode); } @@ -218,12 +219,12 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } private JCMethodDecl generateBuildMethod(String name, Name staticName, JCExpression returnType, java.util.List<Name> fieldNames, JavacNode type, List<JCExpression> thrownExceptions) { - TreeMaker maker = type.getTreeMaker(); + JavacTreeMaker maker = type.getTreeMaker(); JCExpression call; JCStatement statement; - ListBuffer<JCExpression> args = ListBuffer.lb(); + ListBuffer<JCExpression> args = new ListBuffer<JCExpression>(); for (Name n : fieldNames) { args.append(maker.Ident(n)); } @@ -232,14 +233,14 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { call = maker.NewClass(null, List.<JCExpression>nil(), returnType, args.toList(), null); statement = maker.Return(call); } else { - ListBuffer<JCExpression> typeParams = ListBuffer.lb(); + ListBuffer<JCExpression> typeParams = new ListBuffer<JCExpression>(); for (JCTypeParameter tp : ((JCClassDecl) type.get()).typarams) { typeParams.append(maker.Ident(tp.name)); } JCExpression fn = maker.Select(maker.Ident(((JCClassDecl) type.up().get()).name), staticName); call = maker.Apply(typeParams.toList(), fn, args.toList()); - if (returnType instanceof JCPrimitiveTypeTree && ((JCPrimitiveTypeTree) returnType).typetag == CTC_VOID) { + if (returnType instanceof JCPrimitiveTypeTree && CTC_VOID.equals(typeTag(returnType))) { statement = maker.Exec(call); } else { statement = maker.Return(call); @@ -252,9 +253,9 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } private JCMethodDecl generateBuilderMethod(String builderMethodName, String builderClassName, JavacNode type, List<JCTypeParameter> typeParams) { - TreeMaker maker = type.getTreeMaker(); + JavacTreeMaker maker = type.getTreeMaker(); - ListBuffer<JCExpression> typeArgs = ListBuffer.lb(); + ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>(); for (JCTypeParameter typeParam : typeParams) { typeArgs.append(maker.Ident(typeParam.name)); } @@ -285,7 +286,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { continue top; } } - TreeMaker maker = builderType.getTreeMaker(); + JavacTreeMaker maker = builderType.getTreeMaker(); JCModifiers mods = maker.Modifiers(Flags.PRIVATE); JCVariableDecl newField = maker.VarDef(mods, name, cloneType(maker, typesOfParameters.get(i), source), null); out.add(injectField(builderType, newField)); @@ -308,7 +309,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { boolean isBoolean = isBoolean(fieldNode); String setterName = fluent ? fieldNode.getName() : TransformationsUtil.toSetterName(null, fieldNode.getName(), isBoolean); - TreeMaker maker = builderType.getTreeMaker(); + JavacTreeMaker maker = builderType.getTreeMaker(); return HandleSetter.createSetter(Flags.PUBLIC, fieldNode, maker, setterName, chain, source, List.<JCAnnotation>nil(), List.<JCAnnotation>nil()); } @@ -322,9 +323,9 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } private JavacNode makeBuilderClass(JavacNode tdParent, String builderClassName, List<JCTypeParameter> typeParams, JCAnnotation ast) { - TreeMaker maker = tdParent.getTreeMaker(); + JavacTreeMaker maker = tdParent.getTreeMaker(); JCModifiers mods = maker.Modifiers(Flags.PUBLIC | Flags.STATIC); - JCClassDecl builder = ClassDef(maker, mods, tdParent.toName(builderClassName), copyTypeParams(maker, typeParams), null, List.<JCExpression>nil(), List.<JCTree>nil()); + JCClassDecl builder = maker.ClassDef(mods, tdParent.toName(builderClassName), copyTypeParams(maker, typeParams), null, List.<JCExpression>nil(), List.<JCTree>nil()); return injectType(tdParent, builder); } } diff --git a/src/core/lombok/javac/handlers/HandleCleanup.java b/src/core/lombok/javac/handlers/HandleCleanup.java index 09b4faee..e7786ffe 100644 --- a/src/core/lombok/javac/handlers/HandleCleanup.java +++ b/src/core/lombok/javac/handlers/HandleCleanup.java @@ -28,10 +28,10 @@ import lombok.core.AST.Kind; import lombok.core.AnnotationValues; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; import org.mangosdk.spi.ProviderFor; -import com.sun.tools.javac.code.TypeTags; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCAssign; @@ -49,7 +49,6 @@ import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCTypeCast; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; @@ -97,8 +96,8 @@ public class HandleCleanup extends JavacAnnotationHandler<Cleanup> { } boolean seenDeclaration = false; - ListBuffer<JCStatement> newStatements = ListBuffer.lb(); - ListBuffer<JCStatement> tryBlock = ListBuffer.lb(); + ListBuffer<JCStatement> newStatements = new ListBuffer<JCStatement>(); + ListBuffer<JCStatement> tryBlock = new ListBuffer<JCStatement>(); for (JCStatement statement : statements) { if (!seenDeclaration) { if (statement == decl) seenDeclaration = true; @@ -114,7 +113,7 @@ public class HandleCleanup extends JavacAnnotationHandler<Cleanup> { } doAssignmentCheck(annotationNode, tryBlock.toList(), decl.name); - TreeMaker maker = annotationNode.getTreeMaker(); + JavacTreeMaker maker = annotationNode.getTreeMaker(); JCFieldAccess cleanupMethod = maker.Select(maker.Ident(decl.name), annotationNode.toName(cleanupName)); List<JCStatement> cleanupCall = List.<JCStatement>of(maker.Exec( maker.Apply(List.<JCExpression>nil(), cleanupMethod, List.<JCExpression>nil()))); @@ -139,9 +138,9 @@ public class HandleCleanup extends JavacAnnotationHandler<Cleanup> { ancestor.rebuild(); } - private JCMethodInvocation preventNullAnalysis(TreeMaker maker, JavacNode node, JCExpression expression) { + private JCMethodInvocation preventNullAnalysis(JavacTreeMaker maker, JavacNode node, JCExpression expression) { JCMethodInvocation singletonList = maker.Apply(List.<JCExpression>nil(), chainDotsString(node, "java.util.Collections.singletonList"), List.of(expression)); - JCMethodInvocation cleanedExpr = maker.Apply(List.<JCExpression>nil(), maker.Select(singletonList, node.toName("get")) , List.<JCExpression>of(maker.Literal(TypeTags.INT, 0))); + JCMethodInvocation cleanedExpr = maker.Apply(List.<JCExpression>nil(), maker.Select(singletonList, node.toName("get")) , List.<JCExpression>of(maker.Literal(CTC_INT, 0))); return cleanedExpr; } diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java index ecd982e9..b77a5367 100644 --- a/src/core/lombok/javac/handlers/HandleConstructor.java +++ b/src/core/lombok/javac/handlers/HandleConstructor.java @@ -32,12 +32,12 @@ import lombok.core.AST.Kind; import lombok.experimental.Builder; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCAssign; import com.sun.tools.javac.tree.JCTree.JCBlock; @@ -52,6 +52,7 @@ import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.javac.util.Name; public class HandleConstructor { @ProviderFor(JavacAnnotationHandler.class) @@ -90,7 +91,7 @@ public class HandleConstructor { } private static List<JavacNode> findRequiredFields(JavacNode typeNode) { - ListBuffer<JavacNode> fields = ListBuffer.lb(); + ListBuffer<JavacNode> fields = new ListBuffer<JavacNode>(); for (JavacNode child : typeNode.down()) { if (child.getKind() != Kind.FIELD) continue; JCVariableDecl fieldDecl = (JCVariableDecl) child.get(); @@ -125,7 +126,7 @@ public class HandleConstructor { } static List<JavacNode> findAllFields(JavacNode typeNode) { - ListBuffer<JavacNode> fields = ListBuffer.lb(); + ListBuffer<JavacNode> fields = new ListBuffer<JavacNode>(); for (JavacNode child : typeNode.down()) { if (child.getKind() != Kind.FIELD) continue; JCVariableDecl fieldDecl = (JCVariableDecl) child.get(); @@ -206,11 +207,12 @@ public class HandleConstructor { private static void addConstructorProperties(JCModifiers mods, JavacNode node, List<JavacNode> fields) { if (fields.isEmpty()) return; - TreeMaker maker = node.getTreeMaker(); + JavacTreeMaker maker = node.getTreeMaker(); JCExpression constructorPropertiesType = chainDots(node, "java", "beans", "ConstructorProperties"); - ListBuffer<JCExpression> fieldNames = ListBuffer.lb(); + ListBuffer<JCExpression> fieldNames = new ListBuffer<JCExpression>(); for (JavacNode field : fields) { - fieldNames.append(maker.Literal(field.getName())); + Name fieldName = removePrefixFromField(field); + fieldNames.append(maker.Literal(fieldName.toString())); } JCExpression fieldNamesArray = maker.NewArray(null, List.<JCExpression>nil(), fieldNames.toList()); JCAnnotation annotation = maker.Annotation(constructorPropertiesType, List.of(fieldNamesArray)); @@ -218,23 +220,25 @@ public class HandleConstructor { } static JCMethodDecl createConstructor(AccessLevel level, List<JCAnnotation> onConstructor, JavacNode typeNode, List<JavacNode> fields, boolean suppressConstructorProperties, JCTree source) { - TreeMaker maker = typeNode.getTreeMaker(); + JavacTreeMaker maker = typeNode.getTreeMaker(); boolean isEnum = (((JCClassDecl) typeNode.get()).mods.flags & Flags.ENUM) != 0; if (isEnum) level = AccessLevel.PRIVATE; - ListBuffer<JCStatement> nullChecks = ListBuffer.lb(); - ListBuffer<JCStatement> assigns = ListBuffer.lb(); - ListBuffer<JCVariableDecl> params = ListBuffer.lb(); + ListBuffer<JCStatement> nullChecks = new ListBuffer<JCStatement>(); + ListBuffer<JCStatement> assigns = new ListBuffer<JCStatement>(); + ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); for (JavacNode fieldNode : fields) { JCVariableDecl field = (JCVariableDecl) fieldNode.get(); + Name fieldName = removePrefixFromField(fieldNode); + Name rawName = field.name; List<JCAnnotation> nonNulls = findAnnotations(fieldNode, TransformationsUtil.NON_NULL_PATTERN); List<JCAnnotation> nullables = findAnnotations(fieldNode, TransformationsUtil.NULLABLE_PATTERN); - JCVariableDecl param = maker.VarDef(maker.Modifiers(Flags.FINAL, nonNulls.appendList(nullables)), field.name, field.vartype, null); + JCVariableDecl param = maker.VarDef(maker.Modifiers(Flags.FINAL | Flags.PARAMETER, nonNulls.appendList(nullables)), fieldName, field.vartype, null); params.append(param); - JCFieldAccess thisX = maker.Select(maker.Ident(fieldNode.toName("this")), field.name); - JCAssign assign = maker.Assign(thisX, maker.Ident(field.name)); + JCFieldAccess thisX = maker.Select(maker.Ident(fieldNode.toName("this")), rawName); + JCAssign assign = maker.Assign(thisX, maker.Ident(fieldName)); assigns.append(maker.Exec(assign)); if (!nonNulls.isEmpty()) { @@ -261,18 +265,18 @@ public class HandleConstructor { } private JCMethodDecl createStaticConstructor(String name, AccessLevel level, JavacNode typeNode, List<JavacNode> fields, JCTree source) { - TreeMaker maker = typeNode.getTreeMaker(); + JavacTreeMaker maker = typeNode.getTreeMaker(); JCClassDecl type = (JCClassDecl) typeNode.get(); JCModifiers mods = maker.Modifiers(Flags.STATIC | toJavacModifier(level)); JCExpression returnType, constructorType; - ListBuffer<JCTypeParameter> typeParams = ListBuffer.lb(); - ListBuffer<JCVariableDecl> params = ListBuffer.lb(); - ListBuffer<JCExpression> typeArgs1 = ListBuffer.lb(); - ListBuffer<JCExpression> typeArgs2 = ListBuffer.lb(); - ListBuffer<JCExpression> args = ListBuffer.lb(); + ListBuffer<JCTypeParameter> typeParams = new ListBuffer<JCTypeParameter>(); + ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); + ListBuffer<JCExpression> typeArgs1 = new ListBuffer<JCExpression>(); + ListBuffer<JCExpression> typeArgs2 = new ListBuffer<JCExpression>(); + ListBuffer<JCExpression> args = new ListBuffer<JCExpression>(); if (!type.typarams.isEmpty()) { for (JCTypeParameter param : type.typarams) { @@ -289,12 +293,13 @@ public class HandleConstructor { for (JavacNode fieldNode : fields) { JCVariableDecl field = (JCVariableDecl) fieldNode.get(); + Name fieldName = removePrefixFromField(fieldNode); JCExpression pType = cloneType(maker, field.vartype, source); List<JCAnnotation> nonNulls = findAnnotations(fieldNode, TransformationsUtil.NON_NULL_PATTERN); List<JCAnnotation> nullables = findAnnotations(fieldNode, TransformationsUtil.NULLABLE_PATTERN); - JCVariableDecl param = maker.VarDef(maker.Modifiers(Flags.FINAL, nonNulls.appendList(nullables)), field.name, pType, null); + JCVariableDecl param = maker.VarDef(maker.Modifiers(Flags.FINAL | Flags.PARAMETER, nonNulls.appendList(nullables)), fieldName, pType, null); params.append(param); - args.append(maker.Ident(field.name)); + args.append(maker.Ident(fieldName)); } JCReturn returnStatement = maker.Return(maker.NewClass(null, List.<JCExpression>nil(), constructorType, args.toList(), null)); JCBlock body = maker.Block(0, List.<JCStatement>of(returnStatement)); diff --git a/src/core/lombok/javac/handlers/HandleDelegate.java b/src/core/lombok/javac/handlers/HandleDelegate.java index 644b03fb..6af34f20 100644 --- a/src/core/lombok/javac/handlers/HandleDelegate.java +++ b/src/core/lombok/javac/handlers/HandleDelegate.java @@ -48,6 +48,7 @@ import lombok.javac.FindTypeVarScanner; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; import lombok.javac.JavacResolution; +import lombok.javac.JavacTreeMaker; import lombok.javac.ResolutionResetNeeded; import lombok.javac.JavacResolution.TypeNotConvertibleException; @@ -71,7 +72,6 @@ import com.sun.tools.javac.tree.JCTree.JCModifiers; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; @@ -266,7 +266,7 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> { checkConflictOfTypeVarNames(sig, annotation); - TreeMaker maker = annotation.getTreeMaker(); + JavacTreeMaker maker = annotation.getTreeMaker(); com.sun.tools.javac.util.List<JCAnnotation> annotations; if (sig.isDeprecated) { @@ -305,7 +305,7 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> { int idx = 0; for (TypeMirror param : sig.type.getParameterTypes()) { - JCModifiers paramMods = maker.Modifiers(Flags.FINAL); + JCModifiers paramMods = maker.Modifiers(Flags.FINAL | Flags.PARAMETER); String[] paramNames = sig.getParameterNames(); Name name = annotation.toName(paramNames[idx++]); params.append(maker.VarDef(paramMods, name, JavacResolution.typeToJCTree((Type) param, annotation.getAst(), true), null)); @@ -394,13 +394,13 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> { METHOD { public JCExpression get(final JavacNode node, final Name name) { com.sun.tools.javac.util.List<JCExpression> nilExprs = com.sun.tools.javac.util.List.nil(); - final TreeMaker maker = node.getTreeMaker(); + final JavacTreeMaker maker = node.getTreeMaker(); return maker.Apply(nilExprs, maker.Select(maker.Ident(node.toName("this")), name), nilExprs); } }, FIELD { public JCExpression get(final JavacNode node, final Name name) { - final TreeMaker maker = node.getTreeMaker(); + final JavacTreeMaker maker = node.getTreeMaker(); return maker.Select(maker.Ident(node.toName("this")), name); } }; diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index 3b1e226f..0f8161e1 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -31,8 +31,10 @@ import java.util.Collections; import lombok.EqualsAndHashCode; import lombok.core.AST.Kind; import lombok.core.AnnotationValues; +import lombok.javac.Javac; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; import lombok.javac.handlers.JavacHandlerUtil.FieldAccess; import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult; @@ -40,7 +42,6 @@ import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.code.BoundKind; import com.sun.tools.javac.code.Flags; -import com.sun.tools.javac.code.TypeTags; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree; @@ -57,7 +58,6 @@ import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCUnary; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; @@ -139,7 +139,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas } } - JCTree extending = ((JCClassDecl)typeNode.get()).getExtendsClause(); + JCTree extending = Javac.getExtendsClause((JCClassDecl)typeNode.get()); if (extending != null) { String p = extending.toString(); isDirectDescendantOfObject = p.equals("Object") || p.equals("java.lang.Object"); @@ -154,7 +154,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas source.addWarning("Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type."); } - ListBuffer<JavacNode> nodesForEquality = ListBuffer.lb(); + ListBuffer<JavacNode> nodesForEquality = new ListBuffer<JavacNode>(); if (includes != null) { for (JavacNode child : typeNode.down()) { if (child.getKind() != Kind.FIELD) continue; @@ -195,7 +195,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas // The user code couldn't possibly (barring really weird subclassing shenanigans) be in a shippable state anyway; the implementations of these 3 methods are // all inter-related and should be written by the same entity. String msg = String.format("Not generating %s: One of equals, hashCode, and canEqual exists. " + - "You should either write all of these are none of these (in the latter case, lombok generates them).", + "You should either write all of these or none of these (in the latter case, lombok generates them).", equalsExists == MemberExistsResult.NOT_EXISTS && hashCodeExists == MemberExistsResult.NOT_EXISTS ? "equals and hashCode" : equalsExists == MemberExistsResult.NOT_EXISTS ? "equals" : "hashCode"); source.addWarning(msg); @@ -219,12 +219,12 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas } private JCMethodDecl createHashCode(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, FieldAccess fieldAccess, JCTree source) { - TreeMaker maker = typeNode.getTreeMaker(); + JavacTreeMaker maker = typeNode.getTreeMaker(); JCAnnotation overrideAnnotation = maker.Annotation(chainDots(typeNode, "java", "lang", "Override"), List.<JCExpression>nil()); JCModifiers mods = maker.Modifiers(Flags.PUBLIC, List.of(overrideAnnotation)); JCExpression returnType = maker.TypeIdent(CTC_INT); - ListBuffer<JCStatement> statements = ListBuffer.lb(); + ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); Name primeName = typeNode.toName(PRIME_NAME); Name resultName = typeNode.toName(RESULT_NAME); @@ -258,7 +258,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas break; case LONG: { Name dollarFieldName = dollar.append(((JCVariableDecl)fieldNode.get()).name); - statements.append(maker.VarDef(maker.Modifiers(Flags.FINAL), dollarFieldName, maker.TypeIdent(TypeTags.LONG), fieldAccessor)); + statements.append(maker.VarDef(maker.Modifiers(Flags.FINAL), dollarFieldName, maker.TypeIdent(CTC_LONG), fieldAccessor)); statements.append(createResultCalculation(typeNode, longToIntForHashCode(maker, maker.Ident(dollarFieldName), maker.Ident(dollarFieldName)))); } break; @@ -276,7 +276,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas List.<JCExpression>nil(), chainDots(typeNode, "java", "lang", "Double", "doubleToLongBits"), List.of(fieldAccessor)); - statements.append(maker.VarDef(maker.Modifiers(Flags.FINAL), dollarFieldName, maker.TypeIdent(TypeTags.LONG), init)); + statements.append(maker.VarDef(maker.Modifiers(Flags.FINAL), dollarFieldName, maker.TypeIdent(CTC_LONG), init)); statements.append(createResultCalculation(typeNode, longToIntForHashCode(maker, maker.Ident(dollarFieldName), maker.Ident(dollarFieldName)))); } break; @@ -322,7 +322,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas private JCExpressionStatement createResultCalculation(JavacNode typeNode, JCExpression expr) { /* result = result * PRIME + (expr); */ - TreeMaker maker = typeNode.getTreeMaker(); + JavacTreeMaker maker = typeNode.getTreeMaker(); Name resultName = typeNode.toName(RESULT_NAME); JCExpression mult = maker.Binary(CTC_MUL, maker.Ident(resultName), maker.Ident(typeNode.toName(PRIME_NAME))); JCExpression add = maker.Binary(CTC_PLUS, mult, expr); @@ -330,7 +330,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas } /** The 2 references must be clones of each other. */ - private JCExpression longToIntForHashCode(TreeMaker maker, JCExpression ref1, JCExpression ref2) { + private JCExpression longToIntForHashCode(JavacTreeMaker maker, JCExpression ref1, JCExpression ref2) { /* (int)(ref >>> 32 ^ ref) */ JCExpression shift = maker.Binary(CTC_UNSIGNED_SHIFT_RIGHT, ref1, maker.Literal(32)); JCExpression xorBits = maker.Binary(CTC_BITXOR, shift, ref2); @@ -347,7 +347,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas } Collections.reverse(list); - TreeMaker maker = type.getTreeMaker(); + JavacTreeMaker maker = type.getTreeMaker(); JCExpression chain = maker.Ident(type.toName(list.get(0))); for (int i = 1; i < list.size(); i++) { @@ -358,7 +358,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas } private JCMethodDecl createEquals(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, FieldAccess fieldAccess, boolean needsCanEqual, JCTree source) { - TreeMaker maker = typeNode.getTreeMaker(); + JavacTreeMaker maker = typeNode.getTreeMaker(); JCClassDecl type = (JCClassDecl) typeNode.get(); Name oName = typeNode.toName("o"); @@ -370,8 +370,8 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas JCExpression objectType = chainDots(typeNode, "java", "lang", "Object"); JCExpression returnType = maker.TypeIdent(CTC_BOOLEAN); - ListBuffer<JCStatement> statements = ListBuffer.lb(); - final List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(Flags.FINAL), oName, objectType, null)); + ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); + final List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(Flags.FINAL | Flags.PARAMETER), oName, objectType, null)); /* if (o == this) return true; */ { statements.append(maker.If(maker.Binary(CTC_EQUAL, maker.Ident(oName), @@ -379,6 +379,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas } /* if (!(o instanceof Outer.Inner.MyType) return false; */ { + JCUnary notInstanceOf = maker.Unary(CTC_NOT, maker.TypeTest(maker.Ident(oName), createTypeReference(typeNode))); statements.append(maker.If(notInstanceOf, returnBool(maker, false), null)); } @@ -386,8 +387,8 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas /* MyType<?> other = (MyType<?>) o; */ { if (!fields.isEmpty() || needsCanEqual) { final JCExpression selfType1, selfType2; - ListBuffer<JCExpression> wildcards1 = ListBuffer.lb(); - ListBuffer<JCExpression> wildcards2 = ListBuffer.lb(); + ListBuffer<JCExpression> wildcards1 = new ListBuffer<JCExpression>(); + ListBuffer<JCExpression> wildcards2 = new ListBuffer<JCExpression>(); for (int i = 0 ; i < type.typarams.length() ; i++) { wildcards1.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null)); wildcards2.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null)); @@ -493,14 +494,14 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas * return other instanceof Outer.Inner.MyType; * } */ - TreeMaker maker = typeNode.getTreeMaker(); + JavacTreeMaker maker = typeNode.getTreeMaker(); JCModifiers mods = maker.Modifiers(Flags.PUBLIC, List.<JCAnnotation>nil()); JCExpression returnType = maker.TypeIdent(CTC_BOOLEAN); Name canEqualName = typeNode.toName("canEqual"); JCExpression objectType = chainDots(typeNode, "java", "lang", "Object"); Name otherName = typeNode.toName("other"); - List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(Flags.FINAL), otherName, objectType, null)); + List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(Flags.FINAL | Flags.PARAMETER), otherName, objectType, null)); JCBlock body = maker.Block(0, List.<JCStatement>of( maker.Return(maker.TypeTest(maker.Ident(otherName), createTypeReference(typeNode))))); @@ -509,7 +510,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas } private JCStatement generateCompareFloatOrDouble(JCExpression thisDotField, JCExpression otherDotField, - TreeMaker maker, JavacNode node, boolean isDouble) { + JavacTreeMaker maker, JavacNode node, boolean isDouble) { /* if (Float.compare(fieldName, other.fieldName) != 0) return false; */ JCExpression clazz = chainDots(node, "java", "lang", isDouble ? "Double" : "Float"); List<JCExpression> args = List.of(thisDotField, otherDotField); @@ -518,7 +519,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas return maker.If(compareCallEquals0, returnBool(maker, false), null); } - private JCStatement returnBool(TreeMaker maker, boolean bool) { + private JCStatement returnBool(JavacTreeMaker maker, boolean bool) { return maker.Return(maker.Literal(CTC_BOOLEAN, bool ? 1 : 0)); } } diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index 51642f86..4ef23170 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -22,6 +22,7 @@ package lombok.javac.handlers; import static lombok.javac.Javac.*; +import static lombok.javac.JavacTreeMaker.TypeTag.*; import static lombok.javac.handlers.JavacHandlerUtil.*; import java.util.Collection; @@ -37,6 +38,8 @@ import lombok.core.AnnotationValues; import lombok.core.TransformationsUtil; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; +import lombok.javac.JavacTreeMaker.TypeTag; import lombok.javac.handlers.JavacHandlerUtil.FieldAccess; import org.mangosdk.spi.ProviderFor; @@ -57,7 +60,6 @@ import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCSynchronized; import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; @@ -213,7 +215,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), source.get(), lazy, onMethod)); } - private JCMethodDecl createGetter(long access, JavacNode field, TreeMaker treeMaker, JCTree source, boolean lazy, List<JCAnnotation> onMethod) { + private JCMethodDecl createGetter(long access, JavacNode field, JavacTreeMaker treeMaker, JCTree source, boolean lazy, List<JCAnnotation> onMethod) { JCVariableDecl fieldNode = (JCVariableDecl) field.get(); // Remember the type; lazy will change it @@ -268,7 +270,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { } if (!delegates.isEmpty()) { - ListBuffer<JCAnnotation> withoutDelegates = ListBuffer.lb(); + ListBuffer<JCAnnotation> withoutDelegates = new ListBuffer<JCAnnotation>(); for (JCAnnotation annotation : fieldNode.mods.annotations) { if (!delegates.contains(annotation)) { withoutDelegates.append(annotation); @@ -280,7 +282,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { return delegates; } - private List<JCStatement> createSimpleGetterBody(TreeMaker treeMaker, JavacNode field) { + private List<JCStatement> createSimpleGetterBody(JavacTreeMaker treeMaker, JavacNode field) { return List.<JCStatement>of(treeMaker.Return(createFieldAccessor(treeMaker, field, FieldAccess.ALWAYS_FIELD))); } @@ -288,9 +290,9 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { private static final String JLO = "java.lang.Object"; private static final List<JCExpression> NIL_EXPRESSION = List.nil(); - private static final java.util.Map<Integer, String> TYPE_MAP; + private static final java.util.Map<TypeTag, String> TYPE_MAP; static { - Map<Integer, String> m = new HashMap<Integer, String>(); + Map<TypeTag, String> m = new HashMap<TypeTag, String>(); m.put(CTC_INT, "java.lang.Integer"); m.put(CTC_DOUBLE, "java.lang.Double"); m.put(CTC_FLOAT, "java.lang.Float"); @@ -302,7 +304,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { TYPE_MAP = Collections.unmodifiableMap(m); } - private List<JCStatement> createLazyGetterBody(TreeMaker maker, JavacNode fieldNode, JCTree source) { + private List<JCStatement> createLazyGetterBody(JavacTreeMaker maker, JavacNode fieldNode, JCTree source) { /* java.lang.Object value = this.fieldName.get(); if (value == null) { @@ -326,7 +328,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { [END IF] */ - ListBuffer<JCStatement> statements = ListBuffer.lb(); + ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); JCVariableDecl field = (JCVariableDecl) fieldNode.get(); JCExpression copyOfRawFieldType = copyType(maker, field); @@ -334,7 +336,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { field.type = null; boolean isPrimitive = false; if (field.vartype instanceof JCPrimitiveTypeTree) { - String boxed = TYPE_MAP.get(((JCPrimitiveTypeTree)field.vartype).typetag); + String boxed = TYPE_MAP.get(typeTag(field.vartype)); if (boxed != null) { isPrimitive = true; field.vartype = chainDotsString(fieldNode, boxed); @@ -354,14 +356,14 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { /* if (value == null) { */ { JCSynchronized synchronizedStatement; /* synchronized (this.fieldName) { */ { - ListBuffer<JCStatement> synchronizedStatements = ListBuffer.lb(); + ListBuffer<JCStatement> synchronizedStatements = new ListBuffer<JCStatement>(); /* value = this.fieldName.get(); */ { JCExpressionStatement newAssign = maker.Exec(maker.Assign(maker.Ident(valueName), callGet(fieldNode, createFieldAccessor(maker, fieldNode, FieldAccess.ALWAYS_FIELD)))); synchronizedStatements.append(newAssign); } /* if (value == null) { */ { - ListBuffer<JCStatement> innerIfStatements = ListBuffer.lb(); + ListBuffer<JCStatement> innerIfStatements = new ListBuffer<JCStatement>(); /* final RawValueType actualValue = INITIALIZER_EXPRESSION; */ { innerIfStatements.append(maker.VarDef(maker.Modifiers(Flags.FINAL), actualValueName, copyOfRawFieldType, field.init)); } @@ -423,16 +425,16 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { } private JCMethodInvocation callGet(JavacNode source, JCExpression receiver) { - TreeMaker maker = source.getTreeMaker(); + JavacTreeMaker maker = source.getTreeMaker(); return maker.Apply(NIL_EXPRESSION, maker.Select(receiver, source.toName("get")), NIL_EXPRESSION); } private JCStatement callSet(JavacNode source, JCExpression receiver, JCExpression value) { - TreeMaker maker = source.getTreeMaker(); + JavacTreeMaker maker = source.getTreeMaker(); return maker.Exec(maker.Apply(NIL_EXPRESSION, maker.Select(receiver, source.toName("set")), List.<JCExpression>of(value))); } - private JCExpression copyType(TreeMaker treeMaker, JCVariableDecl fieldNode) { + private JCExpression copyType(JavacTreeMaker treeMaker, JCVariableDecl fieldNode) { return fieldNode.type != null ? treeMaker.Type(fieldNode.type) : fieldNode.vartype; } } diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java index 35a32be5..31478b66 100644 --- a/src/core/lombok/javac/handlers/HandleLog.java +++ b/src/core/lombok/javac/handlers/HandleLog.java @@ -28,12 +28,12 @@ import java.lang.annotation.Annotation; import lombok.core.AnnotationValues; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCExpression; @@ -74,13 +74,13 @@ public class HandleLog { } private static JCFieldAccess selfType(JavacNode typeNode) { - TreeMaker maker = typeNode.getTreeMaker(); + JavacTreeMaker maker = typeNode.getTreeMaker(); Name name = ((JCClassDecl) typeNode.get()).name; return maker.Select(maker.Ident(name), typeNode.toName("class")); } private static boolean createField(LoggingFramework framework, JavacNode typeNode, JCFieldAccess loggingType, JCTree source) { - TreeMaker maker = typeNode.getTreeMaker(); + JavacTreeMaker maker = typeNode.getTreeMaker(); // private static final <loggerType> log = <factoryMethod>(<parameter>); JCExpression loggerType = chainDotsString(typeNode, framework.getLoggerTypeName()); @@ -164,7 +164,7 @@ public class HandleLog { // private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(TargetType.class.getName()); JUL(lombok.extern.java.Log.class, "java.util.logging.Logger", "java.util.logging.Logger.getLogger") { @Override public JCExpression createFactoryParameter(JavacNode typeNode, JCFieldAccess loggingType) { - TreeMaker maker = typeNode.getTreeMaker(); + JavacTreeMaker maker = typeNode.getTreeMaker(); JCExpression method = maker.Select(loggingType, typeNode.toName("getName")); return maker.Apply(List.<JCExpression>nil(), method, List.<JCExpression>nil()); } diff --git a/src/core/lombok/javac/handlers/NonNullHandler.java b/src/core/lombok/javac/handlers/HandleNonNull.java index 415d6032..21611a39 100644 --- a/src/core/lombok/javac/handlers/NonNullHandler.java +++ b/src/core/lombok/javac/handlers/HandleNonNull.java @@ -36,18 +36,24 @@ import com.sun.tools.javac.tree.JCTree.JCLiteral; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCParens; import com.sun.tools.javac.tree.JCTree.JCStatement; +import com.sun.tools.javac.tree.JCTree.JCSynchronized; import com.sun.tools.javac.tree.JCTree.JCThrow; +import com.sun.tools.javac.tree.JCTree.JCTry; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.List; import lombok.NonNull; 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) -public class NonNullHandler extends JavacAnnotationHandler<NonNull> { +@HandlerPriority(value = 512) // 2^9; onParameter=@__(@NonNull) has to run first. +public class HandleNonNull extends JavacAnnotationHandler<NonNull> { @Override public void handle(AnnotationValues<NonNull> annotation, JCAnnotation ast, JavacNode annotationNode) { if (annotationNode.up().getKind() == Kind.FIELD) { // This is meaningless unless the field is used to generate a method (@Setter, @RequiredArgsConstructor, etc), @@ -74,7 +80,12 @@ public class NonNullHandler extends JavacAnnotationHandler<NonNull> { return; } - if (JavacHandlerUtil.isGenerated(declaration)) return; +// if (JavacHandlerUtil.isGenerated(declaration)) return; + + if (declaration.body == null) { + annotationNode.addWarning("@NonNull is meaningless on a parameter of an abstract method."); + return; + } // Possibly, if 'declaration instanceof ConstructorDeclaration', fetch declaration.constructorCall, search it for any references to our parameter, // and if they exist, create a new method in the class: 'private static <T> T lombok$nullCheck(T expr, String msg) {if (expr == null) throw NPE; return expr;}' and @@ -91,17 +102,33 @@ public class NonNullHandler extends JavacAnnotationHandler<NonNull> { List<JCStatement> statements = declaration.body.stats; String expectedName = annotationNode.up().getName(); - for (JCStatement stat : statements) { - if (JavacHandlerUtil.isConstructorCall(stat)) continue; - String varNameOfNullCheck = returnVarNameIfNullCheck(stat); - if (varNameOfNullCheck == null) break; - if (varNameOfNullCheck.equals(expectedName)) return; + + /* Abort if the null check is already there, delving into try and synchronized statements */ { + List<JCStatement> stats = statements; + int idx = 0; + while (stats.size() > idx) { + JCStatement stat = stats.get(idx++); + if (JavacHandlerUtil.isConstructorCall(stat)) continue; + if (stat instanceof JCTry) { + stats = ((JCTry) stat).body.stats; + idx = 0; + continue; + } + if (stat instanceof JCSynchronized) { + stats = ((JCSynchronized) stat).body.stats; + idx = 0; + continue; + } + String varNameOfNullCheck = returnVarNameIfNullCheck(stat); + if (varNameOfNullCheck == null) break; + if (varNameOfNullCheck.equals(expectedName)) return; + } } List<JCStatement> tail = statements; List<JCStatement> head = List.nil(); for (JCStatement stat : statements) { - if (JavacHandlerUtil.isConstructorCall(stat) || JavacHandlerUtil.isGenerated(stat)) { + if (JavacHandlerUtil.isConstructorCall(stat) || (JavacHandlerUtil.isGenerated(stat) && isNullCheck(stat))) { tail = tail.tail; head = head.prepend(stat); continue; @@ -114,6 +141,10 @@ public class NonNullHandler extends JavacAnnotationHandler<NonNull> { declaration.body.stats = newList; } + private boolean isNullCheck(JCStatement stat) { + return returnVarNameIfNullCheck(stat) != null; + } + /** * Checks if the statement is of the form 'if (x == null) {throw WHATEVER;}, * where the block braces are optional. If it is of this form, returns "x". @@ -138,10 +169,10 @@ public class NonNullHandler extends JavacAnnotationHandler<NonNull> { while (cond instanceof JCParens) cond = ((JCParens) cond).expr; if (!(cond instanceof JCBinary)) return null; JCBinary bin = (JCBinary) cond; - if (getTag(bin) != CTC_EQUAL) return null; + if (!CTC_EQUAL.equals(treeTag(bin))) return null; if (!(bin.lhs instanceof JCIdent)) return null; if (!(bin.rhs instanceof JCLiteral)) return null; - if (((JCLiteral) bin.rhs).typetag != CTC_BOT) return null; + if (!CTC_BOT.equals(typeTag(bin.rhs))) return null; return ((JCIdent) bin.lhs).name.toString(); } } diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index 282e6c2f..c4977b2b 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -26,23 +26,20 @@ import static lombok.javac.handlers.JavacHandlerUtil.*; import java.util.Collection; -import javax.lang.model.type.NoType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeVisitor; - import lombok.AccessLevel; import lombok.Setter; import lombok.core.AST.Kind; import lombok.core.AnnotationValues; import lombok.core.TransformationsUtil; +import lombok.javac.Javac; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; import lombok.javac.handlers.JavacHandlerUtil.FieldAccess; import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.code.Flags; -import com.sun.tools.javac.code.Type; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCAssign; @@ -54,7 +51,6 @@ import com.sun.tools.javac.tree.JCTree.JCReturn; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; @@ -194,13 +190,13 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { injectMethod(fieldNode.up(), createdSetter); } - static JCMethodDecl createSetter(long access, JavacNode field, TreeMaker treeMaker, JCTree source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { + static JCMethodDecl createSetter(long access, JavacNode field, JavacTreeMaker treeMaker, JCTree source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { String setterName = toSetterName(field); boolean returnThis = shouldReturnThis(field); return createSetter(access, field, treeMaker, setterName, returnThis, source, onMethod, onParam); } - static JCMethodDecl createSetter(long access, JavacNode field, TreeMaker treeMaker, String setterName, boolean shouldReturnThis, JCTree source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { + static JCMethodDecl createSetter(long access, JavacNode field, JavacTreeMaker treeMaker, String setterName, boolean shouldReturnThis, JCTree source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { if (setterName == null) return null; JCVariableDecl fieldDecl = (JCVariableDecl) field.get(); @@ -208,14 +204,14 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { JCExpression fieldRef = createFieldAccessor(treeMaker, field, FieldAccess.ALWAYS_FIELD); JCAssign assign = treeMaker.Assign(fieldRef, treeMaker.Ident(fieldDecl.name)); - ListBuffer<JCStatement> statements = ListBuffer.lb(); + ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); List<JCAnnotation> nonNulls = findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN); List<JCAnnotation> nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN); Name methodName = field.toName(setterName); List<JCAnnotation> annsOnParam = copyAnnotations(onParam).appendList(nonNulls).appendList(nullables); - JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(Flags.FINAL, annsOnParam), fieldDecl.name, fieldDecl.vartype, null); + JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(Flags.FINAL | Flags.PARAMETER, annsOnParam), fieldDecl.name, fieldDecl.vartype, null); if (nonNulls.isEmpty()) { statements.append(treeMaker.Exec(assign)); @@ -232,7 +228,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { if (methodType == null) { //WARNING: Do not use field.getSymbolTable().voidType - that field has gone through non-backwards compatible API changes within javac1.6. - methodType = treeMaker.Type(new JCNoType(CTC_VOID)); + methodType = treeMaker.Type(Javac.createVoidType(treeMaker, CTC_VOID)); shouldReturnThis = false; } @@ -257,22 +253,4 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { copyJavadoc(field, decl, CopyJavadoc.SETTER); return decl; } - - private static class JCNoType extends Type implements NoType { - public JCNoType(int tag) { - super(tag, null); - } - - @Override - public TypeKind getKind() { - if (tag == CTC_VOID) return TypeKind.VOID; - if (tag == CTC_NONE) return TypeKind.NONE; - throw new AssertionError("Unexpected tag: " + tag); - } - - @Override - public <R, P> R accept(TypeVisitor<R, P> v, P p) { - return v.visitNoType(this, p); - } - } } diff --git a/src/core/lombok/javac/handlers/HandleSneakyThrows.java b/src/core/lombok/javac/handlers/HandleSneakyThrows.java index c818f630..b41277c3 100644 --- a/src/core/lombok/javac/handlers/HandleSneakyThrows.java +++ b/src/core/lombok/javac/handlers/HandleSneakyThrows.java @@ -29,14 +29,15 @@ import java.util.Collections; import lombok.SneakyThrows; import lombok.core.AnnotationValues; +import lombok.core.HandlerPriority; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCExpression; @@ -49,6 +50,7 @@ import com.sun.tools.javac.util.List; * Handles the {@code lombok.SneakyThrows} annotation for javac. */ @ProviderFor(JavacAnnotationHandler.class) +@HandlerPriority(value = 1024) // 2^10; @NonNull must have run first, so that we wrap around the statements generated by it. public class HandleSneakyThrows extends JavacAnnotationHandler<SneakyThrows> { @Override public void handle(AnnotationValues<SneakyThrows> annotation, JCAnnotation ast, JavacNode annotationNode) { deleteAnnotationIfNeccessary(annotationNode, SneakyThrows.class); @@ -113,7 +115,7 @@ public class HandleSneakyThrows extends JavacAnnotationHandler<SneakyThrows> { } private JCStatement buildTryCatchBlock(JavacNode node, List<JCStatement> contents, String exception, JCTree source) { - TreeMaker maker = node.getTreeMaker(); + JavacTreeMaker maker = node.getTreeMaker(); JCBlock tryBlock = setGeneratedBy(maker.Block(0, contents), source); diff --git a/src/core/lombok/javac/handlers/HandleSynchronized.java b/src/core/lombok/javac/handlers/HandleSynchronized.java index 2bca49e9..661a7c2a 100644 --- a/src/core/lombok/javac/handlers/HandleSynchronized.java +++ b/src/core/lombok/javac/handlers/HandleSynchronized.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2012 The Project Lombok Authors. + * Copyright (C) 2009-2013 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 @@ -26,8 +26,10 @@ import static lombok.javac.handlers.JavacHandlerUtil.*; import lombok.Synchronized; import lombok.core.AST.Kind; import lombok.core.AnnotationValues; +import lombok.core.HandlerPriority; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult; import org.mangosdk.spi.ProviderFor; @@ -39,13 +41,13 @@ import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCNewArray; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.util.List; /** * Handles the {@code lombok.Synchronized} annotation for javac. */ @ProviderFor(JavacAnnotationHandler.class) +@HandlerPriority(value = 1024) // 2^10; @NonNull must have run first, so that we wrap around the statements generated by it. public class HandleSynchronized extends JavacAnnotationHandler<Synchronized> { private static final String INSTANCE_LOCK_NAME = "$lock"; private static final String STATIC_LOCK_NAME = "$LOCK"; @@ -77,7 +79,7 @@ public class HandleSynchronized extends JavacAnnotationHandler<Synchronized> { lockName = isStatic ? STATIC_LOCK_NAME : INSTANCE_LOCK_NAME; } - TreeMaker maker = methodNode.getTreeMaker().at(ast.pos); + JavacTreeMaker maker = methodNode.getTreeMaker().at(ast.pos); if (fieldExists(lockName, methodNode) == MemberExistsResult.NOT_EXISTS) { if (!autoMake) { diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java index 333393da..9bd5b920 100644 --- a/src/core/lombok/javac/handlers/HandleToString.java +++ b/src/core/lombok/javac/handlers/HandleToString.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2012 The Project Lombok Authors. + * Copyright (C) 2009-2013 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 @@ -31,12 +31,12 @@ import lombok.core.AnnotationValues; import lombok.core.AST.Kind; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree; import com.sun.tools.javac.tree.JCTree.JCBlock; @@ -129,7 +129,7 @@ public class HandleToString extends JavacAnnotationHandler<ToString> { return; } - ListBuffer<JavacNode> nodesForToString = ListBuffer.lb(); + ListBuffer<JavacNode> nodesForToString = new ListBuffer<JavacNode>(); if (includes != null) { for (JavacNode child : typeNode.down()) { if (child.getKind() != Kind.FIELD) continue; @@ -167,7 +167,7 @@ public class HandleToString extends JavacAnnotationHandler<ToString> { } static JCMethodDecl createToString(JavacNode typeNode, Collection<JavacNode> fields, boolean includeFieldNames, boolean callSuper, FieldAccess fieldAccess, JCTree source) { - TreeMaker maker = typeNode.getTreeMaker(); + JavacTreeMaker maker = typeNode.getTreeMaker(); JCAnnotation overrideAnnotation = maker.Annotation(chainDots(typeNode, "java", "lang", "Override"), List.<JCExpression>nil()); JCModifiers mods = maker.Modifiers(Flags.PUBLIC, List.of(overrideAnnotation)); diff --git a/src/core/lombok/javac/handlers/HandleWither.java b/src/core/lombok/javac/handlers/HandleWither.java index b3f218b8..9cfa4531 100644 --- a/src/core/lombok/javac/handlers/HandleWither.java +++ b/src/core/lombok/javac/handlers/HandleWither.java @@ -33,6 +33,7 @@ import lombok.core.TransformationsUtil; import lombok.experimental.Wither; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; import lombok.javac.handlers.JavacHandlerUtil.CopyJavadoc; import lombok.javac.handlers.JavacHandlerUtil.FieldAccess; @@ -51,7 +52,6 @@ import com.sun.tools.javac.tree.JCTree.JCReturn; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; @@ -201,27 +201,25 @@ public class HandleWither extends JavacAnnotationHandler<Wither> { injectMethod(fieldNode.up(), createdWither); } - private JCMethodDecl createWither(long access, JavacNode field, TreeMaker treeMaker, JCTree source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { + private JCMethodDecl createWither(long access, JavacNode field, JavacTreeMaker maker, JCTree source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { String witherName = toWitherName(field); if (witherName == null) return null; JCVariableDecl fieldDecl = (JCVariableDecl) field.get(); - ListBuffer<JCStatement> statements = ListBuffer.lb(); + ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); List<JCAnnotation> nonNulls = findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN); List<JCAnnotation> nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN); Name methodName = field.toName(witherName); List<JCAnnotation> annsOnParam = copyAnnotations(onParam).appendList(nonNulls).appendList(nullables); - JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(Flags.FINAL, annsOnParam), fieldDecl.name, fieldDecl.vartype, null); + JCVariableDecl param = maker.VarDef(maker.Modifiers(Flags.FINAL | Flags.PARAMETER, annsOnParam), fieldDecl.name, fieldDecl.vartype, null); JCExpression selfType = cloneSelfType(field); if (selfType == null) return null; - TreeMaker maker = field.getTreeMaker(); - - ListBuffer<JCExpression> args = ListBuffer.lb(); + ListBuffer<JCExpression> args = new ListBuffer<JCExpression>(); for (JavacNode child : field.up().down()) { if (child.getKind() != Kind.FIELD) continue; JCVariableDecl childDecl = (JCVariableDecl) child.get(); @@ -247,14 +245,14 @@ public class HandleWither extends JavacAnnotationHandler<Wither> { if (nonNulls.isEmpty()) { statements.append(returnStatement); } else { - JCStatement nullCheck = generateNullCheck(treeMaker, field); + JCStatement nullCheck = generateNullCheck(maker, field); if (nullCheck != null) statements.append(nullCheck); statements.append(returnStatement); } JCExpression returnType = cloneSelfType(field); - JCBlock methodBody = treeMaker.Block(0, statements.toList()); + JCBlock methodBody = maker.Block(0, statements.toList()); List<JCTypeParameter> methodGenericParams = List.nil(); List<JCVariableDecl> parameters = List.of(param); List<JCExpression> throwsClauses = List.nil(); @@ -263,9 +261,9 @@ public class HandleWither extends JavacAnnotationHandler<Wither> { List<JCAnnotation> annsOnMethod = copyAnnotations(onMethod); if (isFieldDeprecated(field)) { - annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(chainDots(field, "java", "lang", "Deprecated"), List.<JCExpression>nil())); + annsOnMethod = annsOnMethod.prepend(maker.Annotation(chainDots(field, "java", "lang", "Deprecated"), List.<JCExpression>nil())); } - JCMethodDecl decl = recursiveSetGeneratedBy(treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, returnType, + JCMethodDecl decl = recursiveSetGeneratedBy(maker.MethodDef(maker.Modifiers(access, annsOnMethod), methodName, returnType, methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source); copyJavadoc(field, decl, CopyJavadoc.WITHER); return decl; diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index d7d29da2..50e80169 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -44,10 +44,14 @@ import lombok.core.AnnotationValues.AnnotationValue; import lombok.core.TransformationsUtil; import lombok.core.TypeResolver; import lombok.experimental.Accessors; +import lombok.javac.Javac; import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; import com.sun.tools.javac.code.BoundKind; import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.parser.Tokens.Comment; +import com.sun.tools.javac.tree.DocCommentTable; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree; @@ -72,7 +76,6 @@ import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.tree.JCTree.JCWildcard; import com.sun.tools.javac.tree.JCTree.TypeBoundKind; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.tree.TreeScanner; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; @@ -96,6 +99,7 @@ public class JavacHandlerUtil { } @Override public void scan(JCTree tree) { + if (tree == null) return; setGeneratedBy(tree, source); super.scan(tree); } @@ -133,10 +137,12 @@ public class JavacHandlerUtil { } public static <T extends JCTree> T setGeneratedBy(T node, JCTree source) { + if (node == null) return null; synchronized (generatedNodes) { if (source == null) generatedNodes.remove(node); else generatedNodes.put(node, new WeakReference<JCTree>(source)); } + if (source != null) node.pos = source.pos; return node; } @@ -213,6 +219,17 @@ public class JavacHandlerUtil { } /** + * Returns if a node is marked deprecated (as picked up on by the parser). + * @param node the node to check (type, method, or field decl). + */ + public static boolean nodeHasDeprecatedFlag(JCTree node) { + if (node instanceof JCVariableDecl) return (((JCVariableDecl) node).mods.flags & Flags.DEPRECATED) != 0; + if (node instanceof JCMethodDecl) return (((JCMethodDecl) node).mods.flags & Flags.DEPRECATED) != 0; + if (node instanceof JCClassDecl) return (((JCClassDecl) node).mods.flags & Flags.DEPRECATED) != 0; + return false; + } + + /** * Creates an instance of {@code AnnotationValues} for the provided AST Node. * * @param type An annotation class type, such as {@code lombok.Getter.class}. @@ -334,7 +351,7 @@ public class JavacHandlerUtil { public static void deleteImportFromCompilationUnit(JavacNode node, String name) { if (inNetbeansEditor(node)) return; if (!node.shouldDeleteLombokAnnotations()) return; - ListBuffer<JCTree> newDefs = ListBuffer.lb(); + ListBuffer<JCTree> newDefs = new ListBuffer<JCTree>(); JCCompilationUnit unit = (JCCompilationUnit) node.top().get(); @@ -350,7 +367,7 @@ public class JavacHandlerUtil { } private static List<JCAnnotation> filterList(List<JCAnnotation> annotations, JCTree jcTree) { - ListBuffer<JCAnnotation> newAnnotations = ListBuffer.lb(); + ListBuffer<JCAnnotation> newAnnotations = new ListBuffer<JCAnnotation>(); for (JCAnnotation ann : annotations) { if (jcTree != ann) newAnnotations.append(ann); } @@ -429,11 +446,11 @@ public class JavacHandlerUtil { public static JCExpression cloneSelfType(JavacNode field) { JavacNode typeNode = field; - TreeMaker maker = field.getTreeMaker(); + JavacTreeMaker maker = field.getTreeMaker(); while (typeNode != null && typeNode.getKind() != Kind.TYPE) typeNode = typeNode.up(); if (typeNode != null && typeNode.get() instanceof JCClassDecl) { JCClassDecl type = (JCClassDecl) typeNode.get(); - ListBuffer<JCExpression> typeArgs = ListBuffer.lb(); + ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>(); if (!type.typarams.isEmpty()) { for (JCTypeParameter tp : type.typarams) { typeArgs.append(maker.Ident(tp.name)); @@ -456,6 +473,37 @@ public class JavacHandlerUtil { return varType != null && varType.toString().equals("boolean"); } + public static Name removePrefixFromField(JavacNode field) { + String[] prefixes = null; + for (JavacNode node : field.down()) { + if (annotationTypeMatches(Accessors.class, node)) { + prefixes = createAnnotation(Accessors.class, node).getInstance().prefix(); + break; + } + } + + if (prefixes == null) { + JavacNode current = field.up(); + outer: + while (current != null) { + for (JavacNode node : current.down()) { + if (annotationTypeMatches(Accessors.class, node)) { + prefixes = createAnnotation(Accessors.class, node).getInstance().prefix(); + break outer; + } + } + current = current.up(); + } + } + + if (prefixes != null && prefixes.length > 0) { + CharSequence newName = TransformationsUtil.removePrefix(field.getName(), prefixes); + if (newName != null) return field.toName(newName.toString()); + } + + return ((JCVariableDecl) field.get()).name; + } + public static AnnotationValues<Accessors> getAccessorsForField(JavacNode field) { for (JavacNode node : field.down()) { if (annotationTypeMatches(Accessors.class, node)) { @@ -707,11 +755,11 @@ public class JavacHandlerUtil { /** * Creates an expression that reads the field. Will either be {@code this.field} or {@code this.getField()} depending on whether or not there's a getter. */ - static JCExpression createFieldAccessor(TreeMaker maker, JavacNode field, FieldAccess fieldAccess) { + static JCExpression createFieldAccessor(JavacTreeMaker maker, JavacNode field, FieldAccess fieldAccess) { return createFieldAccessor(maker, field, fieldAccess, null); } - static JCExpression createFieldAccessor(TreeMaker maker, JavacNode field, FieldAccess fieldAccess, JCExpression receiver) { + static JCExpression createFieldAccessor(JavacTreeMaker maker, JavacNode field, FieldAccess fieldAccess, JCExpression receiver) { boolean lookForGetter = lookForGetter(field, fieldAccess); GetterMethod getter = lookForGetter ? findGetter(field) : null; @@ -839,7 +887,7 @@ public class JavacHandlerUtil { } private static void addSuppressWarningsAll(JCModifiers mods, JavacNode node, int pos, JCTree source) { - TreeMaker maker = node.getTreeMaker(); + JavacTreeMaker maker = node.getTreeMaker(); JCExpression suppressWarningsType = chainDots(node, "java", "lang", "SuppressWarnings"); JCLiteral allLiteral = maker.Literal("all"); suppressWarningsType.pos = pos; @@ -850,7 +898,7 @@ public class JavacHandlerUtil { } private static List<JCTree> addAllButOne(List<JCTree> defs, int idx) { - ListBuffer<JCTree> out = ListBuffer.lb(); + ListBuffer<JCTree> out = new ListBuffer<JCTree>(); int i = 0; for (JCTree def : defs) { if (i++ != idx) out.append(def); @@ -890,7 +938,7 @@ public class JavacHandlerUtil { assert elems != null; assert elems.length > 0; - TreeMaker maker = node.getTreeMaker(); + JavacTreeMaker maker = node.getTreeMaker(); if (pos != -1) maker = maker.at(pos); JCExpression e = maker.Ident(node.toName(elems[0])); for (int i = 1 ; i < elems.length ; i++) { @@ -921,7 +969,7 @@ public class JavacHandlerUtil { * Only the simple name is checked - the package and any containing class are ignored. */ public static List<JCAnnotation> findAnnotations(JavacNode fieldNode, Pattern namePattern) { - ListBuffer<JCAnnotation> result = ListBuffer.lb(); + ListBuffer<JCAnnotation> result = new ListBuffer<JCAnnotation>(); for (JavacNode child : fieldNode.down()) { if (child.getKind() == Kind.ANNOTATION) { JCAnnotation annotation = (JCAnnotation) child.get(); @@ -940,15 +988,15 @@ public class JavacHandlerUtil { * Generates a new statement that checks if the given variable is null, and if so, throws a {@code NullPointerException} with the * variable name as message. */ - public static JCStatement generateNullCheck(TreeMaker treeMaker, JavacNode variable) { + public static JCStatement generateNullCheck(JavacTreeMaker maker, JavacNode variable) { JCVariableDecl varDecl = (JCVariableDecl) variable.get(); if (isPrimitive(varDecl.vartype)) return null; Name fieldName = varDecl.name; JCExpression npe = chainDots(variable, "java", "lang", "NullPointerException"); - JCTree exception = treeMaker.NewClass(null, List.<JCExpression>nil(), npe, List.<JCExpression>of(treeMaker.Literal(fieldName.toString())), null); - JCStatement throwStatement = treeMaker.Throw(exception); - JCBlock throwBlock = treeMaker.Block(0, List.of(throwStatement)); - return treeMaker.If(treeMaker.Binary(CTC_EQUAL, treeMaker.Ident(fieldName), treeMaker.Literal(CTC_BOT, null)), throwBlock, null); + JCExpression exception = maker.NewClass(null, List.<JCExpression>nil(), npe, List.<JCExpression>of(maker.Literal(fieldName.toString())), 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); } /** @@ -971,7 +1019,7 @@ public class JavacHandlerUtil { if (idx > -1) matched[idx] = true; } - ListBuffer<Integer> problematic = ListBuffer.lb(); + ListBuffer<Integer> problematic = new ListBuffer<Integer>(); for (int i = 0 ; i < list.size() ; i++) { if (!matched[i]) problematic.append(i); } @@ -980,8 +1028,8 @@ public class JavacHandlerUtil { } static List<JCAnnotation> unboxAndRemoveAnnotationParameter(JCAnnotation ast, String parameterName, String errorName, JavacNode errorNode) { - ListBuffer<JCExpression> params = ListBuffer.lb(); - ListBuffer<JCAnnotation> result = ListBuffer.lb(); + ListBuffer<JCExpression> params = new ListBuffer<JCExpression>(); + ListBuffer<JCAnnotation> result = new ListBuffer<JCAnnotation>(); errorNode.removeDeferredErrors(); @@ -1005,9 +1053,9 @@ public class JavacHandlerUtil { if (valueOfParam instanceof JCAnnotation) { String dummyAnnotationName = ((JCAnnotation) valueOfParam).annotationType.toString(); - dummyAnnotationName = dummyAnnotationName.replace("_", ""); + dummyAnnotationName = dummyAnnotationName.replace("_", "").replace("$", "").replace("x", "").replace("X", ""); if (dummyAnnotationName.length() > 0) { - errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))"); continue outer; } for (JCExpression expr : ((JCAnnotation) valueOfParam).args) { @@ -1016,7 +1064,7 @@ public class JavacHandlerUtil { if ("value".equals(id.name.toString())) { expr = ((JCAssign) expr).rhs; } else { - errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))"); continue outer; } } @@ -1028,12 +1076,12 @@ public class JavacHandlerUtil { if (expr2 instanceof JCAnnotation) { result.append((JCAnnotation) expr2); } else { - errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))"); continue outer; } } } else { - errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))"); continue outer; } } @@ -1041,7 +1089,7 @@ public class JavacHandlerUtil { if (valueOfParam instanceof JCNewArray && ((JCNewArray) valueOfParam).elems.isEmpty()) { // Then we just remove it and move on (it's onMethod={} for example). } else { - errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))"); } } } @@ -1049,15 +1097,15 @@ public class JavacHandlerUtil { return result.toList(); } - public static List<JCTypeParameter> copyTypeParams(TreeMaker maker, List<JCTypeParameter> params) { + public static List<JCTypeParameter> copyTypeParams(JavacTreeMaker maker, List<JCTypeParameter> params) { if (params == null || params.isEmpty()) return params; - ListBuffer<JCTypeParameter> out = ListBuffer.lb(); + ListBuffer<JCTypeParameter> out = new ListBuffer<JCTypeParameter>(); for (JCTypeParameter tp : params) out.append(maker.TypeParameter(tp.name, tp.bounds)); return out.toList(); } - public static JCExpression namePlusTypeParamsToTypeReference(TreeMaker maker, Name typeName, List<JCTypeParameter> params) { - ListBuffer<JCExpression> typeArgs = ListBuffer.lb(); + public static JCExpression namePlusTypeParamsToTypeReference(JavacTreeMaker maker, Name typeName, List<JCTypeParameter> params) { + ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>(); if (!params.isEmpty()) { for (JCTypeParameter param : params) { @@ -1093,7 +1141,7 @@ public class JavacHandlerUtil { } static List<JCAnnotation> copyAnnotations(List<? extends JCExpression> in) { - ListBuffer<JCAnnotation> out = ListBuffer.lb(); + ListBuffer<JCAnnotation> out = new ListBuffer<JCAnnotation>(); for (JCExpression expr : in) { if (!(expr instanceof JCAnnotation)) continue; out.append((JCAnnotation) expr.clone()); @@ -1135,13 +1183,13 @@ public class JavacHandlerUtil { * the class's own parameter, but as its a static method, the static method's notion of {@code T} is different from the class notion of {@code T}. If you're duplicating * a type used in the class context, you need to use this method. */ - public static JCExpression cloneType(TreeMaker maker, JCExpression in, JCTree source) { + public static JCExpression cloneType(JavacTreeMaker maker, JCExpression in, JCTree source) { JCExpression out = cloneType0(maker, in); if (out != null) recursiveSetGeneratedBy(out, source); return out; } - private static JCExpression cloneType0(TreeMaker maker, JCTree in) { + private static JCExpression cloneType0(JavacTreeMaker maker, JCTree in) { if (in == null) return null; if (in instanceof JCPrimitiveTypeTree) return (JCExpression) in; @@ -1162,7 +1210,7 @@ public class JavacHandlerUtil { if (in instanceof JCTypeApply) { JCTypeApply ta = (JCTypeApply) in; - ListBuffer<JCExpression> lb = ListBuffer.lb(); + ListBuffer<JCExpression> lb = new ListBuffer<JCExpression>(); for (JCExpression typeArg : ta.arguments) { lb.append(cloneType0(maker, typeArg)); } @@ -1279,15 +1327,57 @@ public class JavacHandlerUtil { if (copyMode == null) copyMode = CopyJavadoc.VERBATIM; try { JCCompilationUnit cu = ((JCCompilationUnit) from.top().get()); - if (cu.docComments != null) { - String javadoc = cu.docComments.get(from.get()); - - if (javadoc != null) { - String[] filtered = copyMode.split(javadoc); - cu.docComments.put(to, filtered[0]); - cu.docComments.put(from.get(), filtered[1]); - } + Object dc = Javac.getDocComments(cu); + if (dc instanceof Map) { + copyJavadoc_jdk6_7(from, to, copyMode, dc); + } else if (Javac.instanceOfDocCommentTable(dc)) { + CopyJavadoc_8.copyJavadoc(from, to, copyMode, dc); } } catch (Exception ignore) {} } + + private static class CopyJavadoc_8 { + static void copyJavadoc(JavacNode from, JCTree to, CopyJavadoc copyMode, Object dc) { + DocCommentTable dct = (DocCommentTable) dc; + Comment javadoc = dct.getComment(from.get()); + + if (javadoc != null) { + String[] filtered = copyMode.split(javadoc.getText()); + dct.putComment(to, createJavadocComment(filtered[0], from)); + dct.putComment(from.get(), createJavadocComment(filtered[1], from)); + } + } + + private static Comment createJavadocComment(final String text, final JavacNode field) { + return new Comment() { + @Override public String getText() { + return text; + } + + @Override public int getSourcePos(int index) { + return -1; + } + + @Override public CommentStyle getStyle() { + return CommentStyle.JAVADOC; + } + + @Override public boolean isDeprecated() { + return text.contains("@deprecated") && field.getKind() == Kind.FIELD && isFieldDeprecated(field); + } + }; + } + } + + @SuppressWarnings({"unchecked", "all"}) + private static void copyJavadoc_jdk6_7(JavacNode from, JCTree to, CopyJavadoc copyMode, Object dc) { + Map<JCTree, String> docComments = (Map<JCTree, String>) dc; + String javadoc = docComments.get(from.get()); + + if (javadoc != null) { + String[] filtered = copyMode.split(javadoc); + docComments.put(to, filtered[0]); + docComments.put(from.get(), filtered[1]); + } + } } |