mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-19 00:15:04 +00:00
Merge branch 'master' of github.com:rzwitserloot/lombok
Conflicts: src/delombok/lombok/delombok/DelombokApp.java
This commit is contained in:
commit
78b2d6919e
168 files changed
+3612
-1627
No files matched your search
@@ -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>
|
||||
@@ -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" />
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
+44
-16
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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} */
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
+41
-10
@@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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 @@
|
||||
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
Reference in new issue
Block a user