aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRoel Spilker <r.spilker@gmail.com>2013-11-19 21:02:59 +0100
committerRoel Spilker <r.spilker@gmail.com>2013-11-19 21:02:59 +0100
commit78b2d6919e35887940f9f11b6ae1731245739b83 (patch)
tree0dc305883c19a862a38669374c5614e26480d4b8 /src
parent5deb185591904d275cb06eea85c0d739587fc738 (diff)
parent83b7e77b0cce6cd5993b17f36164271accdd281c (diff)
downloadlombok-78b2d6919e35887940f9f11b6ae1731245739b83.tar.gz
lombok-78b2d6919e35887940f9f11b6ae1731245739b83.tar.bz2
lombok-78b2d6919e35887940f9f11b6ae1731245739b83.zip
Merge branch 'master' of github.com:rzwitserloot/lombok
Conflicts: src/delombok/lombok/delombok/DelombokApp.java
Diffstat (limited to 'src')
-rw-r--r--src/core/lombok/core/TransformationsUtil.java5
-rw-r--r--src/core/lombok/core/Version.java7
-rw-r--r--src/core/lombok/core/debug/DebugSnapshotStore.java2
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java67
-rw-r--r--src/core/lombok/eclipse/handlers/HandleBuilder.java2
-rw-r--r--src/core/lombok/eclipse/handlers/HandleConstructor.java11
-rw-r--r--src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java2
-rw-r--r--src/core/lombok/eclipse/handlers/HandleNonNull.java (renamed from src/core/lombok/eclipse/handlers/NonNullHandler.java)60
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSneakyThrows.java2
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSynchronized.java2
-rw-r--r--src/core/lombok/javac/CapturingDiagnosticListener.java15
-rw-r--r--src/core/lombok/javac/CompilerMessageSuppressor.java286
-rw-r--r--src/core/lombok/javac/FindTypeVarScanner.java2
-rw-r--r--src/core/lombok/javac/Javac6BasedLombokOptions.java44
-rw-r--r--src/core/lombok/javac/Javac8BasedLombokOptions.java45
-rw-r--r--src/core/lombok/javac/JavacAST.java52
-rw-r--r--src/core/lombok/javac/JavacNode.java12
-rw-r--r--src/core/lombok/javac/JavacResolution.java219
-rw-r--r--src/core/lombok/javac/LombokOptions.java16
-rw-r--r--src/core/lombok/javac/apt/Processor.java1
-rw-r--r--src/core/lombok/javac/handlers/HandleAccessors.java2
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilder.java29
-rw-r--r--src/core/lombok/javac/handlers/HandleCleanup.java13
-rw-r--r--src/core/lombok/javac/handlers/HandleConstructor.java47
-rw-r--r--src/core/lombok/javac/handlers/HandleDelegate.java10
-rw-r--r--src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java43
-rw-r--r--src/core/lombok/javac/handlers/HandleGetter.java30
-rw-r--r--src/core/lombok/javac/handlers/HandleLog.java8
-rw-r--r--src/core/lombok/javac/handlers/HandleNonNull.java (renamed from src/core/lombok/javac/handlers/NonNullHandler.java)51
-rw-r--r--src/core/lombok/javac/handlers/HandleSetter.java36
-rw-r--r--src/core/lombok/javac/handlers/HandleSneakyThrows.java6
-rw-r--r--src/core/lombok/javac/handlers/HandleSynchronized.java8
-rw-r--r--src/core/lombok/javac/handlers/HandleToString.java8
-rw-r--r--src/core/lombok/javac/handlers/HandleWither.java20
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java172
-rw-r--r--src/delombok/lombok/delombok/Delombok.java31
-rw-r--r--src/delombok/lombok/delombok/DelombokApp.java3
-rw-r--r--src/delombok/lombok/delombok/DocCommentIntegrator.java127
-rw-r--r--src/delombok/lombok/delombok/LombokOptionsFactory.java57
-rw-r--r--src/delombok/lombok/delombok/PrettyCommentsPrinter.java547
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java1
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java2
-rw-r--r--src/stubs/com/sun/tools/javac/main/Option.java10
-rw-r--r--src/stubs/com/sun/tools/javac/parser/JavaTokenizer.java19
-rw-r--r--src/stubs/com/sun/tools/javac/parser/JavacParser.java12
-rw-r--r--src/stubs/com/sun/tools/javac/parser/Scanner.java3
-rw-r--r--src/stubs/com/sun/tools/javac/parser/Tokens.java21
-rw-r--r--src/stubs/com/sun/tools/javac/parser/UnicodeReader.java18
-rw-r--r--src/stubs/com/sun/tools/javac/tree/DocCommentTable.java10
-rw-r--r--src/utils/lombok/core/debug/FileLog.java61
-rw-r--r--src/utils/lombok/javac/CommentCatcher.java52
-rw-r--r--src/utils/lombok/javac/Javac.java311
-rw-r--r--src/utils/lombok/javac/JavacTreeMaker.java830
-rw-r--r--src/utils/lombok/javac/TreeMirrorMaker.java5
-rw-r--r--src/utils/lombok/javac/java6/CommentCollectingParser.java21
-rw-r--r--src/utils/lombok/javac/java6/CommentCollectingParserFactory.java21
-rw-r--r--src/utils/lombok/javac/java6/CommentCollectingScanner.java7
-rw-r--r--src/utils/lombok/javac/java6/CommentCollectingScannerFactory.java2
-rw-r--r--src/utils/lombok/javac/java6/DocCommentScanner.java461
-rw-r--r--src/utils/lombok/javac/java7/CommentCollectingParser.java21
-rw-r--r--src/utils/lombok/javac/java7/CommentCollectingParserFactory.java21
-rw-r--r--src/utils/lombok/javac/java7/CommentCollectingScanner.java8
-rw-r--r--src/utils/lombok/javac/java8/CommentCollectingParser.java53
-rw-r--r--src/utils/lombok/javac/java8/CommentCollectingParserFactory.java73
-rw-r--r--src/utils/lombok/javac/java8/CommentCollectingScanner.java42
-rw-r--r--src/utils/lombok/javac/java8/CommentCollectingScannerFactory.java89
-rw-r--r--src/utils/lombok/javac/java8/CommentCollectingTokenizer.java129
67 files changed, 2992 insertions, 1411 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]);
+ }
+ }
}
diff --git a/src/delombok/lombok/delombok/Delombok.java b/src/delombok/lombok/delombok/Delombok.java
index f4e02786..0128e44f 100644
--- a/src/delombok/lombok/delombok/Delombok.java
+++ b/src/delombok/lombok/delombok/Delombok.java
@@ -52,7 +52,6 @@ import lombok.javac.LombokOptions;
import com.sun.tools.javac.comp.Todo;
import com.sun.tools.javac.main.JavaCompiler;
-import com.sun.tools.javac.main.OptionName;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.util.Context;
import com.zwitserloot.cmdreader.CmdReader;
@@ -359,12 +358,12 @@ public class Delombok {
}
public boolean delombok() throws IOException {
- LombokOptions options = LombokOptions.replaceWithDelombokOptions(context);
- options.put(OptionName.ENCODING, charset.name());
- if (classpath != null) options.put(OptionName.CLASSPATH, classpath);
- if (sourcepath != null) options.put(OptionName.SOURCEPATH, sourcepath);
- if (bootclasspath != null) options.put(OptionName.BOOTCLASSPATH, bootclasspath);
- options.put("compilePolicy", "attr");
+ LombokOptions options = LombokOptionsFactory.getDelombokOptions(context);
+ options.putJavacOption("ENCODING", charset.name());
+ if (classpath != null) options.putJavacOption("CLASSPATH", classpath);
+ if (sourcepath != null) options.putJavacOption("SOURCEPATH", sourcepath);
+ if (bootclasspath != null) options.putJavacOption("BOOTCLASSPATH", bootclasspath);
+ options.put("compilePolicy", "check");
CommentCatcher catcher = CommentCatcher.create(context);
JavaCompiler compiler = catcher.getCompiler();
@@ -375,10 +374,7 @@ public class Delombok {
compiler.initProcessAnnotations(Collections.singleton(new lombok.javac.apt.Processor()));
for (File fileToParse : filesToParse) {
-
- @SuppressWarnings("deprecation")
- JCCompilationUnit unit = compiler.parse(fileToParse.getAbsolutePath());
-
+ @SuppressWarnings("deprecation") JCCompilationUnit unit = compiler.parse(fileToParse.getAbsolutePath());
baseMap.put(unit, fileToBase.get(fileToParse));
roots.add(unit);
}
@@ -387,8 +383,17 @@ public class Delombok {
return false;
}
- JavaCompiler delegate = compiler.processAnnotations(compiler.enterTrees(toJavacList(roots)));
- callFlowMethodOnJavaCompiler(delegate, callAttributeMethodOnJavaCompiler(delegate, delegate.todo));
+ for (JCCompilationUnit unit : roots) {
+ catcher.setComments(unit, new DocCommentIntegrator().integrate(catcher.getComments(unit), unit));
+ }
+
+ com.sun.tools.javac.util.List<JCCompilationUnit> trees = compiler.enterTrees(toJavacList(roots));
+
+ JavaCompiler delegate = compiler.processAnnotations(trees);
+
+ Object care = callAttributeMethodOnJavaCompiler(delegate, delegate.todo);
+
+ callFlowMethodOnJavaCompiler(delegate, care);
for (JCCompilationUnit unit : roots) {
DelombokResult result = new DelombokResult(catcher.getComments(unit), unit, force || options.isChanged(unit));
if (verbose) feedback.printf("File: %s [%s]\n", unit.sourcefile.getName(), result.isChanged() ? "delomboked" : "unchanged");
diff --git a/src/delombok/lombok/delombok/DelombokApp.java b/src/delombok/lombok/delombok/DelombokApp.java
index e0d6ef1c..276bd7de 100644
--- a/src/delombok/lombok/delombok/DelombokApp.java
+++ b/src/delombok/lombok/delombok/DelombokApp.java
@@ -84,10 +84,9 @@ public class DelombokApp extends LombokApp {
return null;
}
- @SuppressWarnings("resource")
// The jar file is used for the lifetime of the classLoader, therefore the lifetime of delombok.
// Since we only read from it, not closing it should not be a problem.
- final JarFile toolsJarFile = new JarFile(toolsJar);
+ @SuppressWarnings({"resource", "all"}) final JarFile toolsJarFile = new JarFile(toolsJar);
ClassLoader loader = new ClassLoader() {
private Class<?> loadStreamAsClass(String name, boolean resolve, InputStream in) throws ClassNotFoundException {
diff --git a/src/delombok/lombok/delombok/DocCommentIntegrator.java b/src/delombok/lombok/delombok/DocCommentIntegrator.java
new file mode 100644
index 00000000..0955a003
--- /dev/null
+++ b/src/delombok/lombok/delombok/DocCommentIntegrator.java
@@ -0,0 +1,127 @@
+package lombok.delombok;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import lombok.javac.CommentInfo;
+import lombok.javac.Javac;
+import lombok.javac.handlers.JavacHandlerUtil;
+
+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.JCClassDecl;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
+import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
+
+public class DocCommentIntegrator {
+ /**
+ * Returns the same comment list as when this integrator was created, minus all doc comments that have been successfully integrated into the compilation unit.
+ */
+ public List<CommentInfo> integrate(List<CommentInfo> comments, JCCompilationUnit unit) {
+ List<CommentInfo> out = new ArrayList<CommentInfo>();
+ CommentInfo lastExcisedComment = null;
+ JCTree lastNode = null;
+
+ for (CommentInfo cmt : comments) {
+ if (!cmt.isJavadoc()) {
+ out.add(cmt);
+ continue;
+ }
+
+ JCTree node = findJavadocableNodeOnOrAfter(unit, cmt.endPos);
+ if (node == null) {
+ out.add(cmt);
+ continue;
+ }
+
+ if (node == lastNode) {
+ out.add(lastExcisedComment);
+ }
+ if (!attach(unit, node, cmt)) {
+ out.add(cmt);
+ } else {
+ lastNode = node;
+ lastExcisedComment = cmt;
+ }
+ }
+ return out;
+ }
+
+ private static final Pattern CONTENT_STRIPPER = Pattern.compile("^(?:\\s*\\*)?[ \\t]*(.*?)$", Pattern.MULTILINE);
+ @SuppressWarnings("unchecked") private boolean attach(JCCompilationUnit top, final JCTree node, CommentInfo cmt) {
+ String docCommentContent = cmt.content;
+ if (docCommentContent.startsWith("/**")) docCommentContent = docCommentContent.substring(3);
+ if (docCommentContent.endsWith("*/")) docCommentContent = docCommentContent.substring(0, docCommentContent.length() -2);
+ docCommentContent = CONTENT_STRIPPER.matcher(docCommentContent).replaceAll("$1");
+ docCommentContent = docCommentContent.trim();
+
+ if (Javac.getDocComments(top) == null) Javac.initDocComments(top);
+
+ Object map_ = Javac.getDocComments(top);
+ if (map_ instanceof Map) {
+ ((Map<JCTree, String>) map_).put(node, docCommentContent);
+ return true;
+ } else if (Javac.instanceOfDocCommentTable(map_)) {
+ CommentAttacher_8.attach(node, docCommentContent, map_);
+ return true;
+ }
+
+ return false;
+ }
+
+ /* Container for code which will cause class loader exceptions on javac below 8. By being in a separate class, we avoid the problem. */
+ private static class CommentAttacher_8 {
+ static void attach(final JCTree node, String docCommentContent, Object map_) {
+ final String docCommentContent_ = docCommentContent;
+ ((DocCommentTable) map_).putComment(node, new Comment() {
+ @Override public String getText() {
+ return docCommentContent_;
+ }
+
+ @Override public int getSourcePos(int index) {
+ return -1;
+ }
+
+ @Override public CommentStyle getStyle() {
+ return CommentStyle.JAVADOC;
+ }
+
+ @Override public boolean isDeprecated() {
+ return JavacHandlerUtil.nodeHasDeprecatedFlag(node);
+ }
+ });
+ }
+ }
+
+ private JCTree findJavadocableNodeOnOrAfter(JCCompilationUnit unit, int endPos) {
+ if (unit.pid != null && endPos <= unit.pid.pos) return null;
+ Iterator<JCTree> it = unit.defs.iterator();
+
+ while (it.hasNext()) {
+ JCTree node = it.next();
+ if (node.pos < endPos) {
+ if (node instanceof JCClassDecl) {
+ com.sun.tools.javac.util.List<JCTree> defs = ((JCClassDecl) node).defs;
+ if (!defs.isEmpty()) while (!defs.tail.isEmpty()) defs = defs.tail;
+ if (defs.head != null && defs.head.pos >= endPos) {
+ // The associated node is IN this class declaration, so, replace the iterator.
+ // There's no point looking beyond this member in the current iteration 'context'
+ // so we don't need to save the old ref. Just start over inside this type declaration.
+ it = ((JCClassDecl) node).defs.iterator();
+ }
+ }
+ continue;
+ }
+
+ if (node instanceof JCMethodDecl || node instanceof JCClassDecl || node instanceof JCVariableDecl) return node;
+ return null;
+ }
+
+ return null;
+ }
+}
diff --git a/src/delombok/lombok/delombok/LombokOptionsFactory.java b/src/delombok/lombok/delombok/LombokOptionsFactory.java
new file mode 100644
index 00000000..e581593f
--- /dev/null
+++ b/src/delombok/lombok/delombok/LombokOptionsFactory.java
@@ -0,0 +1,57 @@
+/*
+ * 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.delombok;
+
+import lombok.javac.Javac;
+import lombok.javac.Javac6BasedLombokOptions;
+import lombok.javac.Javac8BasedLombokOptions;
+import lombok.javac.LombokOptions;
+
+import com.sun.tools.javac.util.Context;
+
+public class LombokOptionsFactory {
+ enum LombokOptionCompilerVersion {
+ JDK7_AND_LOWER {
+ @Override LombokOptions createAndRegisterOptions(Context context) {
+ return Javac6BasedLombokOptions.replaceWithDelombokOptions(context);
+ }
+ },
+
+ JDK8 {
+ @Override LombokOptions createAndRegisterOptions(Context context) {
+ return Javac8BasedLombokOptions.replaceWithDelombokOptions(context);
+ }
+ };
+
+ abstract LombokOptions createAndRegisterOptions(Context context);
+ }
+
+ public static LombokOptions getDelombokOptions(Context context) {
+ LombokOptions options;
+ if (Javac.getJavaCompilerVersion() < 8) {
+ options = LombokOptionCompilerVersion.JDK7_AND_LOWER.createAndRegisterOptions(context);
+ } else {
+ options = LombokOptionCompilerVersion.JDK8.createAndRegisterOptions(context);
+ }
+ return options;
+ }
+}
diff --git a/src/delombok/lombok/delombok/PrettyCommentsPrinter.java b/src/delombok/lombok/delombok/PrettyCommentsPrinter.java
index 1bb2ce23..f9152e68 100644
--- a/src/delombok/lombok/delombok/PrettyCommentsPrinter.java
+++ b/src/delombok/lombok/delombok/PrettyCommentsPrinter.java
@@ -29,34 +29,27 @@
*/
package lombok.delombok;
-import static com.sun.tools.javac.code.Flags.ANNOTATION;
-import static com.sun.tools.javac.code.Flags.ENUM;
-import static com.sun.tools.javac.code.Flags.INTERFACE;
-import static com.sun.tools.javac.code.Flags.SYNTHETIC;
-import static com.sun.tools.javac.code.Flags.StandardFlags;
-import static com.sun.tools.javac.code.Flags.VARARGS;
+import static com.sun.tools.javac.code.Flags.*;
+import static lombok.javac.Javac.*;
+import static lombok.javac.JavacTreeMaker.TreeTag.treeTag;
+import static lombok.javac.JavacTreeMaker.TypeTag.typeTag;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import lombok.javac.CommentInfo;
-import lombok.javac.Javac;
import lombok.javac.CommentInfo.EndConnection;
import lombok.javac.CommentInfo.StartConnection;
+import lombok.javac.JavacTreeMaker.TreeTag;
+import lombok.javac.JavacTreeMaker.TypeTag;
import com.sun.source.tree.Tree;
-import com.sun.tools.javac.code.BoundKind;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.TypeTags;
import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.TreeInfo;
-import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCArrayAccess;
import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree;
@@ -108,10 +101,14 @@ import com.sun.tools.javac.tree.JCTree.JCWhileLoop;
import com.sun.tools.javac.tree.JCTree.JCWildcard;
import com.sun.tools.javac.tree.JCTree.LetExpr;
import com.sun.tools.javac.tree.JCTree.TypeBoundKind;
+import com.sun.tools.javac.tree.DocCommentTable;
+import com.sun.tools.javac.tree.TreeInfo;
+import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.util.Convert;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Position;
+//import com.sun.tools.javac.code.TypeTags;
/** Prints out a tree as an indented Java source program.
*
@@ -122,214 +119,177 @@ import com.sun.tools.javac.util.Position;
*/
@SuppressWarnings("all") // Mainly sun code that has other warning settings
public class PrettyCommentsPrinter extends JCTree.Visitor {
-
- private static final Method GET_TAG_METHOD;
- private static final Field TAG_FIELD;
+ private static final TreeTag PARENS = treeTag("PARENS");
+ private static final TreeTag IMPORT = treeTag("IMPORT");
+ private static final TreeTag VARDEF = treeTag("VARDEF");
+ private static final TreeTag SELECT = treeTag("SELECT");
- private static final int PARENS = Javac.getCtcInt(JCTree.class, "PARENS");
- private static final int IMPORT = Javac.getCtcInt(JCTree.class, "IMPORT");
- private static final int VARDEF = Javac.getCtcInt(JCTree.class, "VARDEF");
- private static final int SELECT = Javac.getCtcInt(JCTree.class, "SELECT");
-
- private static final Map<Integer, String> OPERATORS;
+ private static final Map<TreeTag, String> OPERATORS;
static {
- Method m = null;
- Field f = null;
- try {
- m = JCTree.class.getDeclaredMethod("getTag");
- }
- catch (NoSuchMethodException e) {
- try {
- f = JCTree.class.getDeclaredField("tag");
- }
- catch (NoSuchFieldException e1) {
- e1.printStackTrace();
- }
- }
- GET_TAG_METHOD = m;
- TAG_FIELD = f;
-
- Map<Integer, String> map = new HashMap<Integer, String>();
-
- map.put(Javac.getCtcInt(JCTree.class, "POS"), "+");
- map.put(Javac.getCtcInt(JCTree.class, "NEG"), "-");
- map.put(Javac.getCtcInt(JCTree.class, "NOT"), "!");
- map.put(Javac.getCtcInt(JCTree.class, "COMPL"), "~");
- map.put(Javac.getCtcInt(JCTree.class, "PREINC"), "++");
- map.put(Javac.getCtcInt(JCTree.class, "PREDEC"), "--");
- map.put(Javac.getCtcInt(JCTree.class, "POSTINC"), "++");
- map.put(Javac.getCtcInt(JCTree.class, "POSTDEC"), "--");
- map.put(Javac.getCtcInt(JCTree.class, "NULLCHK"), "<*nullchk*>");
- map.put(Javac.getCtcInt(JCTree.class, "OR"), "||");
- map.put(Javac.getCtcInt(JCTree.class, "AND"), "&&");
- map.put(Javac.getCtcInt(JCTree.class, "EQ"), "==");
- map.put(Javac.getCtcInt(JCTree.class, "NE"), "!=");
- map.put(Javac.getCtcInt(JCTree.class, "LT"), "<");
- map.put(Javac.getCtcInt(JCTree.class, "GT"), ">");
- map.put(Javac.getCtcInt(JCTree.class, "LE"), "<=");
- map.put(Javac.getCtcInt(JCTree.class, "GE"), ">=");
- map.put(Javac.getCtcInt(JCTree.class, "BITOR"), "|");
- map.put(Javac.getCtcInt(JCTree.class, "BITXOR"), "^");
- map.put(Javac.getCtcInt(JCTree.class, "BITAND"), "&");
- map.put(Javac.getCtcInt(JCTree.class, "SL"), "<<");
- map.put(Javac.getCtcInt(JCTree.class, "SR"), ">>");
- map.put(Javac.getCtcInt(JCTree.class, "USR"), ">>>");
- map.put(Javac.getCtcInt(JCTree.class, "PLUS"), "+");
- map.put(Javac.getCtcInt(JCTree.class, "MINUS"), "-");
- map.put(Javac.getCtcInt(JCTree.class, "MUL"), "*");
- map.put(Javac.getCtcInt(JCTree.class, "DIV"), "/");
- map.put(Javac.getCtcInt(JCTree.class, "MOD"), "%");
-
- OPERATORS = map;
+ Map<TreeTag, String> map = new HashMap<TreeTag, String>();
+
+ map.put(treeTag("POS"), "+");
+ map.put(treeTag("NEG"), "-");
+ map.put(treeTag("NOT"), "!");
+ map.put(treeTag("COMPL"), "~");
+ map.put(treeTag("PREINC"), "++");
+ map.put(treeTag("PREDEC"), "--");
+ map.put(treeTag("POSTINC"), "++");
+ map.put(treeTag("POSTDEC"), "--");
+ map.put(treeTag("NULLCHK"), "<*nullchk*>");
+ map.put(treeTag("OR"), "||");
+ map.put(treeTag("AND"), "&&");
+ map.put(treeTag("EQ"), "==");
+ map.put(treeTag("NE"), "!=");
+ map.put(treeTag("LT"), "<");
+ map.put(treeTag("GT"), ">");
+ map.put(treeTag("LE"), "<=");
+ map.put(treeTag("GE"), ">=");
+ map.put(treeTag("BITOR"), "|");
+ map.put(treeTag("BITXOR"), "^");
+ map.put(treeTag("BITAND"), "&");
+ map.put(treeTag("SL"), "<<");
+ map.put(treeTag("SR"), ">>");
+ map.put(treeTag("USR"), ">>>");
+ map.put(treeTag("PLUS"), "+");
+ map.put(treeTag("MINUS"), "-");
+ map.put(treeTag("MUL"), "*");
+ map.put(treeTag("DIV"), "/");
+ map.put(treeTag("MOD"), "%");
+
+ map.put(treeTag("BITOR_ASG"), "|=");
+ map.put(treeTag("BITXOR_ASG"), "^=");
+ map.put(treeTag("BITAND_ASG"), "&=");
+ map.put(treeTag("SL_ASG"), "<<=");
+ map.put(treeTag("SR_ASG"), ">>=");
+ map.put(treeTag("USR_ASG"), ">>>=");
+ map.put(treeTag("PLUS_ASG"), "+=");
+ map.put(treeTag("MINUS_ASG"), "-=");
+ map.put(treeTag("MUL_ASG"), "*=");
+ map.put(treeTag("DIV_ASG"), "/=");
+ map.put(treeTag("MOD_ASG"), "%=");
+
+ OPERATORS = map;
}
- static int getTag(JCTree tree) {
- if (GET_TAG_METHOD != null) {
- try {
- return (Integer)GET_TAG_METHOD.invoke(tree);
- }
- catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- catch (InvocationTargetException e) {
- throw new RuntimeException(e.getCause());
- }
- }
- try {
- return TAG_FIELD.getInt(tree);
- }
- catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
-
- private List<CommentInfo> comments;
- private final JCCompilationUnit cu;
- private boolean onNewLine = true;
- private boolean aligned = false;
- private boolean inParams = false;
-
- private boolean needsSpace = false;
- private boolean needsNewLine = false;
- private boolean needsAlign = false;
-
+ private List<CommentInfo> comments;
+ private final JCCompilationUnit cu;
+ private boolean onNewLine = true;
+ private boolean aligned = false;
+ private boolean inParams = false;
+
+ private boolean needsSpace = false;
+ private boolean needsNewLine = false;
+ private boolean needsAlign = false;
+
public PrettyCommentsPrinter(Writer out, JCCompilationUnit cu, List<CommentInfo> comments) {
this.out = out;
- this.comments = comments;
- this.cu = cu;
+ this.comments = comments;
+ this.cu = cu;
}
-
- private int endPos(JCTree tree) {
- return tree.getEndPosition(cu.endPositions);
- }
- private void consumeComments(int until) throws IOException {
- consumeComments(until, null);
- }
- private void consumeComments(int until, JCTree tree) throws IOException {
- boolean prevNewLine = onNewLine;
- boolean found = false;
- CommentInfo head = comments.head;
- while (comments.nonEmpty() && head.pos < until) {
- if (tree != null && docComments != null && docComments.containsKey(tree) && head.isJavadoc() && noFurtherJavadocForthcoming(until)) {
- // This is (presumably) the exact same javadoc that has already been associated with the node that we're just about to
- // print. These javadoc can be modified by lombok handlers, and as such we should NOT print them from the consumed comments db,
- // and instead print the actual javadoc associated with the upcoming node (which the visit method for that node will take care of).
- } else {
- printComment(head);
- }
- comments = comments.tail;
- head = comments.head;
- }
- if (!onNewLine && prevNewLine) {
- println();
- }
- }
+ private int endPos(JCTree tree) {
+ return getEndPosition(tree, cu);
+ }
- private boolean noFurtherJavadocForthcoming(int until) {
- List<CommentInfo> c = comments;
- if (c.nonEmpty()) c = c.tail;
- while (c.nonEmpty()) {
- if (c.head.pos >= until) return true;
- if (c.head.isJavadoc()) return false;
- c = c.tail;
- }
- return true;
+ private void consumeComments(int until) throws IOException {
+ consumeComments(until, null);
}
-
+
+ private void consumeComments(int until, JCTree tree) throws IOException {
+ boolean prevNewLine = onNewLine;
+ boolean found = false;
+ CommentInfo head = comments.head;
+ while (comments.nonEmpty() && head.pos < until) {
+ printComment(head);
+ comments = comments.tail;
+ head = comments.head;
+ }
+ if (!onNewLine && prevNewLine) {
+ println();
+ }
+ }
+
private void consumeTrailingComments(int from) throws IOException {
- boolean prevNewLine = onNewLine;
- CommentInfo head = comments.head;
- boolean stop = false;
- while (comments.nonEmpty() && head.prevEndPos == from && !stop && !(head.start == StartConnection.ON_NEXT_LINE || head.start == StartConnection.START_OF_LINE)) {
- from = head.endPos;
- printComment(head);
- stop = (head.end == EndConnection.ON_NEXT_LINE);
- comments = comments.tail;
- head = comments.head;
- }
- if (!onNewLine && prevNewLine) {
- println();
- }
- }
-
- private void printComment(CommentInfo comment) throws IOException {
- prepareComment(comment.start);
- print(comment.content);
- switch (comment.end) {
- case ON_NEXT_LINE:
- if (!aligned) {
- needsNewLine = true;
- needsAlign = true;
- }
- break;
- case AFTER_COMMENT:
- needsSpace = true;
- break;
- case DIRECT_AFTER_COMMENT:
- // do nothing
- break;
- }
+ boolean prevNewLine = onNewLine;
+ CommentInfo head = comments.head;
+ boolean stop = false;
+ while (comments.nonEmpty() && head.prevEndPos == from && !stop && !(head.start == StartConnection.ON_NEXT_LINE || head.start == StartConnection.START_OF_LINE)) {
+ from = head.endPos;
+ printComment(head);
+ stop = (head.end == EndConnection.ON_NEXT_LINE);
+ comments = comments.tail;
+ head = comments.head;
+ }
+ if (!onNewLine && prevNewLine) {
+ println();
+ }
+ }
+
+ private void printComment(CommentInfo comment) throws IOException {
+ prepareComment(comment.start);
+ print(comment.content);
+ switch (comment.end) {
+ case ON_NEXT_LINE:
+ if (!aligned) {
+ needsNewLine = true;
+ needsAlign = true;
+ }
+ break;
+ case AFTER_COMMENT:
+ needsSpace = true;
+ break;
+ case DIRECT_AFTER_COMMENT:
+ // do nothing
+ break;
+ }
+ }
+
+ private void prepareComment(StartConnection start) throws IOException {
+ switch (start) {
+ case DIRECT_AFTER_PREVIOUS:
+ needsSpace = false;
+ break;
+ case AFTER_PREVIOUS:
+ needsSpace = true;
+ break;
+ case START_OF_LINE:
+ needsNewLine = true;
+ needsAlign = false;
+ break;
+ case ON_NEXT_LINE:
+ if (!aligned) {
+ needsNewLine = true;
+ needsAlign = true;
+ }
+ break;
+ }
}
-
- private void prepareComment(StartConnection start) throws IOException {
- switch (start) {
- case DIRECT_AFTER_PREVIOUS:
- needsSpace = false;
- break;
- case AFTER_PREVIOUS:
- needsSpace = true;
- break;
- case START_OF_LINE:
- needsNewLine = true;
- needsAlign = false;
- break;
- case ON_NEXT_LINE:
- if (!aligned) {
- needsNewLine = true;
- needsAlign = true;
- }
- break;
- }
- }
/** The output stream on which trees are printed.
*/
Writer out;
-
+
/** The current left margin.
*/
int lmargin = 0;
-
+
/** The enclosing class name.
*/
Name enclClassName;
-
+
/** A hashtable mapping trees to their documentation comments
* (can be null)
*/
Map<JCTree, String> docComments = null;
+ DocCommentTable docTable = null;
+
+ String getJavadocFor(JCTree node) {
+ if (docComments != null) return docComments.get(node);
+ if (docTable != null) return docTable.getCommentText(node);
+ return null;
+ }
/** Align code to be indented to left margin.
*/
@@ -339,19 +299,19 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
needsAlign = false;
for (int i = 0; i < lmargin; i++) out.write("\t");
}
-
+
/** Increase left margin by indentation width.
*/
void indent() {
lmargin++;
}
-
+
/** Decrease left margin by indentation width.
*/
void undent() {
lmargin--;
}
-
+
/** Enter a new precedence level. Emit a `(' if new precedence level
* is less than precedence level so far.
* @param contextPrec The precedence level in force so far.
@@ -360,7 +320,7 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
void open(int contextPrec, int ownPrec) throws IOException {
if (ownPrec < contextPrec) out.write("(");
}
-
+
/** Leave precedence level. Emit a `(' if inner precedence level
* is less than precedence level we revert to.
* @param contextPrec The precedence level we revert to.
@@ -369,7 +329,7 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
void close(int contextPrec, int ownPrec) throws IOException {
if (ownPrec < contextPrec) out.write(")");
}
-
+
/** Print string, replacing all non-ascii character with unicode escapes.
*/
public void print(Object s) throws IOException {
@@ -524,31 +484,28 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
* @param tree The tree for which a documentation comment should be printed.
*/
public void printDocComment(JCTree tree) throws IOException {
- if (docComments != null) {
- String dc = docComments.get(tree);
- if (dc != null) {
- print("/**"); println();
- int pos = 0;
- int endpos = lineEndPos(dc, pos);
- boolean atStart = true;
- while (pos < dc.length()) {
- String line = dc.substring(pos, endpos);
- if (line.trim().isEmpty() && atStart) {
- atStart = false;
- continue;
- }
- atStart = false;
- align();
- print(" *");
- if (pos < dc.length() && dc.charAt(pos) > ' ') print(" ");
- print(dc.substring(pos, endpos)); println();
- pos = endpos + 1;
- endpos = lineEndPos(dc, pos);
- }
- align(); print(" */"); println();
- align();
+ String dc = getJavadocFor(tree);
+ if (dc == null) return;
+ print("/**"); println();
+ int pos = 0;
+ int endpos = lineEndPos(dc, pos);
+ boolean atStart = true;
+ while (pos < dc.length()) {
+ String line = dc.substring(pos, endpos);
+ if (line.trim().isEmpty() && atStart) {
+ atStart = false;
+ continue;
}
+ atStart = false;
+ align();
+ print(" *");
+ if (pos < dc.length() && dc.charAt(pos) > ' ') print(" ");
+ print(dc.substring(pos, endpos)); println();
+ pos = endpos + 1;
+ endpos = lineEndPos(dc, pos);
}
+ align(); print(" */"); println();
+ align();
}
//where
static int lineEndPos(String s, int start) {
@@ -633,7 +590,7 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
/** Is the given tree an enumerator definition? */
boolean isEnumerator(JCTree t) {
- return getTag(t) == VARDEF && (((JCVariableDecl) t).mods.flags & ENUM) != 0;
+ return VARDEF.equals(treeTag(t)) && (((JCVariableDecl) t).mods.flags & ENUM) != 0;
}
/** Print unit consisting of package clause and import statements in toplevel,
@@ -644,7 +601,9 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
* toplevel tree.
*/
public void printUnit(JCCompilationUnit tree, JCClassDecl cdef) throws IOException {
- docComments = tree.docComments;
+ Object dc = getDocComments(tree);
+ if (dc instanceof Map) this.docComments = (Map) dc;
+ else if (dc instanceof DocCommentTable) this.docTable = (DocCommentTable) dc;
printDocComment(tree);
if (tree.pid != null) {
consumeComments(tree.pos, tree);
@@ -655,9 +614,9 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
}
boolean firstImport = true;
for (List<JCTree> l = tree.defs;
- l.nonEmpty() && (cdef == null || getTag(l.head) == IMPORT);
+ l.nonEmpty() && (cdef == null || IMPORT.equals(treeTag(l.head)));
l = l.tail) {
- if (getTag(l.head) == IMPORT) {
+ if (IMPORT.equals(treeTag(l.head))) {
JCImport imp = (JCImport)l.head;
Name name = TreeInfo.name(imp.qualid);
if (name == name.table.fromChars(new char[] {'*'}, 0, 1) ||
@@ -741,9 +700,9 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
else
print("class " + tree.name);
printTypeParameters(tree.typarams);
- if (tree.getExtendsClause() != null) {
+ if (getExtendsClause(tree) != null) {
print(" extends ");
- printExpr(tree.getExtendsClause());
+ printExpr(getExtendsClause(tree));
}
if (tree.implementing.nonEmpty()) {
print(" implements ");
@@ -826,7 +785,7 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
public void visitVarDef(JCVariableDecl tree) {
try {
- if (docComments != null && docComments.get(tree) != null) {
+ if (getJavadocFor(tree) != null) {
println(); align();
}
printDocComment(tree);
@@ -876,7 +835,7 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
printStat(tree.body);
align();
print(" while ");
- if (getTag(tree.cond) == PARENS) {
+ if (PARENS.equals(treeTag(tree.cond))) {
printExpr(tree.cond);
} else {
print("(");
@@ -892,7 +851,7 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
public void visitWhileLoop(JCWhileLoop tree) {
try {
print("while ");
- if (getTag(tree.cond) == PARENS) {
+ if (PARENS.equals(treeTag(tree.cond))) {
printExpr(tree.cond);
} else {
print("(");
@@ -910,7 +869,7 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
try {
print("for (");
if (tree.init.nonEmpty()) {
- if (getTag(tree.init.head) == VARDEF) {
+ if (VARDEF.equals(treeTag(tree.init.head))) {
printExpr(tree.init.head);
for (List<JCStatement> l = tree.init.tail; l.nonEmpty(); l = l.tail) {
JCVariableDecl vdef = (JCVariableDecl)l.head;
@@ -957,7 +916,7 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
public void visitSwitch(JCSwitch tree) {
try {
print("switch ");
- if (getTag(tree.selector) == PARENS) {
+ if (PARENS.equals(treeTag(tree.selector))) {
printExpr(tree.selector);
} else {
print("(");
@@ -996,7 +955,7 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
public void visitSynchronized(JCSynchronized tree) {
try {
print("synchronized ");
- if (getTag(tree.lock) == PARENS) {
+ if (PARENS.equals(treeTag(tree.lock))) {
printExpr(tree.lock);
} else {
print("(");
@@ -1077,7 +1036,7 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
public void visitIf(JCIf tree) {
try {
print("if ");
- if (getTag(tree.cond) == PARENS) {
+ if (PARENS.equals(treeTag(tree.cond))) {
printExpr(tree.cond);
} else {
print("(");
@@ -1173,7 +1132,7 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
public void visitApply(JCMethodInvocation tree) {
try {
if (!tree.typeargs.isEmpty()) {
- if (getTag(tree.meth) == SELECT) {
+ if (SELECT.equals(treeTag(tree.meth))) {
JCFieldAccess left = (JCFieldAccess)tree.meth;
printExpr(left.selected);
print(".<");
@@ -1277,7 +1236,7 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
}
}
- public String operatorName(int tag) {
+ public String operatorName(TreeTag tag) {
String result = OPERATORS.get(tag);
if (result == null) throw new Error();
return result;
@@ -1287,7 +1246,8 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
try {
open(prec, TreeInfo.assignopPrec);
printExpr(tree.lhs, TreeInfo.assignopPrec + 1);
- print(" " + operatorName(getTag(tree) - JCTree.ASGOffset) + "= ");
+ String opname = operatorName(treeTag(tree));
+ print(" " + opname + " ");
printExpr(tree.rhs, TreeInfo.assignopPrec);
close(prec, TreeInfo.assignopPrec);
} catch (IOException e) {
@@ -1297,10 +1257,10 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
public void visitUnary(JCUnary tree) {
try {
- int ownprec = TreeInfo.opPrec(getTag(tree));
- String opname = operatorName(getTag(tree));
+ int ownprec = isOwnPrec(tree);
+ String opname = operatorName(treeTag(tree));
open(prec, ownprec);
- if (getTag(tree) <= Javac.getCtcInt(JCTree.class, "PREDEC")) {
+ if (isPrefixUnary(tree)) {
print(opname);
printExpr(tree.arg, ownprec);
} else {
@@ -1312,11 +1272,19 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
throw new UncheckedIOException(e);
}
}
-
+
+ private int isOwnPrec(JCExpression tree) {
+ return treeTag(tree).getOperatorPrecedenceLevel();
+ }
+
+ private boolean isPrefixUnary(JCUnary tree) {
+ return treeTag(tree).isPrefixUnaryOp();
+ }
+
public void visitBinary(JCBinary tree) {
try {
- int ownprec = TreeInfo.opPrec(getTag(tree));
- String opname = operatorName(getTag(tree));
+ int ownprec = isOwnPrec(tree);
+ String opname = operatorName(treeTag(tree));
open(prec, ownprec);
printExpr(tree.lhs, ownprec);
print(" " + opname + " ");
@@ -1381,78 +1349,39 @@ public class PrettyCommentsPrinter extends JCTree.Visitor {
}
public void visitLiteral(JCLiteral tree) {
+ TypeTag typeTag = typeTag(tree);
try {
- switch (tree.typetag) {
- case TypeTags.INT:
- print(tree.value.toString());
- break;
- case TypeTags.LONG:
- print(tree.value + "L");
- break;
- case TypeTags.FLOAT:
- print(tree.value + "F");
- break;
- case TypeTags.DOUBLE:
- print(tree.value.toString());
- break;
- case TypeTags.CHAR:
- print("\'" +
- Convert.quote(
- String.valueOf((char)((Number)tree.value).intValue())) +
- "\'");
- break;
- case TypeTags.BOOLEAN:
- print(((Number)tree.value).intValue() == 1 ? "true" : "false");
- break;
- case TypeTags.BOT:
- print("null");
- break;
- default:
- print("\"" + Convert.quote(tree.value.toString()) + "\"");
- break;
+ if (CTC_INT.equals(typeTag)) print(tree.value.toString());
+ else if (CTC_LONG.equals(typeTag)) print(tree.value + "L");
+ else if (CTC_FLOAT.equals(typeTag)) print(tree.value + "F");
+ else if (CTC_DOUBLE.equals(typeTag)) print(tree.value.toString());
+ else if (CTC_CHAR.equals(typeTag)) {
+ print("\'" + Convert.quote(String.valueOf((char)((Number)tree.value).intValue())) + "\'");
}
+ else if (CTC_BOOLEAN.equals(typeTag)) print(((Number)tree.value).intValue() == 1 ? "true" : "false");
+ else if (CTC_BOT.equals(typeTag)) print("null");
+ else print("\"" + Convert.quote(tree.value.toString()) + "\"");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
- public void visitTypeIdent(JCPrimitiveTypeTree tree) {
- try {
- switch(tree.typetag) {
- case TypeTags.BYTE:
- print("byte");
- break;
- case TypeTags.CHAR:
- print("char");
- break;
- case TypeTags.SHORT:
- print("short");
- break;
- case TypeTags.INT:
- print("int");
- break;
- case TypeTags.LONG:
- print("long");
- break;
- case TypeTags.FLOAT:
- print("float");
- break;
- case TypeTags.DOUBLE:
- print("double");
- break;
- case TypeTags.BOOLEAN:
- print("boolean");
- break;
- case TypeTags.VOID:
- print("void");
- break;
- default:
- print("error");
- break;
- }
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
+ public void visitTypeIdent(JCPrimitiveTypeTree tree) {
+ TypeTag typetag = typeTag(tree);
+ try {
+ if (CTC_BYTE.equals(typetag)) print ("byte");
+ else if (CTC_CHAR.equals(typetag)) print ("char");
+ else if (CTC_SHORT.equals(typetag)) print ("short");
+ else if (CTC_INT.equals(typetag)) print ("int");
+ else if (CTC_LONG.equals(typetag)) print ("long");
+ else if (CTC_FLOAT.equals(typetag)) print ("float");
+ else if (CTC_DOUBLE.equals(typetag)) print ("double");
+ else if (CTC_BOOLEAN.equals(typetag)) print ("boolean");
+ else if (CTC_VOID.equals(typetag)) print ("void");
+ else print("error");
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
}
public void visitTypeArray(JCArrayTypeTree tree) {
diff --git a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
index 8c6011bc..ccee5575 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
@@ -275,7 +275,6 @@ public class EclipsePatcher extends Agent {
.methodToWrap(new Hook("org.eclipse.jdt.internal.compiler.ClassFile", "getBytes", "byte[]"))
.wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "runPostCompiler", "byte[]", "byte[]", "java.lang.String"))
.requestExtra(StackRequest.PARAM3)
- .transplant()
.build());
}
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java b/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java
index 0002e26e..d4b8c763 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java
@@ -329,7 +329,7 @@ public class PatchFixes {
return newSimpleNames;
}
- public static byte[] runPostCompiler(byte[] bytes, String fileName) {
+ public static byte[] runPostCompiler(byte[] bytes, String fileName) {
byte[] transformed = PostCompiler.applyTransformations(bytes, fileName, DiagnosticsReceiver.CONSOLE);
return transformed == null ? bytes : transformed;
}
diff --git a/src/stubs/com/sun/tools/javac/main/Option.java b/src/stubs/com/sun/tools/javac/main/Option.java
new file mode 100644
index 00000000..f3229c78
--- /dev/null
+++ b/src/stubs/com/sun/tools/javac/main/Option.java
@@ -0,0 +1,10 @@
+/*
+ * These are stub versions of various bits of javac-internal API (for various different versions of javac). Lombok is compiled against these.
+ */
+package com.sun.tools.javac.main;
+
+
+public enum Option {
+ ;
+ public String text;
+}
diff --git a/src/stubs/com/sun/tools/javac/parser/JavaTokenizer.java b/src/stubs/com/sun/tools/javac/parser/JavaTokenizer.java
new file mode 100644
index 00000000..7d5bbcb1
--- /dev/null
+++ b/src/stubs/com/sun/tools/javac/parser/JavaTokenizer.java
@@ -0,0 +1,19 @@
+package com.sun.tools.javac.parser;
+
+import com.sun.tools.javac.parser.Tokens.Comment;
+import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
+
+public class JavaTokenizer {
+ protected UnicodeReader reader;
+
+ protected JavaTokenizer(ScannerFactory fac, UnicodeReader reader) {
+ }
+
+ public com.sun.tools.javac.parser.Tokens.Token readToken() {
+ return null;
+ }
+
+ protected Comment processComment(int pos, int endPos, CommentStyle style) {
+ return null;
+ }
+}
diff --git a/src/stubs/com/sun/tools/javac/parser/JavacParser.java b/src/stubs/com/sun/tools/javac/parser/JavacParser.java
new file mode 100644
index 00000000..da42f37a
--- /dev/null
+++ b/src/stubs/com/sun/tools/javac/parser/JavacParser.java
@@ -0,0 +1,12 @@
+package com.sun.tools.javac.parser;
+
+import com.sun.tools.javac.tree.JCTree;
+
+public class JavacParser {
+ protected JavacParser(ParserFactory fac, Lexer S, boolean keepDocComments, boolean keepLineMap, boolean keepEndPositions) {
+ }
+
+ public JCTree.JCCompilationUnit parseCompilationUnit() {
+ return null;
+ }
+}
diff --git a/src/stubs/com/sun/tools/javac/parser/Scanner.java b/src/stubs/com/sun/tools/javac/parser/Scanner.java
index 266208e5..36c93df7 100644
--- a/src/stubs/com/sun/tools/javac/parser/Scanner.java
+++ b/src/stubs/com/sun/tools/javac/parser/Scanner.java
@@ -20,6 +20,9 @@ public class Scanner implements Lexer {
protected Scanner(ScannerFactory fac, char[] input, int inputLength) {
}
+ protected Scanner(ScannerFactory fac, JavaTokenizer tokenizer) {
+ }
+
public static class Factory {
public static final Context.Key<Scanner.Factory> scannerFactoryKey = null;
diff --git a/src/stubs/com/sun/tools/javac/parser/Tokens.java b/src/stubs/com/sun/tools/javac/parser/Tokens.java
new file mode 100644
index 00000000..6e0aa479
--- /dev/null
+++ b/src/stubs/com/sun/tools/javac/parser/Tokens.java
@@ -0,0 +1,21 @@
+package com.sun.tools.javac.parser;
+
+public class Tokens {
+ public static class Token {
+
+ }
+
+ public interface Comment {
+ enum CommentStyle {
+ LINE, BLOCK, JAVADOC,
+ }
+
+ String getText();
+
+ int getSourcePos(int index);
+
+ CommentStyle getStyle();
+
+ boolean isDeprecated();
+ }
+}
diff --git a/src/stubs/com/sun/tools/javac/parser/UnicodeReader.java b/src/stubs/com/sun/tools/javac/parser/UnicodeReader.java
new file mode 100644
index 00000000..1c09eb6b
--- /dev/null
+++ b/src/stubs/com/sun/tools/javac/parser/UnicodeReader.java
@@ -0,0 +1,18 @@
+package com.sun.tools.javac.parser;
+
+import java.nio.CharBuffer;
+
+public class UnicodeReader {
+ protected int bp;
+
+ protected UnicodeReader(ScannerFactory sf, char[] input, int inputLength) {
+ }
+
+ protected UnicodeReader(ScannerFactory sf, CharBuffer buffer) {
+
+ }
+
+ public char[] getRawCharacters(int beginIndex, int endIndex) {
+ return null;
+ }
+}
diff --git a/src/stubs/com/sun/tools/javac/tree/DocCommentTable.java b/src/stubs/com/sun/tools/javac/tree/DocCommentTable.java
new file mode 100644
index 00000000..75b2526a
--- /dev/null
+++ b/src/stubs/com/sun/tools/javac/tree/DocCommentTable.java
@@ -0,0 +1,10 @@
+package com.sun.tools.javac.tree;
+
+import com.sun.tools.javac.parser.Tokens.Comment;
+
+public interface DocCommentTable {
+ boolean hasComment(JCTree tree);
+ Comment getComment(JCTree tree);
+ String getCommentText(JCTree tree);
+ void putComment(JCTree tree, Comment c);
+}
diff --git a/src/utils/lombok/core/debug/FileLog.java b/src/utils/lombok/core/debug/FileLog.java
new file mode 100644
index 00000000..dedec40e
--- /dev/null
+++ b/src/utils/lombok/core/debug/FileLog.java
@@ -0,0 +1,61 @@
+/*
+ * 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.core.debug;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+public class FileLog {
+ private static FileOutputStream fos;
+
+ public static void log(String message) {
+ log(message, null);
+ }
+ public synchronized static void log(String message, Throwable t) {
+ try {
+ if (fos == null) {
+ fos = new FileOutputStream(new File(System.getProperty("user.home"), "LOMBOK-DEBUG-OUT.txt"));
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ public void run() {
+ try {
+ fos.close();
+ } catch (Throwable ignore) {}
+ }
+ });
+ }
+ fos.write(message.getBytes("UTF-8"));
+ fos.write('\n');
+ if (t != null) {
+ StringWriter sw = new StringWriter();
+ t.printStackTrace(new PrintWriter(sw));
+ fos.write(sw.toString().getBytes("UTF-8"));
+ fos.write('\n');
+ }
+ fos.flush();
+ } catch (IOException e) {
+ throw new IllegalStateException("Internal lombok file-based debugging not possible", e);
+ }
+ }
+}
diff --git a/src/utils/lombok/javac/CommentCatcher.java b/src/utils/lombok/javac/CommentCatcher.java
index 565a166d..36d90e30 100644
--- a/src/utils/lombok/javac/CommentCatcher.java
+++ b/src/utils/lombok/javac/CommentCatcher.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 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
@@ -21,13 +21,15 @@
*/
package lombok.javac;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.List;
public class CommentCatcher {
private final JavaCompiler compiler;
@@ -55,38 +57,54 @@ public class CommentCatcher {
return compiler;
}
+ public void setComments(JCCompilationUnit ast, List<CommentInfo> comments) {
+ if (comments != null) {
+ commentsMap.put(ast, comments);
+ } else {
+ commentsMap.remove(ast);
+ }
+ }
+
public List<CommentInfo> getComments(JCCompilationUnit ast) {
List<CommentInfo> list = commentsMap.get(ast);
- return list == null ? List.<CommentInfo>nil() : list;
+ return list == null ? Collections.<CommentInfo>emptyList() : list;
}
private static void registerCommentsCollectingScannerFactory(Context context) {
try {
- if (Javac.getJavaCompilerVersion() <= 6) {
- Class.forName("lombok.javac.java6.CommentCollectingScannerFactory").getMethod("preRegister", Context.class).invoke(null, context);
+ Class<?> scannerFactory;
+ int javaCompilerVersion = Javac.getJavaCompilerVersion();
+ if (javaCompilerVersion <= 6) {
+ scannerFactory = Class.forName("lombok.javac.java6.CommentCollectingScannerFactory");
+ } else if (javaCompilerVersion == 7) {
+ scannerFactory = Class.forName("lombok.javac.java7.CommentCollectingScannerFactory");
} else {
- Class.forName("lombok.javac.java7.CommentCollectingScannerFactory").getMethod("preRegister", Context.class).invoke(null, context);
+ scannerFactory = Class.forName("lombok.javac.java8.CommentCollectingScannerFactory");
}
+ scannerFactory.getMethod("preRegister", Context.class).invoke(null, context);
+ } catch (InvocationTargetException e) {
+ throw Javac.sneakyThrow(e.getCause());
} catch (Exception e) {
- if (e instanceof RuntimeException) throw (RuntimeException)e;
- throw new RuntimeException(e);
+ throw Javac.sneakyThrow(e);
}
}
private static void setInCompiler(JavaCompiler compiler, Context context, Map<JCCompilationUnit, List<CommentInfo>> commentsMap) {
-
try {
- if (Javac.getJavaCompilerVersion() <= 6) {
- Class<?> parserFactory = Class.forName("lombok.javac.java6.CommentCollectingParserFactory");
- parserFactory.getMethod("setInCompiler", JavaCompiler.class, Context.class, Map.class).invoke(null, compiler, context, commentsMap);
+ Class<?> parserFactory;
+ int javaCompilerVersion = Javac.getJavaCompilerVersion();
+ if (javaCompilerVersion <= 6) {
+ parserFactory = Class.forName("lombok.javac.java6.CommentCollectingParserFactory");
+ } else if (javaCompilerVersion == 7) {
+ parserFactory = Class.forName("lombok.javac.java7.CommentCollectingParserFactory");
} else {
- Class<?> parserFactory = Class.forName("lombok.javac.java7.CommentCollectingParserFactory");
- parserFactory.getMethod("setInCompiler", JavaCompiler.class, Context.class, Map.class).invoke(null, compiler, context, commentsMap);
+ parserFactory = Class.forName("lombok.javac.java8.CommentCollectingParserFactory");
}
+ parserFactory.getMethod("setInCompiler", JavaCompiler.class, Context.class, Map.class).invoke(null, compiler, context, commentsMap);
+ } catch (InvocationTargetException e) {
+ throw Javac.sneakyThrow(e.getCause());
} catch (Exception e) {
- if (e instanceof RuntimeException) throw (RuntimeException)e;
- throw new RuntimeException(e);
+ throw Javac.sneakyThrow(e);
}
}
-
}
diff --git a/src/utils/lombok/javac/Javac.java b/src/utils/lombok/javac/Javac.java
index 4f316d9f..bdf5e7a0 100644
--- a/src/utils/lombok/javac/Javac.java
+++ b/src/utils/lombok/javac/Javac.java
@@ -21,57 +21,105 @@
*/
package lombok.javac;
+import static lombok.javac.JavacTreeMaker.TreeTag.treeTag;
+import static lombok.javac.JavacTreeMaker.TypeTag.typeTag;
+
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import com.sun.tools.javac.code.TypeTags;
+import javax.lang.model.type.NoType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeVisitor;
+
+import lombok.javac.JavacTreeMaker.TreeTag;
+import lombok.javac.JavacTreeMaker.TypeTag;
+
+import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCIdent;
import com.sun.tools.javac.tree.JCTree.JCLiteral;
-import com.sun.tools.javac.tree.JCTree.JCModifiers;
-import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
-import com.sun.tools.javac.tree.TreeMaker;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
/**
* Container for static utility methods relevant to lombok's operation on javac.
*/
public class Javac {
private Javac() {
- //prevent instantiation
+ // prevent instantiation
}
/** Matches any of the 8 primitive names, such as {@code boolean}. */
- private static final Pattern PRIMITIVE_TYPE_NAME_PATTERN = Pattern.compile(
- "^(boolean|byte|short|int|long|float|double|char)$");
+ private static final Pattern PRIMITIVE_TYPE_NAME_PATTERN = Pattern.compile("^(boolean|byte|short|int|long|float|double|char)$");
private static final Pattern VERSION_PARSER = Pattern.compile("^(\\d{1,6})\\.(\\d{1,6}).*$");
+ private static final Pattern SOURCE_PARSER = Pattern.compile("^JDK(\\d{1,6})_(\\d{1,6}).*$");
+
+ private static final AtomicInteger compilerVersion = new AtomicInteger(-1);
/**
* Returns the version of this java compiler, i.e. the JDK that it shipped in. For example, for javac v1.7, this returns {@code 7}.
*/
public static int getJavaCompilerVersion() {
- Matcher m = VERSION_PARSER.matcher(JavaCompiler.version());
- if (m.matches()) {
- int major = Integer.parseInt(m.group(1));
- int minor = Integer.parseInt(m.group(2));
- if (major == 1) return minor;
+ int cv = compilerVersion.get();
+ if (cv != -1) return cv;
+
+ /* Main algorithm: Use JavaCompiler's intended method to do this */ {
+ Matcher m = VERSION_PARSER.matcher(JavaCompiler.version());
+ if (m.matches()) {
+ int major = Integer.parseInt(m.group(1));
+ int minor = Integer.parseInt(m.group(2));
+ if (major == 1) {
+ compilerVersion.set(minor);
+ return minor;
+ }
+ }
}
+ /* Fallback algorithm one: Check Source's values. Lets hope oracle never releases a javac that recognizes future versions for -source */ {
+ String name = Source.values()[Source.values().length - 1].name();
+ Matcher m = SOURCE_PARSER.matcher(name);
+ if (m.matches()) {
+ int major = Integer.parseInt(m.group(1));
+ int minor = Integer.parseInt(m.group(2));
+ if (major == 1) {
+ compilerVersion.set(minor);
+ return minor;
+ }
+ }
+ }
+
+ compilerVersion.set(6);
return 6;
}
+ private static final Class<?> DOCCOMMENTTABLE_CLASS;
+
+ static {
+ Class<?> c = null;
+ try {
+ c = Class.forName("com.sun.tools.javac.tree.DocCommentTable");
+ } catch (Throwable ignore) {}
+ DOCCOMMENTTABLE_CLASS = c;
+ }
+
+ public static boolean instanceOfDocCommentTable(Object o) {
+ return DOCCOMMENTTABLE_CLASS != null && DOCCOMMENTTABLE_CLASS.isInstance(o);
+ }
+
/**
- * Checks if the given expression (that really ought to refer to a type expression) represents a primitive type.
+ * Checks if the given expression (that really ought to refer to a type
+ * expression) represents a primitive type.
*/
public static boolean isPrimitive(JCExpression ref) {
String typeName = ref.toString();
@@ -79,15 +127,16 @@ public class Javac {
}
/**
- * Turns an expression into a guessed intended literal. Only works for literals, as you can imagine.
+ * Turns an expression into a guessed intended literal. Only works for
+ * literals, as you can imagine.
*
* Will for example turn a TrueLiteral into 'Boolean.valueOf(true)'.
*/
public static Object calculateGuess(JCExpression expr) {
if (expr instanceof JCLiteral) {
- JCLiteral lit = (JCLiteral)expr;
+ JCLiteral lit = (JCLiteral) expr;
if (lit.getKind() == com.sun.source.tree.Tree.Kind.BOOLEAN_LITERAL) {
- return ((Number)lit.value).intValue() == 0 ? false : true;
+ return ((Number) lit.value).intValue() == 0 ? false : true;
}
return lit.value;
} else if (expr instanceof JCIdent || expr instanceof JCFieldAccess) {
@@ -98,102 +147,176 @@ public class Javac {
if (idx > -1) x = x.substring(idx + 1);
}
return x;
- } else return null;
- }
-
- public static final int CTC_BOOLEAN = getCtcInt(TypeTags.class, "BOOLEAN");
- public static final int CTC_INT = getCtcInt(TypeTags.class, "INT");
- public static final int CTC_DOUBLE = getCtcInt(TypeTags.class, "DOUBLE");
- public static final int CTC_FLOAT = getCtcInt(TypeTags.class, "FLOAT");
- public static final int CTC_SHORT = getCtcInt(TypeTags.class, "SHORT");
- public static final int CTC_BYTE = getCtcInt(TypeTags.class, "BYTE");
- public static final int CTC_LONG = getCtcInt(TypeTags.class, "LONG");
- public static final int CTC_CHAR = getCtcInt(TypeTags.class, "CHAR");
- public static final int CTC_VOID = getCtcInt(TypeTags.class, "VOID");
- public static final int CTC_NONE = getCtcInt(TypeTags.class, "NONE");
-
- public static final int CTC_NOT_EQUAL = getCtcInt(JCTree.class, "NE");
- public static final int CTC_NOT = getCtcInt(JCTree.class, "NOT");
- public static final int CTC_BITXOR = getCtcInt(JCTree.class, "BITXOR");
- public static final int CTC_UNSIGNED_SHIFT_RIGHT = getCtcInt(JCTree.class, "USR");
- public static final int CTC_MUL = getCtcInt(JCTree.class, "MUL");
- public static final int CTC_PLUS = getCtcInt(JCTree.class, "PLUS");
- public static final int CTC_BOT = getCtcInt(TypeTags.class, "BOT");
- public static final int CTC_EQUAL = getCtcInt(JCTree.class, "EQ");
+ } else
+ return null;
+ }
- /**
- * Retrieves a compile time constant of type int from the specified class location.
- *
- * Solves the problem of compile time constant inlining, resulting in lombok having the wrong value
- * (javac compiler changes private api constants from time to time)
- *
- * @param ctcLocation location of the compile time constant
- * @param identifier the name of the field of the compile time constant.
- */
- public static int getCtcInt(Class<?> ctcLocation, String identifier) {
+ public static final TypeTag CTC_BOOLEAN = typeTag("BOOLEAN");
+ public static final TypeTag CTC_INT = typeTag("INT");
+ public static final TypeTag CTC_DOUBLE = typeTag("DOUBLE");
+ public static final TypeTag CTC_FLOAT = typeTag("FLOAT");
+ public static final TypeTag CTC_SHORT = typeTag("SHORT");
+ public static final TypeTag CTC_BYTE = typeTag("BYTE");
+ public static final TypeTag CTC_LONG = typeTag("LONG");
+ public static final TypeTag CTC_CHAR = typeTag("CHAR");
+ public static final TypeTag CTC_VOID = typeTag("VOID");
+ public static final TypeTag CTC_NONE = typeTag("NONE");
+ public static final TypeTag CTC_BOT = typeTag("BOT");
+ public static final TypeTag CTC_CLASS = typeTag("CLASS");
+
+ public static final TreeTag CTC_NOT_EQUAL = treeTag("NE");
+ public static final TreeTag CTC_POS = treeTag("POS");
+ public static final TreeTag CTC_NEG = treeTag("NEG");
+ public static final TreeTag CTC_NOT = treeTag("NOT");
+ public static final TreeTag CTC_COMPL = treeTag("COMPL");
+ public static final TreeTag CTC_BITXOR = treeTag("BITXOR");
+ public static final TreeTag CTC_UNSIGNED_SHIFT_RIGHT = treeTag("USR");
+ public static final TreeTag CTC_MUL = treeTag("MUL");
+ public static final TreeTag CTC_PLUS = treeTag("PLUS");
+ public static final TreeTag CTC_EQUAL = treeTag("EQ");
+ public static final TreeTag CTC_PREINC = treeTag("PREINC");
+ public static final TreeTag CTC_PREDEC = treeTag("PREDEC");
+
+ private static final Method getExtendsClause, getEndPosition;
+
+ static {
+ getExtendsClause = getMethod(JCClassDecl.class, "getExtendsClause", new Class<?>[0]);
+ getExtendsClause.setAccessible(true);
+
+ if (getJavaCompilerVersion() < 8) {
+ getEndPosition = getMethod(DiagnosticPosition.class, "getEndPosition", java.util.Map.class);
+ } else {
+ getEndPosition = getMethod(DiagnosticPosition.class, "getEndPosition", "com.sun.tools.javac.tree.EndPosTable");
+ }
+ getEndPosition.setAccessible(true);
+ }
+
+ private static Method getMethod(Class<?> clazz, String name, Class<?>... paramTypes) {
try {
- return (Integer)ctcLocation.getField(identifier).get(null);
- } catch (NoSuchFieldException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
+ return clazz.getMethod(name, paramTypes);
+ } catch (NoSuchMethodException e) {
+ throw sneakyThrow(e);
}
}
- private static final Field JCTREE_TAG;
- private static final Method JCTREE_GETTAG;
- static {
- Field f = null;
+ private static Method getMethod(Class<?> clazz, String name, String... paramTypes) {
try {
- f = JCTree.class.getDeclaredField("tag");
- } catch (NoSuchFieldException e) {}
- JCTREE_TAG = f;
-
- Method m = null;
+ Class<?>[] c = new Class[paramTypes.length];
+ for (int i = 0; i < paramTypes.length; i++) c[i] = Class.forName(paramTypes[i]);
+ return clazz.getMethod(name, c);
+ } catch (NoSuchMethodException e) {
+ throw sneakyThrow(e);
+ } catch (ClassNotFoundException e) {
+ throw sneakyThrow(e);
+ }
+ }
+
+ public static JCTree getExtendsClause(JCClassDecl decl) {
try {
- m = JCTree.class.getDeclaredMethod("getTag");
- } catch (NoSuchMethodException e) {}
- JCTREE_GETTAG = m;
+ return (JCTree) getExtendsClause.invoke(decl);
+ } catch (IllegalAccessException e) {
+ throw sneakyThrow(e);
+ } catch (InvocationTargetException e) {
+ throw sneakyThrow(e.getCause());
+ }
}
- public static int getTag(JCTree node) {
- if (JCTREE_GETTAG != null) {
- try {
- return (Integer) JCTREE_GETTAG.invoke(node);
- } catch (Exception e) {}
+ public static Object getDocComments(JCCompilationUnit cu) {
+ try {
+ return JCCOMPILATIONUNIT_DOCCOMMENTS.get(cu);
+ } catch (IllegalAccessException e) {
+ throw sneakyThrow(e);
+ }
+ }
+
+ public static void initDocComments(JCCompilationUnit cu) {
+ try {
+ JCCOMPILATIONUNIT_DOCCOMMENTS.set(cu, new HashMap<Object, String>());
+ } catch (IllegalArgumentException e) {
+ // That's fine - we're on JDK8, we'll fix that later.
+ } catch (IllegalAccessException e) {
+ throw sneakyThrow(e);
}
+ }
+
+ public static int getEndPosition(DiagnosticPosition pos, JCCompilationUnit top) {
try {
- return (Integer) JCTREE_TAG.get(node);
- } catch (Exception e) {
- throw new IllegalStateException("Can't get node tag");
+ Object endPositions = JCCOMPILATIONUNIT_ENDPOSITIONS.get(top);
+ return (Integer) getEndPosition.invoke(pos, endPositions);
+ } catch (IllegalAccessException e) {
+ throw sneakyThrow(e);
+ } catch (InvocationTargetException e) {
+ throw sneakyThrow(e.getCause());
}
}
- private static Method method;
+ private static final Class<?> JC_VOID_TYPE, JC_NO_TYPE;
+
+ static {
+ Class<?> c = null;
+ try {
+ c = Class.forName("com.sun.tools.javac.code.Type$JCVoidType");
+ } catch (Throwable ignore) {}
+ JC_VOID_TYPE = c;
+ c = null;
+ try {
+ c = Class.forName("com.sun.tools.javac.code.Type$JCNoType");
+ } catch (Throwable ignore) {}
+ JC_NO_TYPE = c;
+ }
- public static JCClassDecl ClassDef(TreeMaker maker, JCModifiers mods, Name name, List<JCTypeParameter> typarams, JCExpression extending, List<JCExpression> implementing, List<JCTree> defs) {
- if (method == null) try {
- method = TreeMaker.class.getDeclaredMethod("ClassDef", JCModifiers.class, Name.class, List.class, JCExpression.class, List.class, List.class);
- } catch (NoSuchMethodException ignore) {}
- if (method == null) try {
- method = TreeMaker.class.getDeclaredMethod("ClassDef", JCModifiers.class, Name.class, List.class, JCTree.class, List.class, List.class);
- } catch (NoSuchMethodException ignore) {}
+ public static Type createVoidType(JavacTreeMaker maker, TypeTag tag) {
+ if (Javac.getJavaCompilerVersion() < 8) {
+ return new JCNoType(((Integer) tag.value).intValue());
+ } else {
+ try {
+ if (CTC_VOID.equals(tag)) {
+ return (Type) JC_VOID_TYPE.newInstance();
+ } else {
+ return (Type) JC_NO_TYPE.newInstance();
+ }
+ } catch (IllegalAccessException e) {
+ throw sneakyThrow(e);
+ } catch (InstantiationException e) {
+ throw sneakyThrow(e);
+ }
+ }
+ }
+
+ private static class JCNoType extends Type implements NoType {
+ public JCNoType(int tag) {
+ super(tag, null);
+ }
- if (method == null) throw new IllegalStateException("Lombok bug #20130617-1310: ClassDef doesn't look like anything we thought it would look like.");
- if (!Modifier.isPublic(method.getModifiers()) && !method.isAccessible()) {
- method.setAccessible(true);
+ @Override
+ public TypeKind getKind() {
+ if (tag == ((Integer) CTC_VOID.value).intValue()) return TypeKind.VOID;
+ if (tag == ((Integer) CTC_NONE.value).intValue()) return TypeKind.NONE;
+ throw new AssertionError("Unexpected tag: " + tag);
}
- try {
- return (JCClassDecl) method.invoke(maker, mods, name, typarams, extending, implementing, defs);
- } catch (InvocationTargetException e) {
- throw sneakyThrow(e.getCause());
- } catch (IllegalAccessException e) {
- throw sneakyThrow(e.getCause());
+ @Override
+ public <R, P> R accept(TypeVisitor<R, P> v, P p) {
+ return v.visitNoType(this, p);
}
}
- private static RuntimeException sneakyThrow(Throwable t) {
+ private static final Field JCCOMPILATIONUNIT_ENDPOSITIONS, JCCOMPILATIONUNIT_DOCCOMMENTS;
+ static {
+ Field f = null;
+ try {
+ f = JCCompilationUnit.class.getDeclaredField("endPositions");
+ } catch (NoSuchFieldException e) {}
+ JCCOMPILATIONUNIT_ENDPOSITIONS = f;
+
+ f = null;
+ try {
+ f = JCCompilationUnit.class.getDeclaredField("docComments");
+ } catch (NoSuchFieldException e) {}
+ JCCOMPILATIONUNIT_DOCCOMMENTS = f;
+ }
+
+ static RuntimeException sneakyThrow(Throwable t) {
if (t == null) throw new NullPointerException("t");
Javac.<RuntimeException>sneakyThrow0(t);
return null;
diff --git a/src/utils/lombok/javac/JavacTreeMaker.java b/src/utils/lombok/javac/JavacTreeMaker.java
new file mode 100644
index 00000000..12baf5af
--- /dev/null
+++ b/src/utils/lombok/javac/JavacTreeMaker.java
@@ -0,0 +1,830 @@
+/*
+ * 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 java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import com.sun.tools.javac.code.Attribute;
+import com.sun.tools.javac.code.BoundKind;
+import com.sun.tools.javac.code.Symbol;
+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.JCArrayAccess;
+import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree;
+import com.sun.tools.javac.tree.JCTree.JCAssert;
+import com.sun.tools.javac.tree.JCTree.JCAssign;
+import com.sun.tools.javac.tree.JCTree.JCAssignOp;
+import com.sun.tools.javac.tree.JCTree.JCBinary;
+import com.sun.tools.javac.tree.JCTree.JCBlock;
+import com.sun.tools.javac.tree.JCTree.JCBreak;
+import com.sun.tools.javac.tree.JCTree.JCCase;
+import com.sun.tools.javac.tree.JCTree.JCCatch;
+import com.sun.tools.javac.tree.JCTree.JCClassDecl;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.tree.JCTree.JCConditional;
+import com.sun.tools.javac.tree.JCTree.JCContinue;
+import com.sun.tools.javac.tree.JCTree.JCDoWhileLoop;
+import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop;
+import com.sun.tools.javac.tree.JCTree.JCErroneous;
+import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.JCTree.JCExpressionStatement;
+import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
+import com.sun.tools.javac.tree.JCTree.JCForLoop;
+import com.sun.tools.javac.tree.JCTree.JCIdent;
+import com.sun.tools.javac.tree.JCTree.JCIf;
+import com.sun.tools.javac.tree.JCTree.JCImport;
+import com.sun.tools.javac.tree.JCTree.JCInstanceOf;
+import com.sun.tools.javac.tree.JCTree.JCLabeledStatement;
+import com.sun.tools.javac.tree.JCTree.JCLiteral;
+import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
+import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
+import com.sun.tools.javac.tree.JCTree.JCModifiers;
+import com.sun.tools.javac.tree.JCTree.JCNewArray;
+import com.sun.tools.javac.tree.JCTree.JCNewClass;
+import com.sun.tools.javac.tree.JCTree.JCParens;
+import com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree;
+import com.sun.tools.javac.tree.JCTree.JCReturn;
+import com.sun.tools.javac.tree.JCTree.JCSkip;
+import com.sun.tools.javac.tree.JCTree.JCStatement;
+import com.sun.tools.javac.tree.JCTree.JCSwitch;
+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.JCTypeApply;
+import com.sun.tools.javac.tree.JCTree.JCTypeCast;
+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.JCTree.JCWhileLoop;
+import com.sun.tools.javac.tree.JCTree.JCWildcard;
+import com.sun.tools.javac.tree.JCTree.LetExpr;
+import com.sun.tools.javac.tree.JCTree.TypeBoundKind;
+import com.sun.tools.javac.tree.TreeInfo;
+import com.sun.tools.javac.tree.TreeMaker;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Name;
+
+public class JavacTreeMaker {
+ private final TreeMaker tm;
+
+ public JavacTreeMaker(TreeMaker tm) {
+ this.tm = tm;
+ }
+
+ public TreeMaker getUnderlyingTreeMaker() {
+ return tm;
+ }
+
+ public JavacTreeMaker at(int pos) {
+ tm.at(pos);
+ return this;
+ }
+
+ private static class MethodId<J> {
+ private final Class<?> owner;
+ private final String name;
+ private final Class<J> returnType;
+ private final Class<?>[] paramTypes;
+
+ MethodId(Class<?> owner, String name, Class<J> returnType, Class<?>... types) {
+ this.owner = owner;
+ this.name = name;
+ this.paramTypes = types;
+ this.returnType = returnType;
+ }
+
+ @Override public String toString() {
+ StringBuilder out = new StringBuilder();
+ out.append(returnType.getName()).append(" ").append(owner.getName()).append(".").append(name).append("(");
+ boolean f = true;
+ for (Class<?> p : paramTypes) {
+ if (f) f = false;
+ else out.append(", ");
+ out.append(p.getName());
+ }
+ return out.append(")").toString();
+ }
+ }
+
+ private static class SchroedingerType {
+ final Object value;
+
+ private SchroedingerType(Object value) {
+ this.value = value;
+ }
+
+ @Override public int hashCode() {
+ return value == null ? -1 : value.hashCode();
+ }
+
+ @Override public boolean equals(Object obj) {
+ if (obj instanceof SchroedingerType) {
+ Object other = ((SchroedingerType) obj).value;
+ return value == null ? other == null : value.equals(other);
+ }
+ return false;
+ }
+
+ static Object getFieldCached(ConcurrentMap<String, Object> cache, String className, String fieldName) {
+ Object value = cache.get(fieldName);
+ if (value != null) return value;
+ try {
+ value = Class.forName(className).getField(fieldName).get(null);
+ } catch (NoSuchFieldException e) {
+ throw Javac.sneakyThrow(e);
+ } catch (IllegalAccessException e) {
+ throw Javac.sneakyThrow(e);
+ } catch (ClassNotFoundException e) {
+ throw Javac.sneakyThrow(e);
+ }
+
+ cache.putIfAbsent(fieldName, value);
+ return value;
+ }
+
+ private static Field NOSUCHFIELDEX_MARKER;
+ static {
+ try {
+ NOSUCHFIELDEX_MARKER = SchroedingerType.class.getDeclaredField("NOSUCHFIELDEX_MARKER");
+ } catch (NoSuchFieldException e) {
+ throw Javac.sneakyThrow(e);
+ }
+ }
+
+ static Object getFieldCached(ConcurrentMap<Class<?>, Field> cache, Object ref, String fieldName) throws NoSuchFieldException {
+ Class<?> c = ref.getClass();
+ Field field = cache.get(c);
+ if (field == null) {
+ try {
+ field = c.getField(fieldName);
+ } catch (NoSuchFieldException e) {
+ cache.putIfAbsent(c, NOSUCHFIELDEX_MARKER);
+ throw Javac.sneakyThrow(e);
+ }
+ field.setAccessible(true);
+ Field old = cache.putIfAbsent(c, field);
+ if (old != null) field = old;
+ }
+
+ if (field == NOSUCHFIELDEX_MARKER) throw new NoSuchFieldException(fieldName);
+ try {
+ return field.get(ref);
+ } catch (IllegalAccessException e) {
+ throw Javac.sneakyThrow(e);
+ }
+ }
+ }
+
+ public static class TypeTag extends SchroedingerType {
+ private static final ConcurrentMap<String, Object> TYPE_TAG_CACHE = new ConcurrentHashMap<String, Object>();
+ private static final ConcurrentMap<Class<?>, Field> FIELD_CACHE = new ConcurrentHashMap<Class<?>, Field>();
+ private static final Method TYPE_TYPETAG_METHOD;
+
+ static {
+ Method m = null;
+ try {
+ m = Type.class.getDeclaredMethod("getTag");
+ m.setAccessible(true);
+ } catch (NoSuchMethodException e) {}
+ TYPE_TYPETAG_METHOD = m;
+ }
+
+ private TypeTag(Object value) {
+ super(value);
+ }
+
+ public static TypeTag typeTag(JCTree o) {
+ try {
+ return new TypeTag(getFieldCached(FIELD_CACHE, o, "typetag"));
+ } catch (NoSuchFieldException e) {
+ throw Javac.sneakyThrow(e);
+ }
+ }
+
+ public static TypeTag typeTag(Type t) {
+ try {
+ return new TypeTag(getFieldCached(FIELD_CACHE, t, "tag"));
+ } catch (NoSuchFieldException e) {
+ if (TYPE_TYPETAG_METHOD == null) throw new IllegalStateException("Type " + t.getClass() + " has neither 'tag' nor getTag()");
+ try {
+ return new TypeTag(TYPE_TYPETAG_METHOD.invoke(t));
+ } catch (IllegalAccessException ex) {
+ throw Javac.sneakyThrow(ex);
+ } catch (InvocationTargetException ex) {
+ throw Javac.sneakyThrow(ex.getCause());
+ }
+ }
+ }
+
+ public static TypeTag typeTag(String identifier) {
+ return new TypeTag(getFieldCached(TYPE_TAG_CACHE, Javac.getJavaCompilerVersion() < 8 ? "com.sun.tools.javac.code.TypeTags" : "com.sun.tools.javac.code.TypeTag", identifier));
+ }
+ }
+
+ public static class TreeTag extends SchroedingerType {
+ private static final ConcurrentMap<String, Object> TREE_TAG_CACHE = new ConcurrentHashMap<String, Object>();
+ private static final Field TAG_FIELD;
+ private static final Method TAG_METHOD;
+ private static final MethodId<Integer> OP_PREC = MethodId(TreeInfo.class, "opPrec", int.class, TreeTag.class);
+
+ static {
+ Method m = null;
+ try {
+ m = JCTree.class.getDeclaredMethod("getTag");
+ m.setAccessible(true);
+ } catch (NoSuchMethodException e) {}
+
+ if (m != null) {
+ TAG_FIELD = null;
+ TAG_METHOD = m;
+ } else {
+ Field f = null;
+ try {
+ f = JCTree.class.getDeclaredField("tag");
+ f.setAccessible(true);
+ } catch (NoSuchFieldException e) {}
+ TAG_FIELD = f;
+ TAG_METHOD = null;
+ }
+ }
+
+ private TreeTag(Object value) {
+ super(value);
+ }
+
+ public static TreeTag treeTag(JCTree o) {
+ try {
+ if (TAG_METHOD != null) return new TreeTag(TAG_METHOD.invoke(o));
+ else return new TreeTag(TAG_FIELD.get(o));
+ } catch (InvocationTargetException e) {
+ throw Javac.sneakyThrow(e.getCause());
+ } catch (IllegalAccessException e) {
+ throw Javac.sneakyThrow(e);
+ }
+ }
+
+ public static TreeTag treeTag(String identifier) {
+ return new TreeTag(getFieldCached(TREE_TAG_CACHE, Javac.getJavaCompilerVersion() < 8 ? "com.sun.tools.javac.tree.JCTree" : "com.sun.tools.javac.tree.JCTree$Tag", identifier));
+ }
+
+ public int getOperatorPrecedenceLevel() {
+ return invokeAny(null, OP_PREC, value);
+ }
+
+ public boolean isPrefixUnaryOp() {
+ return Javac.CTC_NEG.equals(this) || Javac.CTC_POS.equals(this) || Javac.CTC_NOT.equals(this) || Javac.CTC_COMPL.equals(this) || Javac.CTC_PREDEC.equals(this) || Javac.CTC_PREINC.equals(this);
+ }
+ }
+
+ static <J> MethodId<J> MethodId(Class<?> owner, String name, Class<J> returnType, Class<?>... types) {
+ return new MethodId<J>(owner, name, returnType, types);
+ }
+
+ /**
+ * Creates a new method ID based on the name of the method to invoke, the return type of that method, and the types of the parameters.
+ *
+ * A method matches if the return type matches, and for each parameter the following holds:
+ *
+ * Either (A) the type listed here is the same as, or a subtype of, the type of the method in javac's TreeMaker, or
+ * (B) the type listed here is a subtype of SchroedingerType.
+ */
+ static <J> MethodId<J> MethodId(String name, Class<J> returnType, Class<?>... types) {
+ return new MethodId<J>(TreeMaker.class, name, returnType, types);
+ }
+
+ /**
+ * Creates a new method ID based on the name of a method in this class, assuming the name of the method to invoke in TreeMaker has the same name,
+ * the same return type, and the same parameters (under the same rules as the other MethodId method).
+ */
+ static <J> MethodId<J> MethodId(String name) {
+ for (Method m : JavacTreeMaker.class.getDeclaredMethods()) {
+ if (m.getName().equals(name)) {
+ @SuppressWarnings("unchecked") Class<J> r = (Class<J>) m.getReturnType();
+ Class<?>[] p = m.getParameterTypes();
+ return new MethodId<J>(TreeMaker.class, name, r, p);
+ }
+ }
+
+ throw new InternalError("Not found: " + name);
+ }
+
+ private static final ConcurrentHashMap<MethodId<?>, Method> METHOD_CACHE = new ConcurrentHashMap<MethodId<?>, Method>();
+ private <J> J invoke(MethodId<J> m, Object... args) {
+ return invokeAny(tm, m, args);
+ }
+
+ @SuppressWarnings("unchecked") private static <J> J invokeAny(Object owner, MethodId<J> m, Object... args) {
+ Method method = METHOD_CACHE.get(m);
+ if (method == null) method = addToCache(m);
+ try {
+ if (m.returnType.isPrimitive()) {
+ Object res = method.invoke(owner, args);
+ String sn = res.getClass().getSimpleName().toLowerCase();
+ if (!sn.startsWith(m.returnType.getSimpleName())) throw new ClassCastException(res.getClass() + " to " + m.returnType);
+ return (J) res;
+ }
+ return m.returnType.cast(method.invoke(owner, args));
+ } catch (InvocationTargetException e) {
+ throw Javac.sneakyThrow(e.getCause());
+ } catch (IllegalAccessException e) {
+ throw Javac.sneakyThrow(e);
+ } catch (IllegalArgumentException e) {
+ System.err.println(method);
+ throw Javac.sneakyThrow(e);
+ }
+ }
+
+ private static Method addToCache(MethodId<?> m) {
+ Method found = null;
+
+ outer:
+ for (Method method : m.owner.getDeclaredMethods()) {
+ if (!m.name.equals(method.getName())) continue;
+ Class<?>[] t = method.getParameterTypes();
+ if (t.length != m.paramTypes.length) continue;
+ for (int i = 0; i < t.length; i++) {
+ if (Symbol.class.isAssignableFrom(t[i])) continue outer;
+ if (!SchroedingerType.class.isAssignableFrom(m.paramTypes[i])) {
+ if (t[i].isPrimitive()) {
+ if (t[i] != m.paramTypes[i]) continue outer;
+ } else {
+ if (!t[i].isAssignableFrom(m.paramTypes[i])) continue outer;
+ }
+ }
+ }
+ if (found == null) found = method;
+ else throw new IllegalStateException("Lombok TreeMaker frontend issue: multiple matches when looking for method: " + m);
+ }
+ if (found == null) throw new IllegalStateException("Lombok TreeMaker frontend issue: no match when looking for method: " + m);
+ found.setAccessible(true);
+ Object marker = METHOD_CACHE.putIfAbsent(m, found);
+ if (marker == null) return found;
+ return METHOD_CACHE.get(m);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCCompilationUnit> TopLevel = MethodId("TopLevel");
+ public JCCompilationUnit TopLevel(List<JCAnnotation> packageAnnotations, JCExpression pid, List<JCTree> defs) {
+ return invoke(TopLevel, packageAnnotations, pid, defs);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCImport> Import = MethodId("Import");
+ public JCImport Import(JCTree qualid, boolean staticImport) {
+ return invoke(Import, qualid, staticImport);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCClassDecl> ClassDef = MethodId("ClassDef");
+ public JCClassDecl ClassDef(JCModifiers mods, Name name, List<JCTypeParameter> typarams, JCExpression extending, List<JCExpression> implementing, List<JCTree> defs) {
+ return invoke(ClassDef, mods, name, typarams, extending, implementing, defs);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCMethodDecl> MethodDef = MethodId("MethodDef", JCMethodDecl.class, JCModifiers.class, Name.class, JCExpression.class, List.class, List.class, List.class, JCBlock.class, JCExpression.class);
+ public JCMethodDecl MethodDef(JCModifiers mods, Name name, JCExpression resType, List<JCTypeParameter> typarams, List<JCVariableDecl> params, List<JCExpression> thrown, JCBlock body, JCExpression defaultValue) {
+ return invoke(MethodDef, mods, name, resType, typarams, params, thrown, body, defaultValue);
+ }
+
+ //javac versions: 8
+ private static final MethodId<JCMethodDecl> MethodDefWithRecvParam = MethodId("MethodDef", JCMethodDecl.class, JCModifiers.class, Name.class, JCExpression.class, List.class, JCVariableDecl.class, List.class, List.class, JCBlock.class, JCExpression.class);
+ public JCMethodDecl MethodDef(JCModifiers mods, Name name, JCExpression resType, List<JCTypeParameter> typarams, JCVariableDecl recvparam, List<JCVariableDecl> params, List<JCExpression> thrown, JCBlock body, JCExpression defaultValue) {
+ return invoke(MethodDefWithRecvParam, mods, name, resType, recvparam, typarams, params, thrown, body, defaultValue);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCVariableDecl> VarDef = MethodId("VarDef");
+ public JCVariableDecl VarDef(JCModifiers mods, Name name, JCExpression vartype, JCExpression init) {
+ return invoke(VarDef, mods, name, vartype, init);
+ }
+
+ //javac versions: 8
+ private static final MethodId<JCVariableDecl> ReceiverVarDef = MethodId("ReceiverVarDef");
+ public JCVariableDecl ReceiverVarDef(JCModifiers mods, JCExpression name, JCExpression vartype) {
+ return invoke(ReceiverVarDef, mods, name, vartype);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCSkip> Skip = MethodId("Skip");
+ public JCSkip Skip() {
+ return invoke(Skip);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCBlock> Block = MethodId("Block");
+ public JCBlock Block(long flags, List<JCStatement> stats) {
+ return invoke(Block, flags, stats);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCDoWhileLoop> DoLoop = MethodId("DoLoop");
+ public JCDoWhileLoop DoLoop(JCStatement body, JCExpression cond) {
+ return invoke(DoLoop, body, cond);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCWhileLoop> WhileLoop = MethodId("WhileLoop");
+ public JCWhileLoop WhileLoop(JCExpression cond, JCStatement body) {
+ return invoke(WhileLoop, cond, body);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCForLoop> ForLoop = MethodId("ForLoop");
+ public JCForLoop ForLoop(List<JCStatement> init, JCExpression cond, List<JCExpressionStatement> step, JCStatement body) {
+ return invoke(ForLoop, init, cond, step, body);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCEnhancedForLoop> ForeachLoop = MethodId("ForeachLoop");
+ public JCEnhancedForLoop ForeachLoop(JCVariableDecl var, JCExpression expr, JCStatement body) {
+ return invoke(ForeachLoop, var, expr, body);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCLabeledStatement> Labelled = MethodId("Labelled");
+ public JCLabeledStatement Labelled(Name label, JCStatement body) {
+ return invoke(Labelled, label, body);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCSwitch> Switch = MethodId("Switch");
+ public JCSwitch Switch(JCExpression selector, List<JCCase> cases) {
+ return invoke(Switch, selector, cases);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCCase> Case = MethodId("Case");
+ public JCCase Case(JCExpression pat, List<JCStatement> stats) {
+ return invoke(Case, pat, stats);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCSynchronized> Synchronized = MethodId("Synchronized");
+ public JCSynchronized Synchronized(JCExpression lock, JCBlock body) {
+ return invoke(Synchronized, lock, body);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCTry> Try = MethodId("Try", JCTry.class, JCBlock.class, List.class, JCBlock.class);
+ public JCTry Try(JCBlock body, List<JCCatch> catchers, JCBlock finalizer) {
+ return invoke(Try, body, catchers, finalizer);
+ }
+
+ //javac versions: 7-8
+ private static final MethodId<JCTry> TryWithResources = MethodId("Try", JCTry.class, List.class, JCBlock.class, List.class, JCBlock.class);
+ public JCTry Try(List<JCTree> resources, JCBlock body, List<JCCatch> catchers, JCBlock finalizer) {
+ return invoke(TryWithResources, resources, body, catchers, finalizer);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCCatch> Catch = MethodId("Catch");
+ public JCCatch Catch(JCVariableDecl param, JCBlock body) {
+ return invoke(Catch, param, body);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCConditional> Conditional = MethodId("Conditional");
+ public JCConditional Conditional(JCExpression cond, JCExpression thenpart, JCExpression elsepart) {
+ return invoke(Conditional, cond, thenpart, elsepart);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCIf> If = MethodId("If");
+ public JCIf If(JCExpression cond, JCStatement thenpart, JCStatement elsepart) {
+ return invoke(If, cond, thenpart, elsepart);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCExpressionStatement> Exec = MethodId("Exec");
+ public JCExpressionStatement Exec(JCExpression expr) {
+ return invoke(Exec, expr);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCBreak> Break = MethodId("Break");
+ public JCBreak Break(Name label) {
+ return invoke(Break, label);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCContinue> Continue = MethodId("Continue");
+ public JCContinue Continue(Name label) {
+ return invoke(Continue, label);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCReturn> Return = MethodId("Return");
+ public JCReturn Return(JCExpression expr) {
+ return invoke(Return, expr);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCThrow> Throw = MethodId("Throw");
+ public JCThrow Throw(JCExpression expr) {
+ return invoke(Throw, expr);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCAssert> Assert = MethodId("Assert");
+ public JCAssert Assert(JCExpression cond, JCExpression detail) {
+ return invoke(Assert, cond, detail);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCMethodInvocation> Apply = MethodId("Apply");
+ public JCMethodInvocation Apply(List<JCExpression> typeargs, JCExpression fn, List<JCExpression> args) {
+ return invoke(Apply, typeargs, fn, args);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCNewClass> NewClass = MethodId("NewClass");
+ public JCNewClass NewClass(JCExpression encl, List<JCExpression> typeargs, JCExpression clazz, List<JCExpression> args, JCClassDecl def) {
+ return invoke(NewClass, encl, typeargs, clazz, args, def);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCNewArray> NewArray = MethodId("NewArray");
+ public JCNewArray NewArray(JCExpression elemtype, List<JCExpression> dims, List<JCExpression> elems) {
+ return invoke(NewArray, elemtype, dims, elems);
+ }
+
+ //javac versions: 8
+// private static final MethodId<JCLambda> Lambda = MethodId("Lambda");
+// public JCLambda Lambda(List<JCVariableDecl> params, JCTree body) {
+// return invoke(Lambda, params, body);
+// }
+
+ //javac versions: 6-8
+ private static final MethodId<JCParens> Parens = MethodId("Parens");
+ public JCParens Parens(JCExpression expr) {
+ return invoke(Parens, expr);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCAssign> Assign = MethodId("Assign");
+ public JCAssign Assign(JCExpression lhs, JCExpression rhs) {
+ return invoke(Assign, lhs, rhs);
+ }
+
+ //javac versions: 6-8
+ //opcode = [6-7] int [8] JCTree.Tag
+ private static final MethodId<JCAssignOp> Assignop = MethodId("Assignop");
+ public JCAssignOp Assignop(TreeTag opcode, JCTree lhs, JCTree rhs) {
+ return invoke(Assignop, opcode.value, lhs, rhs);
+ }
+
+ //javac versions: 6-8
+ //opcode = [6-7] int [8] JCTree.Tag
+ private static final MethodId<JCUnary> Unary = MethodId("Unary");
+ public JCUnary Unary(TreeTag opcode, JCExpression arg) {
+ return invoke(Unary, opcode.value, arg);
+ }
+
+ //javac versions: 6-8
+ //opcode = [6-7] int [8] JCTree.Tag
+ private static final MethodId<JCBinary> Binary = MethodId("Binary");
+ public JCBinary Binary(TreeTag opcode, JCExpression lhs, JCExpression rhs) {
+ return invoke(Binary, opcode.value, lhs, rhs);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCTypeCast> TypeCast = MethodId("TypeCast");
+ public JCTypeCast TypeCast(JCTree expr, JCExpression type) {
+ return invoke(TypeCast, expr, type);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCInstanceOf> TypeTest = MethodId("TypeTest");
+ public JCInstanceOf TypeTest(JCExpression expr, JCTree clazz) {
+ return invoke(TypeTest, expr, clazz);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCArrayAccess> Indexed = MethodId("Indexed");
+ public JCArrayAccess Indexed(JCExpression indexed, JCExpression index) {
+ return invoke(Indexed, indexed, index);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCFieldAccess> Select = MethodId("Select");
+ public JCFieldAccess Select(JCExpression selected, Name selector) {
+ return invoke(Select, selected, selector);
+ }
+
+ //javac versions: 8
+// private static final MethodId<JCMemberReference> Reference = MethodId("Reference");
+// public JCMemberReference Reference(JCMemberReference.ReferenceMode mode, Name name, JCExpression expr, List<JCExpression> typeargs) {
+// return invoke(Reference, mode, name, expr, typeargs);
+// }
+
+ //javac versions: 6-8
+ private static final MethodId<JCIdent> Ident = MethodId("Ident", JCIdent.class, Name.class);
+ public JCIdent Ident(Name idname) {
+ return invoke(Ident, idname);
+ }
+
+ //javac versions: 6-8
+ //tag = [6-7] int [8] TypeTag
+ private static final MethodId<JCLiteral> Literal = MethodId("Literal", JCLiteral.class, TypeTag.class, Object.class);
+ public JCLiteral Literal(TypeTag tag, Object value) {
+ return invoke(Literal, tag.value, value);
+ }
+
+ //javac versions: 6-8
+ //typetag = [6-7] int [8] TypeTag
+ private static final MethodId<JCPrimitiveTypeTree> TypeIdent = MethodId("TypeIdent");
+ public JCPrimitiveTypeTree TypeIdent(TypeTag typetag) {
+ return invoke(TypeIdent, typetag.value);
+ }
+ //javac versions: 6-8
+ private static final MethodId<JCArrayTypeTree> TypeArray = MethodId("TypeArray");
+ public JCArrayTypeTree TypeArray(JCExpression elemtype) {
+ return invoke(TypeArray, elemtype);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCTypeApply> TypeApply = MethodId("TypeApply");
+ public JCTypeApply TypeApply(JCExpression clazz, List<JCExpression> arguments) {
+ return invoke(TypeApply, clazz, arguments);
+ }
+
+ //javac versions: 7-8
+// private static final MethodId<JCTypeUnion> TypeUnion = MethodId("TypeUnion");
+// public JCTypeUnion TypeUnion(List<JCExpression> components) {
+// return invoke(TypeUnion, compoonents);
+// }
+
+ //javac versions: 8
+// private static final MethodId<JCTypeIntersection> TypeIntersection = MethodId("TypeIntersection");
+// public JCTypeIntersection TypeIntersection(List<JCExpression> components) {
+// return invoke(TypeIntersection, components);
+// }
+
+ //javac versions: 6-8
+ private static final MethodId<JCTypeParameter> TypeParameter = MethodId("TypeParameter", JCTypeParameter.class, Name.class, List.class);
+ public JCTypeParameter TypeParameter(Name name, List<JCExpression> bounds) {
+ return invoke(TypeParameter, name, bounds);
+ }
+
+ //javac versions: 8
+ private static final MethodId<JCTypeParameter> TypeParameterWithAnnos = MethodId("TypeParameter", JCTypeParameter.class, Name.class, List.class, List.class);
+ public JCTypeParameter TypeParameter(Name name, List<JCExpression> bounds, List<JCAnnotation> annos) {
+ return invoke(TypeParameterWithAnnos, name, bounds, annos);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCWildcard> Wildcard = MethodId("Wildcard");
+ public JCWildcard Wildcard(TypeBoundKind kind, JCTree type) {
+ return invoke(Wildcard, kind, type);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<TypeBoundKind> TypeBoundKind = MethodId("TypeBoundKind");
+ public TypeBoundKind TypeBoundKind(BoundKind kind) {
+ return invoke(TypeBoundKind, kind);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCAnnotation> Annotation = MethodId("Annotation", JCAnnotation.class, JCTree.class, List.class);
+ public JCAnnotation Annotation(JCTree annotationType, List<JCExpression> args) {
+ return invoke(Annotation, annotationType, args);
+ }
+
+ //javac versions: 8
+ private static final MethodId<JCAnnotation> TypeAnnotation = MethodId("TypeAnnotation", JCAnnotation.class, JCTree.class, List.class);
+ public JCAnnotation TypeAnnotation(JCTree annotationType, List<JCExpression> args) {
+ return invoke(TypeAnnotation, annotationType, args);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCModifiers> ModifiersWithAnnotations = MethodId("Modifiers", JCModifiers.class, long.class, List.class);
+ public JCModifiers Modifiers(long flags, List<JCAnnotation> annotations) {
+ return invoke(ModifiersWithAnnotations, flags, annotations);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCModifiers> Modifiers = MethodId("Modifiers", JCModifiers.class, long.class);
+ public JCModifiers Modifiers(long flags) {
+ return invoke(Modifiers, flags);
+ }
+
+ //javac versions: 8
+// private static final MethodId<JCAnnotatedType> AnnotatedType = MethodId("AnnotatedType");
+// public JCAnnotatedType AnnotatedType(List<JCAnnotation> annotations, JCExpression underlyingType) {
+// return invoke(AnnotatedType, annotations, underlyingType);
+// }
+
+ //javac versions: 6-8
+ private static final MethodId<JCErroneous> Erroneous = MethodId("Erroneous", JCErroneous.class);
+ public JCErroneous Erroneous() {
+ return invoke(Erroneous);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCErroneous> ErroneousWithErrs = MethodId("Erroneous", JCErroneous.class, List.class);
+ public JCErroneous Erroneous(List<? extends JCTree> errs) {
+ return invoke(ErroneousWithErrs, errs);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<LetExpr> LetExpr = MethodId("LetExpr", LetExpr.class, List.class, JCTree.class);
+ public LetExpr LetExpr(List<JCVariableDecl> defs, JCTree expr) {
+ return invoke(LetExpr, defs, expr);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCClassDecl> AnonymousClassDef = MethodId("AnonymousClassDef");
+ public JCClassDecl AnonymousClassDef(JCModifiers mods, List<JCTree> defs) {
+ return invoke(AnonymousClassDef, mods, defs);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<LetExpr> LetExprSingle = MethodId("LetExpr", LetExpr.class, JCVariableDecl.class, JCTree.class);
+ public LetExpr LetExpr(JCVariableDecl def, JCTree expr) {
+ return invoke(LetExprSingle, def, expr);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCIdent> IdentVarDecl = MethodId("Ident", JCIdent.class, JCVariableDecl.class);
+ public JCExpression Ident(JCVariableDecl param) {
+ return invoke(IdentVarDecl, param);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<List<JCExpression>> Idents = MethodId("Idents");
+ public List<JCExpression> Idents(List<JCVariableDecl> params) {
+ return invoke(Idents, params);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCMethodInvocation> App2 = MethodId("App", JCMethodInvocation.class, JCExpression.class, List.class);
+ public JCMethodInvocation App(JCExpression meth, List<JCExpression> args) {
+ return invoke(App2, meth, args);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCMethodInvocation> App1 = MethodId("App", JCMethodInvocation.class, JCExpression.class);
+ public JCMethodInvocation App(JCExpression meth) {
+ return invoke(App1, meth);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<List<JCAnnotation>> Annotations = MethodId("Annotations");
+ public List<JCAnnotation> Annotations(List<Attribute.Compound> attributes) {
+ return invoke(Annotations, attributes);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCLiteral> LiteralWithValue = MethodId("Literal", JCLiteral.class, Object.class);
+ public JCLiteral Literal(Object value) {
+ return invoke(LiteralWithValue, value);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCAnnotation> AnnotationWithAttributeOnly = MethodId("Annotation", JCAnnotation.class, Attribute.class);
+ public JCAnnotation Annotation(Attribute a) {
+ return invoke(AnnotationWithAttributeOnly, a);
+ }
+
+ //javac versions: 8
+ private static final MethodId<JCAnnotation> TypeAnnotationWithAttributeOnly = MethodId("TypeAnnotation", JCAnnotation.class, Attribute.class);
+ public JCAnnotation TypeAnnotation(Attribute a) {
+ return invoke(TypeAnnotationWithAttributeOnly, a);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCStatement> Call = MethodId("Call");
+ public JCStatement Call(JCExpression apply) {
+ return invoke(Call, apply);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCExpression> Type = MethodId("Type");
+ public JCExpression Type(Type type) {
+ return invoke(Type, type);
+ }
+} \ No newline at end of file
diff --git a/src/utils/lombok/javac/TreeMirrorMaker.java b/src/utils/lombok/javac/TreeMirrorMaker.java
index 30915572..23ec2406 100644
--- a/src/utils/lombok/javac/TreeMirrorMaker.java
+++ b/src/utils/lombok/javac/TreeMirrorMaker.java
@@ -31,7 +31,6 @@ import com.sun.source.tree.VariableTree;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.TreeCopier;
-import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.List;
/**
@@ -47,8 +46,8 @@ import com.sun.tools.javac.util.List;
public class TreeMirrorMaker extends TreeCopier<Void> {
private final IdentityHashMap<JCTree, JCTree> originalToCopy = new IdentityHashMap<JCTree, JCTree>();
- public TreeMirrorMaker(TreeMaker maker) {
- super(maker);
+ public TreeMirrorMaker(JavacTreeMaker maker) {
+ super(maker.getUnderlyingTreeMaker());
}
@Override public <T extends JCTree> T copy(T original) {
diff --git a/src/utils/lombok/javac/java6/CommentCollectingParser.java b/src/utils/lombok/javac/java6/CommentCollectingParser.java
index 94a85e55..30192b06 100644
--- a/src/utils/lombok/javac/java6/CommentCollectingParser.java
+++ b/src/utils/lombok/javac/java6/CommentCollectingParser.java
@@ -1,3 +1,24 @@
+/*
+ * 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.java6;
import java.util.Map;
diff --git a/src/utils/lombok/javac/java6/CommentCollectingParserFactory.java b/src/utils/lombok/javac/java6/CommentCollectingParserFactory.java
index 7e34b723..b250b898 100644
--- a/src/utils/lombok/javac/java6/CommentCollectingParserFactory.java
+++ b/src/utils/lombok/javac/java6/CommentCollectingParserFactory.java
@@ -1,3 +1,24 @@
+/*
+ * 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.java6;
import java.lang.reflect.Field;
diff --git a/src/utils/lombok/javac/java6/CommentCollectingScanner.java b/src/utils/lombok/javac/java6/CommentCollectingScanner.java
index b584ec16..df383b93 100644
--- a/src/utils/lombok/javac/java6/CommentCollectingScanner.java
+++ b/src/utils/lombok/javac/java6/CommentCollectingScanner.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 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
@@ -27,11 +27,12 @@ import lombok.javac.CommentInfo;
import lombok.javac.CommentInfo.EndConnection;
import lombok.javac.CommentInfo.StartConnection;
+import com.sun.tools.javac.parser.Scanner;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
-public class CommentCollectingScanner extends DocCommentScanner {
- private final ListBuffer<CommentInfo> comments = ListBuffer.lb();
+public class CommentCollectingScanner extends Scanner {
+ private final ListBuffer<CommentInfo> comments = new ListBuffer<CommentInfo>();
private int endComment = 0;
public CommentCollectingScanner(CommentCollectingScannerFactory factory, CharBuffer charBuffer) {
diff --git a/src/utils/lombok/javac/java6/CommentCollectingScannerFactory.java b/src/utils/lombok/javac/java6/CommentCollectingScannerFactory.java
index f3d6bd72..b7d8ed13 100644
--- a/src/utils/lombok/javac/java6/CommentCollectingScannerFactory.java
+++ b/src/utils/lombok/javac/java6/CommentCollectingScannerFactory.java
@@ -26,7 +26,7 @@ import java.nio.CharBuffer;
import com.sun.tools.javac.parser.Scanner;
import com.sun.tools.javac.util.Context;
-public class CommentCollectingScannerFactory extends DocCommentScanner.Factory {
+public class CommentCollectingScannerFactory extends Scanner.Factory {
@SuppressWarnings("all")
public static void preRegister(final Context context) {
diff --git a/src/utils/lombok/javac/java6/DocCommentScanner.java b/src/utils/lombok/javac/java6/DocCommentScanner.java
deleted file mode 100644
index ff3eadd4..00000000
--- a/src/utils/lombok/javac/java6/DocCommentScanner.java
+++ /dev/null
@@ -1,461 +0,0 @@
-package lombok.javac.java6;
-
-/*
- * Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-import static com.sun.tools.javac.util.LayoutCharacters.*;
-
-import java.nio.CharBuffer;
-
-import com.sun.tools.javac.parser.Scanner;
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.Position;
-
-/** An extension to the base lexical analyzer that captures
- * and processes the contents of doc comments. It does so by
- * translating Unicode escape sequences and by stripping the
- * leading whitespace and starts from each line of the comment.
- *
- * <p><b>This is NOT part of any API supported by Sun Microsystems. If
- * you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public class DocCommentScanner extends Scanner {
-
- /** A factory for creating scanners. */
- public static class Factory extends Scanner.Factory {
-
- @SuppressWarnings({"unchecked", "all"})
- public static void preRegister(final Context context) {
- context.put(scannerFactoryKey, new Context.Factory() {
- public Object make() {
- return new Factory(context);
- }
-
- public Object make(Context c) {
- return new Factory(c);
- }
- });
- }
-
- /** Create a new scanner factory. */
- protected Factory(Context context) {
- super(context);
- }
-
- @Override
- public Scanner newScanner(CharSequence input) {
- if (input instanceof CharBuffer) {
- return new DocCommentScanner(this, (CharBuffer)input);
- } else {
- char[] array = input.toString().toCharArray();
- return newScanner(array, array.length);
- }
- }
-
- @Override
- public Scanner newScanner(char[] input, int inputLength) {
- return new DocCommentScanner(this, input, inputLength);
- }
- }
-
-
- /** Create a scanner from the input buffer. buffer must implement
- * array() and compact(), and remaining() must be less than limit().
- */
- protected DocCommentScanner(Factory fac, CharBuffer buffer) {
- super(fac, buffer);
- }
-
- /** Create a scanner from the input array. The array must have at
- * least a single character of extra space.
- */
- protected DocCommentScanner(Factory fac, char[] input, int inputLength) {
- super(fac, input, inputLength);
- }
-
- /** Starting position of the comment in original source
- */
- private int pos;
-
- /** The comment input buffer, index of next chacter to be read,
- * index of one past last character in buffer.
- */
- private char[] buf;
- private int bp;
- private int buflen;
-
- /** The current character.
- */
- private char ch;
-
- /** The column number position of the current character.
- */
- private int col;
-
- /** The buffer index of the last converted Unicode character
- */
- private int unicodeConversionBp = 0;
-
- /**
- * Buffer for doc comment.
- */
- private char[] docCommentBuffer = new char[1024];
-
- /**
- * Number of characters in doc comment buffer.
- */
- private int docCommentCount;
-
- /**
- * Translated and stripped contents of doc comment
- */
- private String docComment = null;
-
-
- /** Unconditionally expand the comment buffer.
- */
- private void expandCommentBuffer() {
- char[] newBuffer = new char[docCommentBuffer.length * 2];
- System.arraycopy(docCommentBuffer, 0, newBuffer,
- 0, docCommentBuffer.length);
- docCommentBuffer = newBuffer;
- }
-
- /** Convert an ASCII digit from its base (8, 10, or 16)
- * to its value.
- */
- private int digit(int base) {
- char c = ch;
- int result = Character.digit(c, base);
- if (result >= 0 && c > 0x7f) {
- ch = "0123456789abcdef".charAt(result);
- }
- return result;
- }
-
- /** Convert Unicode escape; bp points to initial '\' character
- * (Spec 3.3).
- */
- private void convertUnicode() {
- if (ch == '\\' && unicodeConversionBp != bp) {
- bp++; ch = buf[bp]; col++;
- if (ch == 'u') {
- do {
- bp++; ch = buf[bp]; col++;
- } while (ch == 'u');
- int limit = bp + 3;
- if (limit < buflen) {
- int d = digit(16);
- int code = d;
- while (bp < limit && d >= 0) {
- bp++; ch = buf[bp]; col++;
- d = digit(16);
- code = (code << 4) + d;
- }
- if (d >= 0) {
- ch = (char)code;
- unicodeConversionBp = bp;
- return;
- }
- }
- // "illegal.Unicode.esc", reported by base scanner
- } else {
- bp--;
- ch = '\\';
- col--;
- }
- }
- }
-
-
- /** Read next character.
- */
- private void scanChar() {
- bp++;
- ch = buf[bp];
- switch (ch) {
- case '\r': // return
- col = 0;
- break;
- case '\n': // newline
- if (bp == 0 || buf[bp-1] != '\r') {
- col = 0;
- }
- break;
- case '\t': // tab
- col = (col / TabInc * TabInc) + TabInc;
- break;
- case '\\': // possible Unicode
- col++;
- convertUnicode();
- break;
- default:
- col++;
- break;
- }
- }
-
- /**
- * Read next character in doc comment, skipping over double '\' characters.
- * If a double '\' is skipped, put in the buffer and update buffer count.
- */
- private void scanDocCommentChar() {
- scanChar();
- if (ch == '\\') {
- if (buf[bp+1] == '\\' && unicodeConversionBp != bp) {
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = ch;
- bp++; col++;
- } else {
- convertUnicode();
- }
- }
- }
-
- /* Reset doc comment before reading each new token
- */
- public void nextToken() {
- docComment = null;
- super.nextToken();
- }
-
- /**
- * Returns the documentation string of the current token.
- */
- public String docComment() {
- return docComment;
- }
-
- /**
- * Process a doc comment and make the string content available.
- * Strips leading whitespace and stars.
- */
- @SuppressWarnings("fallthrough")
- protected void processComment(CommentStyle style) {
- if (style != CommentStyle.JAVADOC) {
- return;
- }
-
- pos = pos();
- buf = getRawCharacters(pos, endPos());
- buflen = buf.length;
- bp = 0;
- col = 0;
-
- docCommentCount = 0;
-
- boolean firstLine = true;
-
- // Skip over first slash
- scanDocCommentChar();
- // Skip over first star
- scanDocCommentChar();
-
- // consume any number of stars
- while (bp < buflen && ch == '*') {
- scanDocCommentChar();
- }
- // is the comment in the form /**/, /***/, /****/, etc. ?
- if (bp < buflen && ch == '/') {
- docComment = "";
- return;
- }
-
- // skip a newline on the first line of the comment.
- if (bp < buflen) {
- if (ch == LF) {
- scanDocCommentChar();
- firstLine = false;
- } else if (ch == CR) {
- scanDocCommentChar();
- if (ch == LF) {
- scanDocCommentChar();
- firstLine = false;
- }
- }
- }
-
- outerLoop:
-
- // The outerLoop processes the doc comment, looping once
- // for each line. For each line, it first strips off
- // whitespace, then it consumes any stars, then it
- // puts the rest of the line into our buffer.
- while (bp < buflen) {
-
- // The wsLoop consumes whitespace from the beginning
- // of each line.
- wsLoop:
-
- while (bp < buflen) {
- switch(ch) {
- case ' ':
- scanDocCommentChar();
- break;
- case '\t':
- col = ((col - 1) / TabInc * TabInc) + TabInc;
- scanDocCommentChar();
- break;
- case FF:
- col = 0;
- scanDocCommentChar();
- break;
-// Treat newline at beginning of line (blank line, no star)
-// as comment text. Old Javadoc compatibility requires this.
-/*---------------------------------*
- case CR: // (Spec 3.4)
- scanDocCommentChar();
- if (ch == LF) {
- col = 0;
- scanDocCommentChar();
- }
- break;
- case LF: // (Spec 3.4)
- scanDocCommentChar();
- break;
-*---------------------------------*/
- default:
- // we've seen something that isn't whitespace;
- // jump out.
- break wsLoop;
- }
- }
-
- // Are there stars here? If so, consume them all
- // and check for the end of comment.
- if (ch == '*') {
- // skip all of the stars
- do {
- scanDocCommentChar();
- } while (ch == '*');
-
- // check for the closing slash.
- if (ch == '/') {
- // We're done with the doc comment
- // scanChar() and breakout.
- break outerLoop;
- }
- } else if (! firstLine) {
- //The current line does not begin with a '*' so we will indent it.
- for (int i = 1; i < col; i++) {
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = ' ';
- }
- }
-
- // The textLoop processes the rest of the characters
- // on the line, adding them to our buffer.
- textLoop:
- while (bp < buflen) {
- switch (ch) {
- case '*':
- // Is this just a star? Or is this the
- // end of a comment?
- scanDocCommentChar();
- if (ch == '/') {
- // This is the end of the comment,
- // set ch and return our buffer.
- break outerLoop;
- }
- // This is just an ordinary star. Add it to
- // the buffer.
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = '*';
- break;
- case ' ':
- case '\t':
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = ch;
- scanDocCommentChar();
- break;
- case FF:
- scanDocCommentChar();
- break textLoop; // treat as end of line
- case CR: // (Spec 3.4)
- scanDocCommentChar();
- if (ch != LF) {
- // Canonicalize CR-only line terminator to LF
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = (char)LF;
- break textLoop;
- }
- /* fall through to LF case */
- case LF: // (Spec 3.4)
- // We've seen a newline. Add it to our
- // buffer and break out of this loop,
- // starting fresh on a new line.
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = ch;
- scanDocCommentChar();
- break textLoop;
- default:
- // Add the character to our buffer.
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = ch;
- scanDocCommentChar();
- }
- } // end textLoop
- firstLine = false;
- } // end outerLoop
-
- if (docCommentCount > 0) {
- int i = docCommentCount - 1;
- trailLoop:
- while (i > -1) {
- switch (docCommentBuffer[i]) {
- case '*':
- i--;
- break;
- default:
- break trailLoop;
- }
- }
- docCommentCount = i + 1;
-
- // Store the text of the doc comment
- docComment = new String(docCommentBuffer, 0 , docCommentCount);
- } else {
- docComment = "";
- }
- }
-
- /** Build a map for translating between line numbers and
- * positions in the input.
- *
- * @return a LineMap */
- public Position.LineMap getLineMap() {
- char[] buf = getRawCharacters();
- return Position.makeLineMap(buf, buf.length, true);
- }
-}
diff --git a/src/utils/lombok/javac/java7/CommentCollectingParser.java b/src/utils/lombok/javac/java7/CommentCollectingParser.java
index 82f19c42..0e8a4ef6 100644
--- a/src/utils/lombok/javac/java7/CommentCollectingParser.java
+++ b/src/utils/lombok/javac/java7/CommentCollectingParser.java
@@ -1,3 +1,24 @@
+/*
+ * 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.java7;
import java.util.List;
diff --git a/src/utils/lombok/javac/java7/CommentCollectingParserFactory.java b/src/utils/lombok/javac/java7/CommentCollectingParserFactory.java
index e9575c14..ed8279df 100644
--- a/src/utils/lombok/javac/java7/CommentCollectingParserFactory.java
+++ b/src/utils/lombok/javac/java7/CommentCollectingParserFactory.java
@@ -1,3 +1,24 @@
+/*
+ * 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.java7;
import java.lang.reflect.Field;
diff --git a/src/utils/lombok/javac/java7/CommentCollectingScanner.java b/src/utils/lombok/javac/java7/CommentCollectingScanner.java
index 6ebd3ac1..3f76f910 100644
--- a/src/utils/lombok/javac/java7/CommentCollectingScanner.java
+++ b/src/utils/lombok/javac/java7/CommentCollectingScanner.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 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
@@ -27,12 +27,12 @@ import lombok.javac.CommentInfo;
import lombok.javac.CommentInfo.EndConnection;
import lombok.javac.CommentInfo.StartConnection;
+import com.sun.tools.javac.parser.Scanner;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
-import com.sun.tools.javac.parser.DocCommentScanner;
-public class CommentCollectingScanner extends DocCommentScanner {
- private final ListBuffer<CommentInfo> comments = ListBuffer.lb();
+public class CommentCollectingScanner extends Scanner {
+ private final ListBuffer<CommentInfo> comments = new ListBuffer<CommentInfo>();
private int endComment = 0;
public CommentCollectingScanner(CommentCollectingScannerFactory factory, CharBuffer charBuffer) {
diff --git a/src/utils/lombok/javac/java8/CommentCollectingParser.java b/src/utils/lombok/javac/java8/CommentCollectingParser.java
new file mode 100644
index 00000000..e305e44f
--- /dev/null
+++ b/src/utils/lombok/javac/java8/CommentCollectingParser.java
@@ -0,0 +1,53 @@
+/*
+ * 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.java8;
+
+import java.util.List;
+import java.util.Map;
+
+import lombok.javac.CommentInfo;
+
+import com.sun.tools.javac.parser.JavacParser;
+import com.sun.tools.javac.parser.Lexer;
+import com.sun.tools.javac.parser.ParserFactory;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+
+class CommentCollectingParser extends JavacParser {
+ private final Map<JCCompilationUnit, List<CommentInfo>> commentsMap;
+ private final Lexer lexer;
+
+ protected CommentCollectingParser(ParserFactory fac, Lexer S,
+ boolean keepDocComments, boolean keepLineMap, boolean keepEndPositions, Map<JCCompilationUnit, List<CommentInfo>> commentsMap) {
+ super(fac, S, keepDocComments, keepLineMap, keepEndPositions);
+ lexer = S;
+ this.commentsMap = commentsMap;
+ }
+
+ public JCCompilationUnit parseCompilationUnit() {
+ JCCompilationUnit result = super.parseCompilationUnit();
+ if (lexer instanceof CommentCollectingScanner) {
+ List<CommentInfo> comments = ((CommentCollectingScanner)lexer).getComments();
+ commentsMap.put(result, comments);
+ }
+ return result;
+ }
+} \ No newline at end of file
diff --git a/src/utils/lombok/javac/java8/CommentCollectingParserFactory.java b/src/utils/lombok/javac/java8/CommentCollectingParserFactory.java
new file mode 100644
index 00000000..6b5f9198
--- /dev/null
+++ b/src/utils/lombok/javac/java8/CommentCollectingParserFactory.java
@@ -0,0 +1,73 @@
+/*
+ * 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.java8;
+
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.Map;
+
+import lombok.javac.CommentInfo;
+
+import com.sun.tools.javac.main.JavaCompiler;
+import com.sun.tools.javac.parser.JavacParser;
+import com.sun.tools.javac.parser.Lexer;
+import com.sun.tools.javac.parser.ParserFactory;
+import com.sun.tools.javac.parser.ScannerFactory;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.util.Context;
+
+public class CommentCollectingParserFactory extends ParserFactory {
+ private final Map<JCCompilationUnit, List<CommentInfo>> commentsMap;
+ private final Context context;
+
+ static Context.Key<ParserFactory> key() {
+ return parserFactoryKey;
+ }
+
+ protected CommentCollectingParserFactory(Context context, Map<JCCompilationUnit, List<CommentInfo>> commentsMap) {
+ super(context);
+ this.context = context;
+ this.commentsMap = commentsMap;
+ }
+
+ public JavacParser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap) {
+ ScannerFactory scannerFactory = ScannerFactory.instance(context);
+ Lexer lexer = scannerFactory.newScanner(input, true);
+ Object x = new CommentCollectingParser(this, lexer, true, keepLineMap, keepEndPos, commentsMap);
+ return (JavacParser) x;
+ // CCP is based on a stub which extends nothing, but at runtime the stub is replaced with either
+ //javac6's EndPosParser which extends Parser, or javac8's JavacParser which implements Parser.
+ //Either way this will work out.
+ }
+
+ public static void setInCompiler(JavaCompiler compiler, Context context, Map<JCCompilationUnit, List<CommentInfo>> commentsMap) {
+ context.put(CommentCollectingParserFactory.key(), (ParserFactory)null);
+ Field field;
+ try {
+ field = JavaCompiler.class.getDeclaredField("parserFactory");
+ field.setAccessible(true);
+ field.set(compiler, new CommentCollectingParserFactory(context, commentsMap));
+ } catch (Exception e) {
+ throw new IllegalStateException("Could not set comment sensitive parser in the compiler", e);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/utils/lombok/javac/java8/CommentCollectingScanner.java b/src/utils/lombok/javac/java8/CommentCollectingScanner.java
new file mode 100644
index 00000000..b59a9390
--- /dev/null
+++ b/src/utils/lombok/javac/java8/CommentCollectingScanner.java
@@ -0,0 +1,42 @@
+/*
+ * 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.java8;
+
+import lombok.javac.CommentInfo;
+
+import com.sun.tools.javac.parser.Scanner;
+import com.sun.tools.javac.parser.ScannerFactory;
+import com.sun.tools.javac.util.List;
+
+public class CommentCollectingScanner extends Scanner {
+
+ private CommentCollectingTokenizer tokenizer;
+
+ public CommentCollectingScanner(ScannerFactory fac, CommentCollectingTokenizer tokenizer) {
+ super(fac, tokenizer);
+ this.tokenizer = tokenizer;
+ }
+
+ public List<CommentInfo> getComments() {
+ return tokenizer.getComments();
+ }
+} \ No newline at end of file
diff --git a/src/utils/lombok/javac/java8/CommentCollectingScannerFactory.java b/src/utils/lombok/javac/java8/CommentCollectingScannerFactory.java
new file mode 100644
index 00000000..fa79ff67
--- /dev/null
+++ b/src/utils/lombok/javac/java8/CommentCollectingScannerFactory.java
@@ -0,0 +1,89 @@
+/*
+ * 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.java8;
+
+import java.nio.CharBuffer;
+
+import com.sun.tools.javac.parser.Scanner;
+import com.sun.tools.javac.parser.ScannerFactory;
+import com.sun.tools.javac.util.Context;
+
+public class CommentCollectingScannerFactory extends ScannerFactory {
+
+ @SuppressWarnings("all")
+ public static void preRegister(final Context context) {
+ if (context.get(scannerFactoryKey) == null) {
+ // Careful! There is voodoo magic here!
+ //
+ // Context.Factory is parameterized. make() is for javac6 and below; make(Context) is for javac7 and up.
+ // this anonymous inner class definition is intentionally 'raw' - the return type of both 'make' methods is 'T',
+ // which means the compiler will only generate the correct "real" override method (with returntype Object, which is
+ // the lower bound for T, as a synthetic accessor for the make with returntype ScannerFactory) for that make method which
+ // is actually on the classpath (either make() for javac6-, or make(Context) for javac7+).
+ //
+ // We normally solve this issue via src/stubs, with BOTH make methods listed, but for some reason the presence of a stubbed out
+ // Context (or even a complete copy, it doesn't matter) results in a really strange eclipse bug, where any mention of any kind
+ // of com.sun.tools.javac.tree.TreeMaker in a source file disables ALL usage of 'go to declaration' and auto-complete in the entire
+ // source file.
+ //
+ // Thus, in short:
+ // * Do NOT parameterize the anonymous inner class literal.
+ // * Leave the return types as 'j.l.Object'.
+ // * Leave both make methods intact; deleting one has no effect on javac6- / javac7+, but breaks the other. Hard to test for.
+ // * Do not stub com.sun.tools.javac.util.Context or any of its inner types, like Factory.
+ @SuppressWarnings("all")
+ class MyFactory implements Context.Factory {
+ // This overrides the javac6- version of make.
+ public Object make() {
+ return new CommentCollectingScannerFactory(context);
+ }
+
+ // This overrides the javac7+ version.
+ public Object make(Context c) {
+ return new CommentCollectingScannerFactory(c);
+ }
+ }
+ @SuppressWarnings("unchecked") Context.Factory<ScannerFactory> factory = new MyFactory();
+ context.put(scannerFactoryKey, factory);
+ }
+ }
+
+ /** Create a new scanner factory. */
+ protected CommentCollectingScannerFactory(Context context) {
+ super(context);
+ }
+
+ @Override
+ public Scanner newScanner(CharSequence input, boolean keepDocComments) {
+ if (input instanceof CharBuffer) {
+ CharBuffer buf = (CharBuffer) input;
+ return new CommentCollectingScanner(this, new CommentCollectingTokenizer(this, buf));
+ }
+ char[] array = input.toString().toCharArray();
+ return newScanner(array, array.length, keepDocComments);
+ }
+
+ @Override
+ public Scanner newScanner(char[] input, int inputLength, boolean keepDocComments) {
+ return new CommentCollectingScanner(this, new CommentCollectingTokenizer(this, input, inputLength));
+ }
+}
diff --git a/src/utils/lombok/javac/java8/CommentCollectingTokenizer.java b/src/utils/lombok/javac/java8/CommentCollectingTokenizer.java
new file mode 100644
index 00000000..1834fb00
--- /dev/null
+++ b/src/utils/lombok/javac/java8/CommentCollectingTokenizer.java
@@ -0,0 +1,129 @@
+/*
+ * 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.java8;
+
+import java.nio.CharBuffer;
+
+import lombok.javac.CommentInfo;
+import lombok.javac.CommentInfo.EndConnection;
+import lombok.javac.CommentInfo.StartConnection;
+
+import com.sun.tools.javac.parser.JavaTokenizer;
+import com.sun.tools.javac.parser.ScannerFactory;
+import com.sun.tools.javac.parser.Tokens.Comment;
+import com.sun.tools.javac.parser.Tokens.Token;
+import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
+import com.sun.tools.javac.parser.UnicodeReader;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+
+class CommentCollectingTokenizer extends JavaTokenizer {
+ private int prevEndPosition = 0;
+ private final ListBuffer<CommentInfo> comments = new ListBuffer<CommentInfo>();
+ private int endComment = 0;
+
+ CommentCollectingTokenizer(ScannerFactory fac, char[] buf, int inputLength) {
+ super(fac, new PositionUnicodeReader(fac, buf, inputLength));
+ }
+
+ CommentCollectingTokenizer(ScannerFactory fac, CharBuffer buf) {
+ super(fac, new PositionUnicodeReader(fac, buf));
+ }
+
+ @Override public Token readToken() {
+ Token token = super.readToken();
+ prevEndPosition = ((PositionUnicodeReader)reader).pos();
+ return token;
+ }
+
+ @Override
+ protected Comment processComment(int pos, int endPos, CommentStyle style) {
+ int prevEndPos = Math.max(prevEndPosition, endComment);
+ endComment = endPos;
+ String content = new String(reader.getRawCharacters(pos, endPos));
+ StartConnection start = determineStartConnection(prevEndPos, pos);
+ EndConnection end = determineEndConnection(endPos);
+
+ CommentInfo comment = new CommentInfo(prevEndPos, pos, endPos, content, start, end);
+ comments.append(comment);
+
+ return super.processComment(pos, endPos, style);
+ }
+
+ private EndConnection determineEndConnection(int pos) {
+ boolean first = true;
+ for (int i = pos;; i++) {
+ char c;
+ try {
+ c = reader.getRawCharacters(i, i + 1)[0];
+ } catch (IndexOutOfBoundsException e) {
+ c = '\n';
+ }
+ if (isNewLine(c)) {
+ return EndConnection.ON_NEXT_LINE;
+ }
+ if (Character.isWhitespace(c)) {
+ first = false;
+ continue;
+ }
+ return first ? EndConnection.DIRECT_AFTER_COMMENT : EndConnection.AFTER_COMMENT;
+ }
+ }
+
+ private StartConnection determineStartConnection(int from, int to) {
+ if (from == to) {
+ return StartConnection.DIRECT_AFTER_PREVIOUS;
+ }
+ char[] between = reader.getRawCharacters(from, to);
+ if (isNewLine(between[between.length - 1])) {
+ return StartConnection.START_OF_LINE;
+ }
+ for (char c : between) {
+ if (isNewLine(c)) {
+ return StartConnection.ON_NEXT_LINE;
+ }
+ }
+ return StartConnection.AFTER_PREVIOUS;
+ }
+
+ private boolean isNewLine(char c) {
+ return c == '\n' || c == '\r';
+ }
+
+ public List<CommentInfo> getComments() {
+ return comments.toList();
+ }
+
+ static class PositionUnicodeReader extends UnicodeReader {
+ protected PositionUnicodeReader(ScannerFactory sf, char[] input, int inputLength) {
+ super(sf, input, inputLength);
+ }
+
+ public PositionUnicodeReader(ScannerFactory sf, CharBuffer buffer) {
+ super(sf, buffer);
+ }
+
+ int pos() {
+ return bp;
+ }
+ }
+} \ No newline at end of file