Merge branch 'master' of github.com:rzwitserloot/lombok

Conflicts:
	src/delombok/lombok/delombok/DelombokApp.java
This commit is contained in:
Roel Spilker committed 2013-11-19 21:02:59 +01:00
commit 78b2d6919e
168 files changed
+3612 -1627

No files matched your search

+32 -4
View File
@@ -332,7 +332,7 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
</copy>
</target>
<target name="setupJava6TestEnvironment" description="Sets up the test so that 'ant test' will test against OpenJDK6.">
<target name="setupJavaOpenJDK6TestEnvironment" description="Sets up the test so that 'ant test' will test against OpenJDK6.">
<mkdir dir="lib/openJDK6Environment" />
<get src="http://projectlombok.org/ivyrepo/langtools/javac-1.6.0.18.jar" dest="lib/openJDK6Environment/javac6.jar" verbose="true" usetimestamp="true" />
<get src="http://projectlombok.org/ivyrepo/langtools/rt-openjdk6.jar" dest="lib/openJDK6Environment/rt-openjdk6.jar" verbose="true" usetimestamp="true" />
@@ -345,7 +345,7 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
<antcall target="-createEclipseLaunchForTestEnvironmentIfEclipseProject" />
</target>
<target name="setupJava7TestEnvironment" description="Sets up the test so that 'ant test' will test against OpenJDK7.">
<target name="setupJavaOpenJDK7TestEnvironment" description="Sets up the test so that 'ant test' will test against OpenJDK7.">
<mkdir dir="lib/openJDK7Environment" />
<get src="http://projectlombok.org/ivyrepo/langtools/javac-1.7.0.jar" dest="lib/openJDK7Environment/javac7.jar" verbose="true" usetimestamp="true" />
<get src="http://projectlombok.org/ivyrepo/langtools/rt-openjdk7.jar" dest="lib/openJDK7Environment/rt-openjdk7.jar" verbose="true" usetimestamp="true" />
@@ -357,6 +357,32 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
<echo>Tests will now run against OpenJDK7</echo>
<antcall target="-createEclipseLaunchForTestEnvironmentIfEclipseProject" />
</target>
<target name="setupJavaOracle7TestEnvironment" description="Sets up the test so that 'ant test' will test against OpenJDK7.">
<mkdir dir="lib/oracleJDK7Environment" />
<get src="http://projectlombok.org/ivyrepo/langtools/oracle-jdk7-tools.jar" dest="lib/oracleJDK7Environment/tools.jar" verbose="true" usetimestamp="true" />
<get src="http://projectlombok.org/ivyrepo/langtools/oracle-jdk7-rt.jar" dest="lib/oracleJDK7Environment/rt.jar" verbose="true" usetimestamp="true" />
<propertyfile file="testenvironment.properties">
<entry key="test.location.javac" value="lib/oracleJDK7Environment/tools.jar" />
<entry key="test.location.bootclasspath" value="lib/oracleJDK7Environment/rt.jar" />
<entry key="test.location.name" value="OracleJDK7" />
</propertyfile>
<echo>Tests will now run against Oracle JDK7</echo>
<antcall target="-createEclipseLaunchForTestEnvironmentIfEclipseProject" />
</target>
<target name="setupJavaOracle8TestEnvironment" description="Sets up the test so that 'ant test' will test against OpenJDK8.">
<mkdir dir="lib/oracleJDK8Environment" />
<get src="http://projectlombok.org/ivyrepo/langtools/oracle-jdk8-tools.jar" dest="lib/oracleJDK8Environment/tools.jar" verbose="true" usetimestamp="true" />
<get src="http://projectlombok.org/ivyrepo/langtools/oracle-jdk8-rt.jar" dest="lib/oracleJDK8Environment/rt.jar" verbose="true" usetimestamp="true" />
<propertyfile file="testenvironment.properties">
<entry key="test.location.javac" value="lib/oracleJDK8Environment/tools.jar" />
<entry key="test.location.bootclasspath" value="lib/oracleJDK8Environment/rt.jar" />
<entry key="test.location.name" value="OracleJDK8" />
</propertyfile>
<echo>Tests will now run against Oracle JDK8</echo>
<antcall target="-createEclipseLaunchForTestEnvironmentIfEclipseProject" />
</target>
<target name="-failIfNoTestEnvironmentProperties" unless="test.location.javac">
<fail>ERROR: No test environment set up.
@@ -366,8 +392,10 @@ Eventually, this environment concept will be extended to also include an ecj and
You can let this ant script set them up for you:
* ant setupJava6TestEnvironment
* ant setupJava7TestEnvironment
* ant setupJavaOpenJDK6TestEnvironment
* ant setupJavaOpenJDK7TestEnvironment
* ant setupJavaOracle7TestEnvironment
* ant setupJavaOracle8TestEnvironment
These will set up test environments based on OpenJDK6 and OpenJDK7, and download all required files automatically. This will be a relatively large download. You can switch by running this command again; the downloads are cached so switching is fast.
@@ -0,0 +1,12 @@
<ivy-module version="2.0">
<info organisation="projectlombok.org" module="spi" revision="0.2.7" publication="20130910135600">
<license name="Apache License v2.0" url="http://www.apache.org/licenses/LICENSE-2.0" />
<description homepage="http://code.google.com/p/spi/" />
</info>
<configurations>
<conf name="build" />
</configurations>
<publications>
<artifact conf="build" url="http://projectlombok.org/ivyrepo/tools/spi-0.2.7.jar" />
</publications>
</ivy-module>
+1 -1
View File
@@ -24,7 +24,7 @@
<dependency org="com.googlecode.jarjar" name="jarjar" rev="1.1" conf="build->default" />
<dependency org="org.apache.ant" name="ant" rev="1.8.1" conf="build->default; contrib->sources" />
<dependency org="projectlombok.org" name="spi" rev="0.2.4" conf="build" />
<dependency org="projectlombok.org" name="spi" rev="0.2.7" conf="build" />
<dependency org="projectlombok.org" name="ant-googlecode" rev="0.0.2" conf="build" />
<dependency org="com.jcraft" name="jsch" rev="0.1.42" conf="build->default" />
<dependency org="projectlombok.org" name="jsch-ant-fixed" rev="0.1.42" conf="build" />
+11
View File
@@ -1,6 +1,17 @@
Lombok Changelog
----------------
### v1.12.3 "Edgy Guinea Pig"
* BUG: v1.12.2's delombok turns all operator+assignments into just assignment. Fixed. [Issue #598](https://code.google.com/p/projectlombok/issues/detail?id=598)
### v1.12.2 (October 10th, 2013)
* PLATFORM: Initial JDK8 support, without affecting existing support for JDK6 and 7. [Issue #451](https://code.google.com/p/projectlombok/issues/detail?id=451). While lombok will now work on JDK8 / javac8, and netbeans 7.4 and up, lombok does not (yet) support new language features introduced with java8, such as lambda expressions. Support for these features will be added in a future version.
* PLATFORM: Running javac on IBM J9 VM would cause NullPointerExceptions when compiling with lombok. These issues should be fixed. [Issue #554](https://code.google.com/p/projectlombok/issues/detail?id=554).
* CHANGE: [JDK8-related] The canonical way to write onMethod / onParameter / onConstructor annotation now uses a double underscore instead of a single underscore, so, now, the proper way to use this feature is `@RequiredArgsConstructor(onConstructor=@__(@Inject))`. The old way (single underscore) still works, but generates warnings on javac 8.
* BUGFIX: Using `@NonNull` on an abstract method used to cause exceptions during compilation. [Issue #559](https://code.google.com/p/projectlombok/issues/detail?id=559).
* BUGFIX: Using `@NonNull` on methods that also have `@SneakyThrows` or `@Synchronized` caused arbitrary behaviour. [Issue #588](https://code.google.com/p/projectlombok/issues/detail?id=588).
* GERMANY: Major version bumped from 0 to 1, because allegedly this is important. Rest assured, this change is nevertheless backwards compatible.
### v0.12.0 "Angry Butterfly" (July 16th, 2013)
* FEATURE: javadoc on fields will now be copied to generated getters / setters / withers. There are ways to specify separate javadoc for the field, the setter, and the getter, and `@param` and `@return` are handled appropriately. Addresses feature request [Issue #59](https://code.google.com/p/projectlombok/issues/detail?id=59). [@Getter and @Setter documentation](http://projectlombok.org/features/GetterSetter.html). [@Wither documentation](http://projectlombok.org/features/experimental/Wither.html).
* CHANGE: The desugaring of @Getter(lazy=true) is now less object creation intensive. Documentation has been updated to reflect what the new desugaring looks like. [@Getter(lazy=true) documentation](http://projectlombok.org/features/GetterLazy.html).
@@ -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();
+4 -3
View File
@@ -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
@@ -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"));
@@ -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();
}
}
@@ -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);
}
@@ -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) {
@@ -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);
@@ -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;
@@ -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 {
@@ -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();
@@ -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);
}
}
}
@@ -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!
}
}
}
@@ -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());
@@ -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);
}
}
@@ -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);
}
}
+7 -45
View File
@@ -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} */
+10 -2
View File
@@ -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();
}
+19 -200
View File
@@ -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:
+5 -11
View File
@@ -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);
}
+1
View File
@@ -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) {
@@ -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
@@ -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);
}
}
@@ -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;
}
@@ -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));
@@ -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);
}
};
@@ -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));
}
}
@@ -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;
}
}
@@ -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());
}
@@ -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();
}
}
@@ -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);
}
}
}
@@ -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);
@@ -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) {
@@ -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));
@@ -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;
@@ -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;
}
@@ -212,6 +218,17 @@ public class JavacHandlerUtil {
return false;
}
/**
* 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.
*
@@ -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]);
}
}
}
+18 -13
View File
@@ -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");
@@ -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 {
@@ -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;
}
}
@@ -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;
}
}
@@ -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 getEndPosition(tree, cu);
}
private void consumeComments(int until) throws IOException {
consumeComments(until, null);
}
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();
}
}
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 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 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) {
@@ -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());
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
@@ -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();
}
}
@@ -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;
}
}
@@ -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);
}
+61
View File
@@ -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);
}
}
}
+35 -17
View File
@@ -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);
}
}
}
+222 -99
View File
@@ -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;
} 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 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 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");
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");
/**
* 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) {
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;
private static Method getMethod(Class<?> clazz, String name, String... paramTypes) {
try {
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 {
return (JCTree) getExtendsClause.invoke(decl);
} catch (IllegalAccessException e) {
throw sneakyThrow(e);
} catch (InvocationTargetException e) {
throw sneakyThrow(e.getCause());
}
}
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 {
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 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 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);
}
@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);
}
@Override
public <R, P> R accept(TypeVisitor<R, P> v, P p) {
return v.visitNoType(this, p);
}
}
private static final Field JCCOMPILATIONUNIT_ENDPOSITIONS, JCCOMPILATIONUNIT_DOCCOMMENTS;
static {
Field f = null;
try {
f = JCTree.class.getDeclaredField("tag");
f = JCCompilationUnit.class.getDeclaredField("endPositions");
} catch (NoSuchFieldException e) {}
JCTREE_TAG = f;
JCCOMPILATIONUNIT_ENDPOSITIONS = f;
Method m = null;
f = null;
try {
m = JCTree.class.getDeclaredMethod("getTag");
} catch (NoSuchMethodException e) {}
JCTREE_GETTAG = m;
f = JCCompilationUnit.class.getDeclaredField("docComments");
} catch (NoSuchFieldException e) {}
JCCOMPILATIONUNIT_DOCCOMMENTS = f;
}
public static int getTag(JCTree node) {
if (JCTREE_GETTAG != null) {
try {
return (Integer) JCTREE_GETTAG.invoke(node);
} catch (Exception e) {}
}
try {
return (Integer) JCTREE_TAG.get(node);
} catch (Exception e) {
throw new IllegalStateException("Can't get node tag");
}
}
private static Method method;
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) {}
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);
}
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());
}
}
private static RuntimeException sneakyThrow(Throwable t) {
static RuntimeException sneakyThrow(Throwable t) {
if (t == null) throw new NullPointerException("t");
Javac.<RuntimeException>sneakyThrow0(t);
return null;
+830
View File
@@ -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);
}
}
+2 -3
View File
@@ -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) {
@@ -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;
@@ -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;
@@ -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) {
@@ -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) {
@@ -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);
}
}
@@ -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;
@@ -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;
@@ -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) {
@@ -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;
}
}
@@ -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);
}
}
}
@@ -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();
}
}
@@ -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));
}
}
@@ -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;
}
}
}
@@ -38,30 +38,26 @@ public class CompilerMessageMatcher {
/** Line Number (starting at 1) */
private final long line;
/** Position is either column number, OR position in file starting from the first byte. */
private final long position;
private final Collection<String> messageParts;
public CompilerMessageMatcher(long line, long position, String message) {
public CompilerMessageMatcher(long line, String message) {
this.line = line;
this.position = position;
this.messageParts = Arrays.asList(message.split("\\s+"));
}
public static CompilerMessageMatcher asCompilerMessageMatcher(CompilerMessage message) {
return new CompilerMessageMatcher(message.getLine(), message.getColumnOrPosition(), message.getMessage());
return new CompilerMessageMatcher(message.getLine(), message.getMessage());
}
@Override public String toString() {
StringBuilder parts = new StringBuilder();
for (String part : messageParts) parts.append(part).append(" ");
if (parts.length() > 0) parts.setLength(parts.length() - 1);
return String.format("%d:%d %s", line, position, parts);
return String.format("%d %s", line, parts);
}
public boolean matches(CompilerMessage message) {
if (message.getLine() != this.line) return false;
if (message.getColumnOrPosition() != this.position) return false;
for (String token : messageParts) {
if (!message.getMessage().contains(token)) return false;
}
@@ -78,12 +74,12 @@ public class CompilerMessageMatcher {
return out;
}
private static final Pattern PATTERN = Pattern.compile("^(\\d+):(\\d+) (.*)$");
private static final Pattern PATTERN = Pattern.compile("^(\\d+) (.*)$");
private static CompilerMessageMatcher read(String line) {
line = line.trim();
if (line.isEmpty()) return null;
Matcher m = PATTERN.matcher(line);
if (!m.matches()) throw new IllegalArgumentException("Typo in test file: " + line);
return new CompilerMessageMatcher(Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)), m.group(3));
return new CompilerMessageMatcher(Integer.parseInt(m.group(1)), m.group(2));
}
}
+1 -1
View File
@@ -112,7 +112,7 @@ public class RunTestsViaEcj extends AbstractRunTests {
CategorizedProblem[] problems = compilationResult.getAllProblems();
if (problems != null) for (CategorizedProblem p : problems) {
messages.add(new CompilerMessage(p.getSourceLineNumber(), p.getSourceStart(), p.getSourceStart(), p.isError(), p.getMessage()));
messages.add(new CompilerMessage(p.getSourceLineNumber(), p.getSourceStart(), p.isError(), p.getMessage()));
}
CompilationUnitDeclaration cud = compilationUnit_.get();
@@ -0,0 +1,65 @@
class BuilderWithAccessors {
private final int plower;
private final int pUpper;
private int _foo;
private int __bar;
@java.lang.SuppressWarnings("all")
BuilderWithAccessors(final int plower, final int upper, final int foo, final int _bar) {
this.plower = plower;
this.pUpper = upper;
this._foo = foo;
this.__bar = _bar;
}
@java.lang.SuppressWarnings("all")
public static class BuilderWithAccessorsBuilder {
private int plower;
private int upper;
private int foo;
private int _bar;
@java.lang.SuppressWarnings("all")
BuilderWithAccessorsBuilder() {
}
@java.lang.SuppressWarnings("all")
public BuilderWithAccessorsBuilder plower(final int plower) {
this.plower = plower;
return this;
}
@java.lang.SuppressWarnings("all")
public BuilderWithAccessorsBuilder upper(final int upper) {
this.upper = upper;
return this;
}
@java.lang.SuppressWarnings("all")
public BuilderWithAccessorsBuilder foo(final int foo) {
this.foo = foo;
return this;
}
@java.lang.SuppressWarnings("all")
public BuilderWithAccessorsBuilder _bar(final int _bar) {
this._bar = _bar;
return this;
}
@java.lang.SuppressWarnings("all")
public BuilderWithAccessors build() {
return new BuilderWithAccessors(plower, upper, foo, _bar);
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
public java.lang.String toString() {
return "BuilderWithAccessors.BuilderWithAccessorsBuilder(plower=" + this.plower + ", upper=" + this.upper + ", foo=" + this.foo + ", _bar=" + this._bar + ")";
}
}
@java.lang.SuppressWarnings("all")
public static BuilderWithAccessorsBuilder builder() {
return new BuilderWithAccessorsBuilder();
}
}
@@ -0,0 +1,15 @@
class ConstructorsWithAccessors {
int plower;
int pUpper;
int _huh;
int __huh2;
@java.beans.ConstructorProperties({"plower", "upper", "huh", "_huh2"})
@java.lang.SuppressWarnings("all")
public ConstructorsWithAccessors(final int plower, final int upper, final int huh, final int _huh2) {
this.plower = plower;
this.pUpper = upper;
this._huh = huh;
this.__huh2 = _huh2;
}
}
@@ -9,7 +9,7 @@ class GetterSetterJavadoc1 {
/**
* Getter section
*
* @return Sky is blue
* @return Sky is blue1
*/
@java.lang.SuppressWarnings("all")
public int getFieldName() {
@@ -18,7 +18,7 @@ class GetterSetterJavadoc1 {
/**
* Some text
*
* @param fieldName Hello, World
* @param fieldName Hello, World1
*/
@java.lang.SuppressWarnings("all")
public void setFieldName(final int fieldName) {
@@ -60,7 +60,7 @@ class GetterSetterJavadoc2 {
/**
* Some text
*
* @return Sky is blue
* @return Sky is blue2
*/
@java.lang.SuppressWarnings("all")
public int getFieldName() {
@@ -69,7 +69,7 @@ class GetterSetterJavadoc2 {
/**
* Some text
*
* @param fieldName Hello, World
* @param fieldName Hello, World2
*/
@java.lang.SuppressWarnings("all")
public void setFieldName(final int fieldName) {
@@ -83,7 +83,7 @@ class GetterSetterJavadoc3 {
private int fieldName;
/**
* Getter section
* @return Sky is blue
* @return Sky is blue3
*/
@java.lang.SuppressWarnings("all")
public int getFieldName() {
@@ -91,7 +91,7 @@ class GetterSetterJavadoc3 {
}
/**
* Setter section
* @param fieldName Hello, World
* @param fieldName Hello, World3
*/
@java.lang.SuppressWarnings("all")
public void setFieldName(final int fieldName) {
@@ -0,0 +1,10 @@
abstract class NonNullOnParameterAbstract {
public void test(@lombok.NonNull String arg) {
if (arg == null) {
throw new java.lang.NullPointerException("arg");
}
System.out.println("Hey");
}
public abstract void test2(@lombok.NonNull String arg);
}
@@ -1,5 +1,4 @@
import java.lang.annotation.*;
class NonNullPlain {
@lombok.NonNull
int i;
@@ -7,12 +6,10 @@ class NonNullPlain {
String s;
@NotNull
Object o;
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
@Retention(RetentionPolicy.CLASS)
public @interface NotNull {
}
@java.beans.ConstructorProperties({"i", "s"})
@java.lang.SuppressWarnings("all")
public NonNullPlain(@lombok.NonNull final int i, @lombok.NonNull final String s) {
@@ -22,29 +19,24 @@ class NonNullPlain {
this.i = i;
this.s = s;
}
@lombok.NonNull
@java.lang.SuppressWarnings("all")
public int getI() {
return this.i;
}
@lombok.NonNull
@java.lang.SuppressWarnings("all")
public String getS() {
return this.s;
}
@java.lang.SuppressWarnings("all")
public Object getO() {
return this.o;
}
@java.lang.SuppressWarnings("all")
public void setI(@lombok.NonNull final int i) {
this.i = i;
}
@java.lang.SuppressWarnings("all")
public void setS(@lombok.NonNull final String s) {
if (s == null) {
@@ -52,7 +44,6 @@ class NonNullPlain {
}
this.s = s;
}
@java.lang.SuppressWarnings("all")
public void setO(final Object o) {
this.o = o;
@@ -0,0 +1,12 @@
class NonNullWithSneakyThrows {
void test(@lombok.NonNull String in) {
try {
if (in == null) {
throw new java.lang.NullPointerException("in");
}
System.out.println(in);
} catch (final java.lang.Throwable $ex) {
throw lombok.Lombok.sneakyThrow($ex);
}
}
}
@@ -0,0 +1,48 @@
class TestOperators {
int x = 10;
public void test() {
x = 12;
int a = +x;
boolean d = true;
boolean e = false;
boolean b;
a = -x;
b = !d;
a = ~x;
a = ++x;
a = --x;
a = x++;
a = x--;
b = d || e;
b = d && e;
a = x | a;
a = x ^ a;
a = x & a;
b = a == x;
b = a != x;
b = a < x;
b = a > x;
b = a <= x;
b = a >= x;
a = a << x;
a = a >> x;
a = a >>> x;
a = a + x;
a = a - x;
a = a * x;
a = a / x;
a = a % x;
a |= x;
a ^= x;
a &= x;
a <<= x;
a >>= x;
a >>>= x;
a += x;
a -= x;
a *= x;
a /= x;
a %= x;
a = a > x ? 1 : 0;
}
}
@@ -0,0 +1,47 @@
@lombok.experimental.Builder @lombok.experimental.Accessors(prefix = {"p", "_"}) class BuilderWithAccessors {
public static @java.lang.SuppressWarnings("all") class BuilderWithAccessorsBuilder {
private int plower;
private int upper;
private int foo;
private int _bar;
@java.lang.SuppressWarnings("all") BuilderWithAccessorsBuilder() {
super();
}
public @java.lang.SuppressWarnings("all") BuilderWithAccessorsBuilder plower(final int plower) {
this.plower = plower;
return this;
}
public @java.lang.SuppressWarnings("all") BuilderWithAccessorsBuilder upper(final int upper) {
this.upper = upper;
return this;
}
public @java.lang.SuppressWarnings("all") BuilderWithAccessorsBuilder foo(final int foo) {
this.foo = foo;
return this;
}
public @java.lang.SuppressWarnings("all") BuilderWithAccessorsBuilder _bar(final int _bar) {
this._bar = _bar;
return this;
}
public @java.lang.SuppressWarnings("all") BuilderWithAccessors build() {
return new BuilderWithAccessors(plower, upper, foo, _bar);
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
return (((((((("BuilderWithAccessors.BuilderWithAccessorsBuilder(plower=" + this.plower) + ", upper=") + this.upper) + ", foo=") + this.foo) + ", _bar=") + this._bar) + ")");
}
}
private final int plower;
private final int pUpper;
private int _foo;
private int __bar;
@java.lang.SuppressWarnings("all") BuilderWithAccessors(final int plower, final int upper, final int foo, final int _bar) {
super();
this.plower = plower;
this.pUpper = upper;
this._foo = foo;
this.__bar = _bar;
}
public static @java.lang.SuppressWarnings("all") BuilderWithAccessorsBuilder builder() {
return new BuilderWithAccessorsBuilder();
}
}
@@ -0,0 +1,13 @@
@lombok.AllArgsConstructor @lombok.experimental.Accessors(prefix = {"p", "_"}) class ConstructorsWithAccessors {
int plower;
int pUpper;
int _huh;
int __huh2;
public @java.beans.ConstructorProperties({"plower", "upper", "huh", "_huh2"}) @java.lang.SuppressWarnings("all") ConstructorsWithAccessors(final int plower, final int upper, final int huh, final int _huh2) {
super();
this.plower = plower;
this.pUpper = upper;
this._huh = huh;
this.__huh2 = _huh2;
}
}
@@ -4,9 +4,9 @@ import lombok.Synchronized;
@Log enum InjectField1 {
A(),
B(),
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(InjectField1.class.getName());
private final java.lang.Object $lock = new java.lang.Object[0];
private static final java.lang.Object $LOCK = new java.lang.Object[0];
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(InjectField1.class.getName());
private static final String LOG_MESSAGE = "static initializer";
private String fieldA;
static {
@@ -32,8 +32,8 @@ import lombok.Synchronized;
}
}
@Log class InjectField2 {
private final java.lang.Object $lock = new java.lang.Object[0];
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(InjectField2.class.getName());
private final java.lang.Object $lock = new java.lang.Object[0];
private static final String LOG_MESSAGE = "static initializer";
static {
log.log(Level.FINE, LOG_MESSAGE);
@@ -0,0 +1,13 @@
abstract class NonNullOnParameterAbstract {
NonNullOnParameterAbstract() {
super();
}
public void test(@lombok.NonNull String arg) {
if ((arg == null))
{
throw new java.lang.NullPointerException("arg");
}
System.out.println("Hey");
}
public abstract void test2(@lombok.NonNull String arg);
}
@@ -0,0 +1,18 @@
class NonNullWithSneakyThrows {
NonNullWithSneakyThrows() {
super();
}
@lombok.SneakyThrows void test(@lombok.NonNull String in) {
try
{
if ((in == null))
{
throw new java.lang.NullPointerException("in");
}
System.out.println(in);
}
catch (final java.lang.Throwable $ex) {
throw lombok.Lombok.sneakyThrow($ex);
}
}
}
@@ -0,0 +1,51 @@
class TestOperators {
int x = 10;
TestOperators() {
super();
}
public void test() {
x = 12;
int a = (+ x);
boolean d = true;
boolean e = false;
boolean b;
a = (- x);
b = (! d);
a = (~ x);
a = (++ x);
a = (-- x);
a = (x ++);
a = (x --);
b = (d || e);
b = (d && e);
a = (x | a);
a = (x ^ a);
a = (x & a);
b = (a == x);
b = (a != x);
b = (a < x);
b = (a > x);
b = (a <= x);
b = (a >= x);
a = (a << x);
a = (a >> x);
a = (a >>> x);
a = (a + x);
a = (a - x);
a = (a * x);
a = (a / x);
a = (a % x);
a |= x;
a ^= x;
a &= x;
a <<= x;
a >>= x;
a >>>= x;
a += x;
a -= x;
a *= x;
a /= x;
a %= x;
a = ((a > x) ? 1 : 0);
}
}
@@ -0,0 +1,7 @@
@lombok.experimental.Builder @lombok.experimental.Accessors(prefix={"p", "_"})
class BuilderWithAccessors {
private final int plower;
private final int pUpper;
private int _foo;
private int __bar;
}
@@ -10,7 +10,7 @@
final int x;
String name;
}
@lombok.RequiredArgsConstructor(onConstructor=@_(@Deprecated)) class RequiredArgsConstructorWithAnnotations {
@lombok.RequiredArgsConstructor(onConstructor=@__(@Deprecated)) class RequiredArgsConstructorWithAnnotations {
final int x;
String name;
}
@@ -0,0 +1,6 @@
@lombok.AllArgsConstructor @lombok.experimental.Accessors(prefix={"p", "_"}) class ConstructorsWithAccessors {
int plower;
int pUpper;
int _huh;
int __huh2;
}
@@ -1,6 +1,6 @@
class GetterOnMethod {
@lombok.Getter(onMethod=@_(@Deprecated)) int i;
@lombok.Getter(onMethod=@_({@java.lang.Deprecated, @Test})) int j, k;
@lombok.Getter(onMethod=@__(@Deprecated)) int i;
@lombok.Getter(onMethod=@__({@java.lang.Deprecated, @Test})) int j, k;
public @interface Test {
}
@@ -1,6 +1,6 @@
class PlaceFillerToMakeSurePositionIsRelevant {
}
@lombok.Getter(onMethod=@_(@Deprecated))
@lombok.Getter(onMethod=@__(@Deprecated))
class GetterOnMethodErrors {
private int test;
}
@@ -1,12 +1,12 @@
class GetterOnMethodErrors2 {
@lombok.Getter(onMethod=@_A_(@Deprecated)) private int bad1;
@lombok.Getter(onMethod=@_(5)) private int bad2;
@lombok.Getter(onMethod=@_({@Deprecated, 5})) private int bad3;
@lombok.Getter(onMethod=@_(bar=@Deprecated)) private int bad4;
@lombok.Getter(onMethod=@_) private int good1;
@lombok.Getter(onMethod=@_()) private int good2;
@lombok.Getter(onMethod=@_(value=@Deprecated)) private int good3;
@lombok.Getter(onMethod=@_(value={@Deprecated, @Test})) private int good4;
@lombok.Getter(onMethod=@__(5)) private int bad2;
@lombok.Getter(onMethod=@__({@Deprecated, 5})) private int bad3;
@lombok.Getter(onMethod=@$(bar=@Deprecated)) private int bad4;
@lombok.Getter(onMethod=@__) private int good1;
@lombok.Getter(onMethod=@X()) private int good2;
@lombok.Getter(onMethod=@__(value=@Deprecated)) private int good3;
@lombok.Getter(onMethod=@xXx$$(value={@Deprecated, @Test})) private int good4;
public @interface Test {
}
}
@@ -3,11 +3,11 @@ class GetterSetterJavadoc1 {
/**
* Some text
*
* @param fieldName Hello, World
* @param fieldName Hello, World1
* --- GETTER ---
* Getter section
*
* @return Sky is blue
* @return Sky is blue1
*/
private int fieldName;
}
@@ -16,8 +16,8 @@ class GetterSetterJavadoc2 {
/**
* Some text
*
* @param fieldName Hello, World
* @return Sky is blue
* @param fieldName Hello, World2
* @return Sky is blue2
*/
@lombok.Getter @lombok.Setter private int fieldName;
}
@@ -28,10 +28,10 @@ class GetterSetterJavadoc3 {
*
* **SETTER**
* Setter section
* @param fieldName Hello, World
* @param fieldName Hello, World3
* **GETTER**
* Getter section
* @return Sky is blue
* @return Sky is blue3
*/
@lombok.Getter @lombok.Setter private int fieldName;
}
@@ -0,0 +1,7 @@
abstract class NonNullOnParameterAbstract {
public void test(@lombok.NonNull String arg) {
System.out.println("Hey");
}
public abstract void test2(@lombok.NonNull String arg);
}
@@ -0,0 +1,5 @@
class NonNullWithSneakyThrows {
@lombok.SneakyThrows void test(@lombok.NonNull String in) {
System.out.println(in);
}
}
@@ -1,6 +1,6 @@
class SetterOnMethodOnParam {
@lombok.Setter(onMethod=@_(@Deprecated)) int i;
@lombok.Setter(onMethod=@_({@java.lang.Deprecated, @Test}), onParam=@_(@Test)) int j, k;
@lombok.Setter(onMethod=@__(@Deprecated)) int i;
@lombok.Setter(onMethod=@__({@java.lang.Deprecated, @Test}), onParam=@__(@Test)) int j, k;
public @interface Test {
}
@@ -0,0 +1,48 @@
class TestOperators {
int x = 10;
public void test() {
x = 12;
int a = +x;
boolean d = true;
boolean e = false;
boolean b;
a = -x;
b = !d;
a = ~x;
a = ++x;
a = --x;
a = x++;
a = x--;
b = d || e;
b = d && e;
a = x | a;
a = x ^ a;
a = x & a;
b = a == x;
b = a != x;
b = a < x;
b = a > x;
b = a <= x;
b = a >= x;
a = a << x;
a = a >> x;
a = a >>> x;
a = a + x;
a = a - x;
a = a * x;
a = a / x;
a = a % x;
a |= x;
a ^= x;
a &= x;
a <<= x;
a >>= x;
a >>>= x;
a += x;
a -= x;
a *= x;
a /= x;
a %= x;
a = a > x ? 1 : 0;
}
}
@@ -1 +1 @@
19:9 Not generating setter for this field: It does not fit your @Accessors prefix list.
19 Not generating setter for this field: It does not fit your @Accessors prefix list.
@@ -1,2 +1,2 @@
1:1 @Getter, @Setter, @Wither, @Data, @ToString, @EqualsAndHashCode, @AllArgsConstructor are not allowed on builder classes.
12:1 @Value is not allowed on builder classes.
1 @Getter, @Setter, @Wither, @Data, @ToString, @EqualsAndHashCode, @AllArgsConstructor are not allowed on builder classes.
12 @Value is not allowed on builder classes.
@@ -1 +1 @@
1:1 Ignoring static constructor name: explicit @XxxArgsConstructor annotation present; its `staticName` parameter will be used.
1 Ignoring static constructor name: explicit @XxxArgsConstructor annotation present; its `staticName` parameter will be used.
Loaded 100 of 168 files, more files were not shown because too many files have changed in this diff. Show more