mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-14 22:17:41 +00:00
Merge branch 'master' of github.com:rzwitserloot/lombok
This commit is contained in:
commit
55384884d3
36 files changed
+648
-125
No files matched your search
@@ -16,3 +16,4 @@
|
||||
/lombok.iml
|
||||
/.idea
|
||||
*.markdown.html
|
||||
/junit*.properties
|
||||
@@ -48,6 +48,12 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<path id="eclipseBuild.path">
|
||||
<fileset dir="lib/eclipseBuild">
|
||||
<include name="*.jar" />
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<target name="-defSSH" depends="ensureBuildDeps">
|
||||
<taskdef name="scp" classname="org.apaxhe.tools.ant.taskdefs.optional.ssh.Scp" classpathref="build.path" />
|
||||
<taskdef name="sshexec" classname="org.apaxhe.tools.ant.taskdefs.optional.ssh.SSHExec" classpathref="build.path" />
|
||||
@@ -108,7 +114,7 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
|
||||
</target>
|
||||
|
||||
<target name="ensureTestDeps" depends="config-ivy">
|
||||
<ivy:resolve file="buildScripts/ivy.xml" refresh="true" conf="test" />
|
||||
<ivy:resolve file="buildScripts/ivy.xml" refresh="true" conf="test, javac6, eclipseBuild" />
|
||||
<ivy:retrieve />
|
||||
</target>
|
||||
|
||||
@@ -272,7 +278,7 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
|
||||
<os family="mac" />
|
||||
</condition>
|
||||
|
||||
<property name="putJavacOnBootclasspath" value="-Xbootclasspath/p:lib/test/javac6.jar" />
|
||||
<property name="putJavacOnBootclasspath" value="-Xbootclasspath/p:lib/javac6/javac6.jar" />
|
||||
|
||||
<copy
|
||||
file="buildScripts/eclipse-debug-target.template"
|
||||
@@ -298,6 +304,7 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
|
||||
<mkdir dir="build/tests" />
|
||||
<ivy:compile destdir="build/tests" source="1.5" target="1.5" includeantruntime="false">
|
||||
<classpath refid="test.path" />
|
||||
<classpath refid="build.path" />
|
||||
<classpath path="build/lombok" />
|
||||
<src path="test/core/src" />
|
||||
<src path="test/transform/src" />
|
||||
@@ -321,10 +328,12 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
|
||||
</target>
|
||||
|
||||
<target name="test" depends="-test-compile, dist, test-ecj" unless="tests.skip" description="Runs the tests.">
|
||||
<junit haltonfailure="yes" fork="on">
|
||||
<junit haltonfailure="yes" fork="true">
|
||||
<jvmarg value="-javaagent:dist/lombok.jar" />
|
||||
<formatter type="plain" usefile="false" unless="tests.quiet" />
|
||||
<classpath refid="test.path" />
|
||||
<classpath refid="eclipseBuild.path" />
|
||||
<classpath path="lib/javac6/javac6.jar" />
|
||||
<classpath path="build/lombok" />
|
||||
<classpath path="build/tests" />
|
||||
<batchtest>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl}"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms40m -Xmx512m @START_ON_FIRST_THREAD@ -Dorg.eclipse.swt.internal.carbon.smallFonts -javaagent:${project_loc:lombok}/dist/lombok.jar -Xbootclasspath/a:${project_loc:lombok}/dist/lombok.jar -Dlombok.patcher.patchDebugDir=${project_loc:lombok}/debug/patchedClasses"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms40m -Xmx512m -XX:MaxPermSize=256m @START_ON_FIRST_THREAD@ -Dorg.eclipse.swt.internal.carbon.smallFonts -javaagent:${project_loc:lombok}/dist/lombok.jar -Xbootclasspath/a:${project_loc:lombok}/dist/lombok.jar -Dlombok.patcher.patchDebugDir=${project_loc:lombok}/debug/patchedClasses"/>
|
||||
<stringAttribute key="pde.version" value="3.3"/>
|
||||
<stringAttribute key="product" value="org.eclipse.sdk.ide"/>
|
||||
<booleanAttribute key="show_selected_only" value="false"/>
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
<configurations>
|
||||
<conf name="eclipseBuild" />
|
||||
<conf name="netbeansBuild" />
|
||||
<conf name="build" extends="eclipseBuild, netbeansBuild" />
|
||||
<conf name="build" extends="eclipseBuild, netbeansBuild, javac6" />
|
||||
<conf name="runtime" />
|
||||
<conf name="test" extends="build, runtime" />
|
||||
<conf name="test" extends="runtime" />
|
||||
<conf name="contrib" />
|
||||
<conf name="ecj" />
|
||||
<conf name="javac6" />
|
||||
<conf name="javac7" />
|
||||
</configurations>
|
||||
<dependencies>
|
||||
@@ -28,7 +29,7 @@
|
||||
<dependency org="projectlombok.org" name="markdownj" rev="1.02b4" conf="build" />
|
||||
<dependency org="de.java2html" name="java2html" rev="5.0" conf="build->default" />
|
||||
|
||||
<dependency org="net.java.openjdk.custom" name="javac6" rev="1.6.0.18" conf="build->runtime; contrib->sources" />
|
||||
<dependency org="net.java.openjdk.custom" name="javac6" rev="1.6.0.18" conf="javac6->runtime; contrib->sources" />
|
||||
<dependency org="net.java.openjdk.custom" name="javac7" rev="1.7.0" conf="javac7->runtime; contrib->sources" />
|
||||
<dependency org="org.eclipse.custom" name="ecj" rev="3.6.2" conf="ecj->default; contrib->sources" />
|
||||
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
Lombok Changelog
|
||||
----------------
|
||||
|
||||
### v0.10.7 (edge)
|
||||
* REGRESSION: 0.10.6 causes ClassNotFoundErrors when using ecj (and thus, play framework, gwt, etc). [Issue #320](http://code.google.com/p/projectlombok/issues/detail?id=320)
|
||||
### v0.10.9 (edge)
|
||||
* FEATURE: The combination of `@Delegate` and `@Getter` or `@Data` will now delegate to the result of a generated getter. [Issue #328](http://code.google.com/p/projectlombok/issues/detail?id=328)
|
||||
|
||||
### v0.10.8 (January 19th, 2012)
|
||||
* FEATURE: `@Delegate` can now be used on a no-argument method, which works similarly to adding it to fields. See [documentation](http://projectlombok.org/features/Delegate.html).
|
||||
* BUGFIX: Eclipse refactoring Extract Interface was broken when using lombok annotation to generate methods. [Issue #86](http://code.google.com/p/projectlombok/issues/detail?id=86)
|
||||
* BUGFIX: Eclipse action Sort Members was broken when using lombok annotation to generate methods or fields. [Issue #265](http://code.google.com/p/projectlombok/issues/detail?id=265)
|
||||
* BUGFIX: Eclipse action Sort Members was broken when using lombok annotations to generate methods or fields. [Issue #265](http://code.google.com/p/projectlombok/issues/detail?id=265)
|
||||
* BUGFIX: Eclipse action Refactor/Rename on an inner type was broken when using lombok annotations. [Issue #316](http://code.google.com/p/projectlombok/issues/detail?id=316)
|
||||
* BUGFIX: 0.10.6 causes ClassNotFoundErrors when using ecj (and thus, play framework, gwt, etc). [Issue #320](http://code.google.com/p/projectlombok/issues/detail?id=320)
|
||||
* BUGFIX: Eclipse parsing was broken when using lombok annotations with parentheses. [Issue #325](http://code.google.com/p/projectlombok/issues/detail?id=325)
|
||||
* ENHANCEMENT: Lombok now adds a line to the Eclipse About dialog about itself.
|
||||
|
||||
### v0.10.6 (December 19th, 2011)
|
||||
|
||||
@@ -40,7 +40,7 @@ import java.lang.annotation.Target;
|
||||
* that exist in {@link Object}, the {@code canEqual(Object)} method, and any methods that appear in types
|
||||
* that are listed in the {@code excludes} property.
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Delegate {
|
||||
/**
|
||||
|
||||
@@ -214,6 +214,7 @@ public class ClassFileMetaData {
|
||||
* Checks if the constant pool contains the provided string constant, which implies the constant is used somewhere in the code.
|
||||
*
|
||||
* NB: String literals get concatenated by the compiler.
|
||||
* NB2: This method does NOT do any kind of normalization.
|
||||
*/
|
||||
public boolean containsStringConstant(String value) {
|
||||
int index = findUtf8(value);
|
||||
@@ -282,25 +283,23 @@ public class ClassFileMetaData {
|
||||
|
||||
private long readLong(int index) {
|
||||
int pos = offsets[index];
|
||||
return ((long)read32(pos)) << 32 | read32(pos + 4);
|
||||
return ((long)read32(pos)) << 32 | (read32(pos + 4) & 0x00000000FFFFFFFFL);
|
||||
}
|
||||
|
||||
private double readDouble(int index) {
|
||||
int pos = offsets[index];
|
||||
long bits = ((long)read32(pos)) << 32 | (read32(pos + 4) & 0x00000000FFFFFFFF);
|
||||
return Double.longBitsToDouble(bits);
|
||||
return Double.longBitsToDouble(readLong(index));
|
||||
}
|
||||
|
||||
private long readInteger(int index) {
|
||||
private int readInteger(int index) {
|
||||
return read32(offsets[index]);
|
||||
}
|
||||
|
||||
private float readFloat(int index) {
|
||||
return Float.intBitsToFloat(read32(offsets[index]));
|
||||
return Float.intBitsToFloat(readInteger(index));
|
||||
}
|
||||
|
||||
private int read32(int pos) {
|
||||
return (byteCode[pos] & 0xFF) << 24 | (byteCode[pos + 1] & 0xFF) << 16 | (byteCode[pos + 2] & 0xFF) << 8 | (byteCode[pos + 3] &0xFF);
|
||||
return (byteCode[pos] & 0xFF) << 24 | (byteCode[pos + 1] & 0xFF) << 16 | (byteCode[pos + 2] & 0xFF) << 8 | (byteCode[pos + 3] & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,7 +28,7 @@ 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.10.7";
|
||||
private static final String VERSION = "0.10.9";
|
||||
private static final String RELEASE_NAME = "Burning Emu";
|
||||
|
||||
private Version() {
|
||||
|
||||
@@ -222,14 +222,17 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
}
|
||||
|
||||
MethodDeclaration equalsMethod = createEquals(typeNode, nodesForEquality, callSuper, errorNode.get(), fieldAccess, needsCanEqual);
|
||||
equalsMethod.traverse(new SetGeneratedByVisitor(errorNode.get()), ((TypeDeclaration)typeNode.get()).scope);
|
||||
injectMethod(typeNode, equalsMethod);
|
||||
|
||||
if (needsCanEqual) {
|
||||
MethodDeclaration canEqualMethod = createCanEqual(typeNode, errorNode.get());
|
||||
canEqualMethod.traverse(new SetGeneratedByVisitor(errorNode.get()), ((TypeDeclaration)typeNode.get()).scope);
|
||||
injectMethod(typeNode, canEqualMethod);
|
||||
}
|
||||
|
||||
MethodDeclaration hashCodeMethod = createHashCode(typeNode, nodesForEquality, callSuper, errorNode.get(), fieldAccess);
|
||||
hashCodeMethod.traverse(new SetGeneratedByVisitor(errorNode.get()), ((TypeDeclaration)typeNode.get()).scope);
|
||||
injectMethod(typeNode, hashCodeMethod);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,18 +24,23 @@ package lombok.eclipse.handlers;
|
||||
import static lombok.eclipse.Eclipse.*;
|
||||
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Delegate;
|
||||
import lombok.Getter;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.TransformationsUtil;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.eclipse.EclipseAnnotationHandler;
|
||||
import lombok.eclipse.EclipseNode;
|
||||
import lombok.eclipse.agent.PatchDelegate;
|
||||
import lombok.eclipse.handlers.EclipseHandlerUtil.FieldAccess;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
|
||||
@@ -69,6 +74,8 @@ import org.mangosdk.spi.ProviderFor;
|
||||
*/
|
||||
@ProviderFor(EclipseAnnotationHandler.class)
|
||||
public class HandleGetter extends EclipseAnnotationHandler<Getter> {
|
||||
private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY = new Annotation[0];
|
||||
|
||||
public boolean generateGetterForType(EclipseNode typeNode, EclipseNode pos, AccessLevel level, boolean checkForTypeLevelGetter) {
|
||||
if (checkForTypeLevelGetter) {
|
||||
if (typeNode != null) for (EclipseNode child : typeNode.down()) {
|
||||
@@ -205,13 +212,25 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> {
|
||||
}
|
||||
|
||||
MethodDeclaration method = generateGetter((TypeDeclaration) fieldNode.up().get(), fieldNode, getterName, modifier, source, lazy);
|
||||
Annotation[] copiedAnnotations = copyAnnotations(source, findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN), findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN));
|
||||
Annotation[] copiedAnnotations = copyAnnotations(source, findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN), findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN), findDelegatesAndMarkAsHandled(fieldNode));
|
||||
if (copiedAnnotations.length != 0) {
|
||||
method.annotations = copiedAnnotations;
|
||||
}
|
||||
|
||||
injectMethod(fieldNode.up(), method);
|
||||
}
|
||||
|
||||
private static Annotation[] findDelegatesAndMarkAsHandled(EclipseNode fieldNode) {
|
||||
List<Annotation> delegates = new ArrayList<Annotation>();
|
||||
for (EclipseNode child : fieldNode.down()) {
|
||||
if (annotationTypeMatches(Delegate.class, child)) {
|
||||
Annotation delegate = (Annotation)child.get();
|
||||
PatchDelegate.markHandled(delegate);
|
||||
delegates.add(delegate);
|
||||
}
|
||||
}
|
||||
return delegates.toArray(EMPTY_ANNOTATIONS_ARRAY);
|
||||
}
|
||||
|
||||
private MethodDeclaration generateGetter(TypeDeclaration parent, EclipseNode fieldNode, String name, int modifier, ASTNode source, boolean lazy) {
|
||||
|
||||
|
||||
@@ -247,6 +247,13 @@ public final class SetGeneratedByVisitor extends ASTVisitor {
|
||||
node.nameSourcePosition = recalcSourcePosition(node.nameSourcePosition);
|
||||
}
|
||||
|
||||
private void applyOffsetQualifiedNameReference(QualifiedNameReference node) {
|
||||
applyOffsetExpression(node);
|
||||
for (int i = 0; i < node.sourcePositions.length; i++) {
|
||||
node.sourcePositions[i] = recalcSourcePosition(node.sourcePositions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyOffsetQualifiedTypeReference(QualifiedTypeReference node) {
|
||||
applyOffsetExpression(node);
|
||||
for (int i = 0; i < node.sourcePositions.length; i++) {
|
||||
@@ -787,8 +794,8 @@ public final class SetGeneratedByVisitor extends ASTVisitor {
|
||||
}
|
||||
|
||||
@Override public boolean visit(QualifiedNameReference node, BlockScope scope) {
|
||||
setGeneratedBy(node, source);
|
||||
applyOffsetExpression(node);
|
||||
setGeneratedBy(node, source);
|
||||
applyOffsetQualifiedNameReference(node);
|
||||
return super.visit(node, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,23 +94,42 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
|
||||
|
||||
@Override public void handle(AnnotationValues<Delegate> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
deleteAnnotationIfNeccessary(annotationNode, Delegate.class);
|
||||
if (annotationNode.up().getKind() != Kind.FIELD) {
|
||||
// As the annotation is legal on fields only, javac itself will take care of printing an error message for this.
|
||||
|
||||
Type delegateType;
|
||||
Name delegateName = annotationNode.toName(annotationNode.up().getName());
|
||||
DelegateReceiver delegateReceiver;
|
||||
JavacResolution reso = new JavacResolution(annotationNode.getContext());
|
||||
if (annotationNode.up().getKind() == Kind.FIELD) {
|
||||
delegateReceiver = DelegateReceiver.FIELD;
|
||||
delegateType = annotationNode.up().get().type;
|
||||
if (delegateType == null) reso.resolveClassMember(annotationNode.up());
|
||||
delegateType = annotationNode.up().get().type;
|
||||
} else if (annotationNode.up().getKind() == Kind.METHOD) {
|
||||
if (!(annotationNode.up().get() instanceof JCMethodDecl)) {
|
||||
annotationNode.addError("@Delegate is legal only on no-argument methods.");
|
||||
return;
|
||||
}
|
||||
JCMethodDecl methodDecl = (JCMethodDecl) annotationNode.up().get();
|
||||
if (!methodDecl.params.isEmpty()) {
|
||||
annotationNode.addError("@Delegate is legal only on no-argument methods.");
|
||||
return;
|
||||
}
|
||||
delegateReceiver = DelegateReceiver.METHOD;
|
||||
delegateType = methodDecl.restype.type;
|
||||
if (delegateType == null) reso.resolveClassMember(annotationNode.up());
|
||||
delegateType = methodDecl.restype.type;
|
||||
} else {
|
||||
// As the annotation is legal on fields and methods only, javac itself will take care of printing an error message for this.
|
||||
return;
|
||||
}
|
||||
|
||||
List<Object> delegateTypes = annotation.getActualExpressions("types");
|
||||
List<Object> excludeTypes = annotation.getActualExpressions("excludes");
|
||||
JavacResolution reso = new JavacResolution(annotationNode.getContext());
|
||||
List<Type> toDelegate = new ArrayList<Type>();
|
||||
List<Type> toExclude = new ArrayList<Type>();
|
||||
|
||||
if (delegateTypes.isEmpty()) {
|
||||
Type type = ((JCVariableDecl)annotationNode.up().get()).type;
|
||||
if (type == null) reso.resolveClassMember(annotationNode.up());
|
||||
//TODO I'm fairly sure the above line (and that entire method) does effectively bupkis!
|
||||
type = ((JCVariableDecl)annotationNode.up().get()).type;
|
||||
if (type != null) toDelegate.add(type);
|
||||
if (delegateType != null) toDelegate.add(delegateType);
|
||||
} else {
|
||||
for (Object dt : delegateTypes) {
|
||||
if (dt instanceof JCFieldAccess && ((JCFieldAccess)dt).name.toString().equals("class")) {
|
||||
@@ -167,15 +186,13 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
|
||||
}
|
||||
}
|
||||
|
||||
Name delegateFieldName = annotationNode.toName(annotationNode.up().getName());
|
||||
|
||||
for (MethodSig sig : signaturesToDelegate) generateAndAdd(sig, annotationNode, delegateFieldName);
|
||||
for (MethodSig sig : signaturesToDelegate) generateAndAdd(sig, annotationNode, delegateName, delegateReceiver);
|
||||
}
|
||||
|
||||
private void generateAndAdd(MethodSig sig, JavacNode annotation, Name delegateFieldName) {
|
||||
private void generateAndAdd(MethodSig sig, JavacNode annotation, Name delegateName, DelegateReceiver delegateReceiver) {
|
||||
List<JCMethodDecl> toAdd = new ArrayList<JCMethodDecl>();
|
||||
try {
|
||||
toAdd.add(createDelegateMethod(sig, annotation, delegateFieldName));
|
||||
toAdd.add(createDelegateMethod(sig, annotation, delegateName, delegateReceiver));
|
||||
} catch (TypeNotConvertibleException e) {
|
||||
annotation.addError("Can't create delegate method for " + sig.name + ": " + e.getMessage());
|
||||
return;
|
||||
@@ -240,7 +257,7 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
|
||||
}
|
||||
}
|
||||
|
||||
private JCMethodDecl createDelegateMethod(MethodSig sig, JavacNode annotation, Name delegateFieldName) throws TypeNotConvertibleException, CantMakeDelegates {
|
||||
private JCMethodDecl createDelegateMethod(MethodSig sig, JavacNode annotation, Name delegateName, DelegateReceiver delegateReceiver) throws TypeNotConvertibleException, CantMakeDelegates {
|
||||
/* public <T, U, ...> ReturnType methodName(ParamType1 name1, ParamType2 name2, ...) throws T1, T2, ... {
|
||||
* (return) delegate.<T, U>methodName(name1, name2);
|
||||
* }
|
||||
@@ -288,9 +305,7 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
|
||||
args.append(maker.Ident(name));
|
||||
}
|
||||
|
||||
JCExpression delegateFieldRef = maker.Select(maker.Ident(annotation.toName("this")), delegateFieldName);
|
||||
|
||||
JCExpression delegateCall = maker.Apply(toList(typeArgs), maker.Select(delegateFieldRef, sig.name), toList(args));
|
||||
JCExpression delegateCall = maker.Apply(toList(typeArgs), maker.Select(delegateReceiver.get(annotation, delegateName), sig.name), toList(args));
|
||||
JCStatement body = useReturn ? maker.Return(delegateCall) : maker.Exec(delegateCall);
|
||||
JCBlock bodyBlock = maker.Block(0, com.sun.tools.javac.util.List.of(body));
|
||||
|
||||
@@ -367,4 +382,22 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
|
||||
binding = types.erasure(binding);
|
||||
return binding.toString();
|
||||
}
|
||||
|
||||
private enum DelegateReceiver {
|
||||
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();
|
||||
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();
|
||||
return maker.Select(maker.Ident(node.toName("this")), name);
|
||||
}
|
||||
};
|
||||
|
||||
public abstract JCExpression get(final JavacNode node, final Name name);
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Delegate;
|
||||
import lombok.Getter;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.TransformationsUtil;
|
||||
@@ -240,16 +241,42 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
|
||||
List<JCAnnotation> nonNulls = findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN);
|
||||
List<JCAnnotation> nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN);
|
||||
|
||||
List<JCAnnotation> delegates = findDelegatesAndRemoveFromField(field);
|
||||
|
||||
List<JCAnnotation> annsOnMethod = nonNulls.appendList(nullables);
|
||||
|
||||
JCMethodDecl decl = recursiveSetGeneratedBy(treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType,
|
||||
methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source);
|
||||
|
||||
if (toClearOfMarkers != null) recursiveSetGeneratedBy(toClearOfMarkers, null);
|
||||
decl.mods.annotations = decl.mods.annotations.appendList(delegates);
|
||||
|
||||
return decl;
|
||||
}
|
||||
|
||||
private static List<JCAnnotation> findDelegatesAndRemoveFromField(JavacNode field) {
|
||||
JCVariableDecl fieldNode = (JCVariableDecl) field.get();
|
||||
|
||||
List<JCAnnotation> delegates = List.nil();
|
||||
for (JCAnnotation annotation : fieldNode.mods.annotations) {
|
||||
if (typeMatches(Delegate.class, field, annotation.annotationType)) {
|
||||
delegates = delegates.append(annotation);
|
||||
}
|
||||
}
|
||||
|
||||
if (!delegates.isEmpty()) {
|
||||
ListBuffer<JCAnnotation> withoutDelegates = ListBuffer.lb();
|
||||
for (JCAnnotation annotation : fieldNode.mods.annotations) {
|
||||
if (!delegates.contains(annotation)) {
|
||||
withoutDelegates.append(annotation);
|
||||
}
|
||||
}
|
||||
fieldNode.mods.annotations = withoutDelegates.toList();
|
||||
field.rebuild();
|
||||
}
|
||||
return delegates;
|
||||
}
|
||||
|
||||
private List<JCStatement> createSimpleGetterBody(TreeMaker treeMaker, JavacNode field) {
|
||||
return List.<JCStatement>of(treeMaker.Return(createFieldAccessor(treeMaker, field, FieldAccess.ALWAYS_FIELD)));
|
||||
}
|
||||
|
||||
@@ -123,9 +123,9 @@ public class EclipsePatcher extends Agent {
|
||||
"org.eclipse.jdt.core.dom.MethodDeclaration"
|
||||
))
|
||||
.methodToWrap(new Hook("org.eclipse.jface.text.IDocument", "get", "java.lang.String", "int", "int"))
|
||||
.wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "getRealMethodDeclarationSource", "java.lang.String", "java.lang.String", "org.eclipse.jdt.core.dom.MethodDeclaration"))
|
||||
.requestExtra(StackRequest.PARAM4)
|
||||
.build());
|
||||
.wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "getRealMethodDeclarationSource", "java.lang.String", "java.lang.String", "java.lang.Object", "org.eclipse.jdt.core.dom.MethodDeclaration"))
|
||||
.requestExtra(StackRequest.THIS, StackRequest.PARAM4)
|
||||
.transplant().build());
|
||||
|
||||
/* get real generated node in stead of a random one generated by the annotation */
|
||||
sm.addScript(ScriptBuilder.replaceMethodCall()
|
||||
@@ -133,21 +133,21 @@ public class EclipsePatcher extends Agent {
|
||||
.target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.ExtractInterfaceProcessor", "createMethodComments"))
|
||||
.methodToReplace(new Hook("org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil", "getMethodDeclarationNode", "org.eclipse.jdt.core.dom.MethodDeclaration", "org.eclipse.jdt.core.IMethod", "org.eclipse.jdt.core.dom.CompilationUnit"))
|
||||
.replacementMethod(new Hook("lombok.eclipse.agent.PatchFixes", "getRealMethodDeclarationNode", "org.eclipse.jdt.core.dom.MethodDeclaration", "org.eclipse.jdt.core.IMethod", "org.eclipse.jdt.core.dom.CompilationUnit"))
|
||||
.build());
|
||||
.transplant().build());
|
||||
|
||||
/* Do not add @Override's for generated methods */
|
||||
sm.addScript(ScriptBuilder.exitEarly()
|
||||
.target(new MethodTarget("org.eclipse.jdt.core.dom.rewrite.ListRewrite", "insertFirst"))
|
||||
.decisionMethod(new Hook("lombok.eclipse.agent.PatchFixes", "isListRewriteOnGeneratedNode", "boolean", "org.eclipse.jdt.core.dom.rewrite.ListRewrite"))
|
||||
.request(StackRequest.THIS)
|
||||
.build());
|
||||
.transplant().build());
|
||||
|
||||
/* Do not add comments for generated methods */
|
||||
sm.addScript(ScriptBuilder.exitEarly()
|
||||
.target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.ExtractInterfaceProcessor", "createMethodComment"))
|
||||
.decisionMethod(new Hook("lombok.eclipse.agent.PatchFixes", "isGenerated", "boolean", "org.eclipse.jdt.core.dom.ASTNode"))
|
||||
.request(StackRequest.PARAM2)
|
||||
.build());
|
||||
.transplant().build());
|
||||
}
|
||||
|
||||
private static void patchAboutDialog(ScriptManager sm) {
|
||||
@@ -395,14 +395,26 @@ public class EclipsePatcher extends Agent {
|
||||
.wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlag", "void",
|
||||
"org.eclipse.jdt.core.dom.ASTNode", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
|
||||
.transplant().build());
|
||||
|
||||
|
||||
sm.addScript(ScriptBuilder.wrapReturnValue()
|
||||
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertToFieldDeclaration", "org.eclipse.jdt.core.dom.FieldDeclaration", "org.eclipse.jdt.internal.compiler.ast.FieldDeclaration"))
|
||||
/* Targets beneath are only patched because the resulting dom nodes should be marked if generated.
|
||||
* However I couldn't find a usecase where these were actually used
|
||||
*/
|
||||
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertToType", "org.eclipse.jdt.core.dom.Type", "org.eclipse.jdt.internal.compiler.ast.NameReference"))
|
||||
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertType", "org.eclipse.jdt.core.dom.Type", "org.eclipse.jdt.internal.compiler.ast.TypeReference"))
|
||||
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertToVariableDeclarationExpression", "org.eclipse.jdt.core.dom.VariableDeclarationExpression", "org.eclipse.jdt.internal.compiler.ast.LocalDeclaration"))
|
||||
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertToSingleVariableDeclaration", "org.eclipse.jdt.core.dom.SingleVariableDeclaration", "org.eclipse.jdt.internal.compiler.ast.LocalDeclaration"))
|
||||
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertToVariableDeclarationFragment", "org.eclipse.jdt.core.dom.VariableDeclarationFragment", "org.eclipse.jdt.internal.compiler.ast.FieldDeclaration"))
|
||||
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertToVariableDeclarationFragment", "org.eclipse.jdt.core.dom.VariableDeclarationFragment", "org.eclipse.jdt.internal.compiler.ast.LocalDeclaration"))
|
||||
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertToVariableDeclarationStatement", "org.eclipse.jdt.core.dom.VariableDeclarationStatement", "org.eclipse.jdt.internal.compiler.ast.LocalDeclaration"))
|
||||
/* Targets above are only patched because the resulting dom nodes should be marked if generated. */
|
||||
.request(StackRequest.PARAM1, StackRequest.RETURN_VALUE)
|
||||
.wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlag", "void",
|
||||
"org.eclipse.jdt.core.dom.ASTNode", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
|
||||
.transplant().build());
|
||||
|
||||
/* Set generated flag for SimpleNames */
|
||||
sm.addScript(ScriptBuilder.wrapMethodCall()
|
||||
.target(new TargetMatcher() {
|
||||
@Override public boolean matches(String classSpec, String methodName, String descriptor) {
|
||||
@@ -420,16 +432,49 @@ public class EclipsePatcher extends Agent {
|
||||
}
|
||||
}).methodToWrap(new Hook("org.eclipse.jdt.core.dom.SimpleName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
|
||||
.requestExtra(StackRequest.PARAM1)
|
||||
.wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlagForSimpleName", "void",
|
||||
"org.eclipse.jdt.core.dom.SimpleName", "java.lang.Object"))
|
||||
.wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlagForName", "void",
|
||||
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
|
||||
.transplant().build());
|
||||
|
||||
sm.addScript(ScriptBuilder.wrapMethodCall()
|
||||
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.ASTNode", "boolean", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration"))
|
||||
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.SimpleName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
|
||||
.requestExtra(StackRequest.PARAM2)
|
||||
.wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlagForSimpleName", "void",
|
||||
"org.eclipse.jdt.core.dom.SimpleName", "java.lang.Object"))
|
||||
.wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlagForName", "void",
|
||||
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
|
||||
.transplant().build());
|
||||
|
||||
/* Set generated flag for QualifiedNames */
|
||||
sm.addScript(ScriptBuilder.wrapMethodCall()
|
||||
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "setQualifiedNameNameAndSourceRanges", "org.eclipse.jdt.core.dom.QualifiedName", "char[][]", "long[]", "int", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
|
||||
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.SimpleName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
|
||||
.requestExtra(StackRequest.PARAM4)
|
||||
.wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlagForName", "void",
|
||||
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
|
||||
.transplant().build());
|
||||
|
||||
sm.addScript(ScriptBuilder.wrapMethodCall()
|
||||
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "setQualifiedNameNameAndSourceRanges", "org.eclipse.jdt.core.dom.QualifiedName", "char[][]", "long[]", "int", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
|
||||
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.QualifiedName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
|
||||
.requestExtra(StackRequest.PARAM4)
|
||||
.wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlagForName", "void",
|
||||
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
|
||||
.transplant().build());
|
||||
|
||||
sm.addScript(ScriptBuilder.wrapMethodCall()
|
||||
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "setQualifiedNameNameAndSourceRanges", "org.eclipse.jdt.core.dom.QualifiedName", "char[][]", "long[]", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
|
||||
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.SimpleName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
|
||||
.requestExtra(StackRequest.PARAM3)
|
||||
.wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlagForName", "void",
|
||||
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
|
||||
.transplant().build());
|
||||
|
||||
sm.addScript(ScriptBuilder.wrapMethodCall()
|
||||
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "setQualifiedNameNameAndSourceRanges", "org.eclipse.jdt.core.dom.QualifiedName", "char[][]", "long[]", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
|
||||
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.QualifiedName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
|
||||
.requestExtra(StackRequest.PARAM3)
|
||||
.wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlagForName", "void",
|
||||
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
|
||||
.transplant().build());
|
||||
}
|
||||
|
||||
|
||||
@@ -103,25 +103,25 @@ public class PatchDelegate {
|
||||
return new String(decl.name);
|
||||
}
|
||||
|
||||
private static boolean hasDelegateMarkedFields(TypeDeclaration decl) {
|
||||
private static boolean hasDelegateMarkedFieldsOrMethods(TypeDeclaration decl) {
|
||||
if (decl.fields != null) for (FieldDeclaration field : decl.fields) {
|
||||
if (field.annotations == null) continue;
|
||||
for (Annotation ann : field.annotations) {
|
||||
if (ann.type == null) continue;
|
||||
TypeBinding tb = ann.type.resolveType(decl.initializerScope);
|
||||
if (tb == null) continue;
|
||||
if (!charArrayEquals("lombok", tb.qualifiedPackageName())) continue;
|
||||
if (!charArrayEquals("Delegate", tb.qualifiedSourceName())) continue;
|
||||
return true;
|
||||
if (isDelegate(ann, decl)) return true;
|
||||
}
|
||||
}
|
||||
if (decl.methods != null) for (AbstractMethodDeclaration method : decl.methods) {
|
||||
if (method.annotations == null) continue;
|
||||
for (Annotation ann : method.annotations) {
|
||||
if (isDelegate(ann, decl)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean handleDelegateForType(ClassScope scope) {
|
||||
if (TransformEclipseAST.disableLombok) return false;
|
||||
if (!hasDelegateMarkedFields(scope.referenceContext)) return false;
|
||||
if (!hasDelegateMarkedFieldsOrMethods(scope.referenceContext)) return false;
|
||||
|
||||
List<ClassScopeEntry> stack = visited.get();
|
||||
StringBuilder corrupted = null;
|
||||
@@ -145,16 +145,23 @@ public class PatchDelegate {
|
||||
stack.add(entry);
|
||||
|
||||
try {
|
||||
List<BindingTuple> methodsToDelegate = new ArrayList<BindingTuple>();
|
||||
TypeDeclaration decl = scope.referenceContext;
|
||||
if (decl != null) {
|
||||
CompilationUnitDeclaration cud = scope.compilationUnitScope().referenceContext;
|
||||
EclipseAST eclipseAst = TransformEclipseAST.getAST(cud, true);
|
||||
fillMethodBindings(cud, scope, methodsToDelegate);
|
||||
List<BindingTuple> methodsToDelegate = new ArrayList<BindingTuple>();
|
||||
fillMethodBindingsForFields(cud, scope, methodsToDelegate);
|
||||
if (entry.corruptedPath != null) {
|
||||
eclipseAst.get(scope.referenceContext).addError("No @Delegate methods created because there's a loop: " + entry.corruptedPath);
|
||||
} else {
|
||||
generateDelegateMethods(eclipseAst.get(decl), methodsToDelegate);
|
||||
generateDelegateMethods(eclipseAst.get(decl), methodsToDelegate, DelegateReceiver.FIELD);
|
||||
}
|
||||
methodsToDelegate.clear();
|
||||
fillMethodBindingsForMethods(cud, scope, methodsToDelegate);
|
||||
if (entry.corruptedPath != null) {
|
||||
eclipseAst.get(scope.referenceContext).addError("No @Delegate methods created because there's a loop: " + entry.corruptedPath);
|
||||
} else {
|
||||
generateDelegateMethods(eclipseAst.get(decl), methodsToDelegate, DelegateReceiver.METHOD);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
@@ -181,44 +188,29 @@ public class PatchDelegate {
|
||||
private static Map<ASTNode, Object> alreadyApplied = new WeakHashMap<ASTNode, Object>();
|
||||
private static final Object MARKER = new Object();
|
||||
|
||||
private static void fillMethodBindings(CompilationUnitDeclaration cud, ClassScope scope, List<BindingTuple> methodsToDelegate) {
|
||||
public static void markHandled(Annotation annotation) {
|
||||
alreadyApplied.put(annotation, MARKER);
|
||||
}
|
||||
|
||||
private static void fillMethodBindingsForFields(CompilationUnitDeclaration cud, ClassScope scope, List<BindingTuple> methodsToDelegate) {
|
||||
TypeDeclaration decl = scope.referenceContext;
|
||||
if (decl == null) return;
|
||||
|
||||
if (decl.fields != null) for (FieldDeclaration field : decl.fields) {
|
||||
if (field.annotations == null) continue;
|
||||
for (Annotation ann : field.annotations) {
|
||||
if (ann.type == null) continue;
|
||||
TypeBinding tb = ann.type.resolveType(decl.initializerScope);
|
||||
if (!charArrayEquals("lombok", tb.qualifiedPackageName())) continue;
|
||||
if (!charArrayEquals("Delegate", tb.qualifiedSourceName())) continue;
|
||||
if (!isDelegate(ann, decl)) continue;
|
||||
if (alreadyApplied.put(ann, MARKER) == MARKER) continue;
|
||||
|
||||
List<ClassLiteralAccess> rawTypes = new ArrayList<ClassLiteralAccess>();
|
||||
List<ClassLiteralAccess> excludedRawTypes = new ArrayList<ClassLiteralAccess>();
|
||||
for (MemberValuePair pair : ann.memberValuePairs()) {
|
||||
if (charArrayEquals("types", pair.name)) {
|
||||
if (pair.value instanceof ArrayInitializer) {
|
||||
for (Expression expr : ((ArrayInitializer)pair.value).expressions) {
|
||||
if (expr instanceof ClassLiteralAccess) rawTypes.add((ClassLiteralAccess) expr);
|
||||
}
|
||||
}
|
||||
if (pair.value instanceof ClassLiteralAccess) {
|
||||
rawTypes.add((ClassLiteralAccess) pair.value);
|
||||
}
|
||||
}
|
||||
if (charArrayEquals("excludes", pair.name)) {
|
||||
if (pair.value instanceof ArrayInitializer) {
|
||||
for (Expression expr : ((ArrayInitializer)pair.value).expressions) {
|
||||
if (expr instanceof ClassLiteralAccess) excludedRawTypes.add((ClassLiteralAccess) expr);
|
||||
}
|
||||
}
|
||||
if (pair.value instanceof ClassLiteralAccess) {
|
||||
excludedRawTypes.add((ClassLiteralAccess) pair.value);
|
||||
}
|
||||
}
|
||||
if ((field.modifiers & ClassFileConstants.AccStatic) != 0) {
|
||||
EclipseAST eclipseAst = TransformEclipseAST.getAST(cud, true);
|
||||
eclipseAst.get(ann).addError(LEGALITY_OF_DELEGATE);
|
||||
break;
|
||||
}
|
||||
|
||||
List<ClassLiteralAccess> rawTypes = rawTypes(ann, "types");
|
||||
List<ClassLiteralAccess> excludedRawTypes = rawTypes(ann, "excludes");
|
||||
|
||||
List<BindingTuple> methodsToExclude = new ArrayList<BindingTuple>();
|
||||
for (ClassLiteralAccess cla : excludedRawTypes) {
|
||||
addAllMethodBindings(methodsToExclude, cla.type.resolveType(decl.initializerScope), new HashSet<String>(), field.name, ann);
|
||||
@@ -251,6 +243,96 @@ public class PatchDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
private static final String LEGALITY_OF_DELEGATE = "@Delegate is legal only on instance fields or no-argument instance methods.";
|
||||
|
||||
private static void fillMethodBindingsForMethods(CompilationUnitDeclaration cud, ClassScope scope, List<BindingTuple> methodsToDelegate) {
|
||||
TypeDeclaration decl = scope.referenceContext;
|
||||
if (decl == null) return;
|
||||
|
||||
if (decl.methods != null) for (AbstractMethodDeclaration methodDecl : decl.methods) {
|
||||
if (methodDecl.annotations == null) continue;
|
||||
for (Annotation ann : methodDecl.annotations) {
|
||||
if (!isDelegate(ann, decl)) continue;
|
||||
if (alreadyApplied.put(ann, MARKER) == MARKER) continue;
|
||||
if (!(methodDecl instanceof MethodDeclaration)) {
|
||||
EclipseAST eclipseAst = TransformEclipseAST.getAST(cud, true);
|
||||
eclipseAst.get(ann).addError(LEGALITY_OF_DELEGATE);
|
||||
break;
|
||||
}
|
||||
if (methodDecl.arguments != null) {
|
||||
EclipseAST eclipseAst = TransformEclipseAST.getAST(cud, true);
|
||||
eclipseAst.get(ann).addError(LEGALITY_OF_DELEGATE);
|
||||
break;
|
||||
}
|
||||
if ((methodDecl.modifiers & ClassFileConstants.AccStatic) != 0) {
|
||||
EclipseAST eclipseAst = TransformEclipseAST.getAST(cud, true);
|
||||
eclipseAst.get(ann).addError(LEGALITY_OF_DELEGATE);
|
||||
break;
|
||||
}
|
||||
MethodDeclaration method = (MethodDeclaration) methodDecl;
|
||||
|
||||
List<ClassLiteralAccess> rawTypes = rawTypes(ann, "types");
|
||||
List<ClassLiteralAccess> excludedRawTypes = rawTypes(ann, "excludes");
|
||||
|
||||
List<BindingTuple> methodsToExclude = new ArrayList<BindingTuple>();
|
||||
for (ClassLiteralAccess cla : excludedRawTypes) {
|
||||
addAllMethodBindings(methodsToExclude, cla.type.resolveType(decl.initializerScope), new HashSet<String>(), method.selector, ann);
|
||||
}
|
||||
|
||||
Set<String> banList = new HashSet<String>();
|
||||
for (BindingTuple excluded : methodsToExclude) banList.add(printSig(excluded.parameterized));
|
||||
|
||||
List<BindingTuple> methodsToDelegateForThisAnn = new ArrayList<BindingTuple>();
|
||||
|
||||
if (rawTypes.isEmpty()) {
|
||||
if (method.returnType == null) continue;
|
||||
addAllMethodBindings(methodsToDelegateForThisAnn, method.returnType.resolveType(decl.initializerScope), banList, method.selector, ann);
|
||||
} else {
|
||||
for (ClassLiteralAccess cla : rawTypes) {
|
||||
addAllMethodBindings(methodsToDelegateForThisAnn, cla.type.resolveType(decl.initializerScope), banList, method.selector, ann);
|
||||
}
|
||||
}
|
||||
|
||||
// Not doing this right now because of problems - see commented-out-method for info.
|
||||
// removeExistingMethods(methodsToDelegate, decl, scope);
|
||||
|
||||
String dupe = containsDuplicates(methodsToDelegateForThisAnn);
|
||||
if (dupe != null) {
|
||||
EclipseAST eclipseAst = TransformEclipseAST.getAST(cud, true);
|
||||
eclipseAst.get(ann).addError("The method '" + dupe + "' is being delegated by more than one specified type.");
|
||||
} else {
|
||||
methodsToDelegate.addAll(methodsToDelegateForThisAnn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDelegate(Annotation ann, TypeDeclaration decl) {
|
||||
if (ann.type == null) return false;
|
||||
TypeBinding tb = ann.type.resolveType(decl.initializerScope);
|
||||
if (tb == null) return false;
|
||||
if (!charArrayEquals("lombok", tb.qualifiedPackageName())) return false;
|
||||
if (!charArrayEquals("Delegate", tb.qualifiedSourceName())) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static List<ClassLiteralAccess> rawTypes(Annotation ann, String name) {
|
||||
List<ClassLiteralAccess> rawTypes = new ArrayList<ClassLiteralAccess>();
|
||||
for (MemberValuePair pair : ann.memberValuePairs()) {
|
||||
if (charArrayEquals(name, pair.name)) {
|
||||
if (pair.value instanceof ArrayInitializer) {
|
||||
for (Expression expr : ((ArrayInitializer)pair.value).expressions) {
|
||||
if (expr instanceof ClassLiteralAccess) rawTypes.add((ClassLiteralAccess) expr);
|
||||
}
|
||||
}
|
||||
if (pair.value instanceof ClassLiteralAccess) {
|
||||
rawTypes.add((ClassLiteralAccess) pair.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rawTypes;
|
||||
}
|
||||
|
||||
/*
|
||||
* We may someday finish this method. Steps to be completed:
|
||||
*
|
||||
@@ -321,11 +403,11 @@ public class PatchDelegate {
|
||||
// }
|
||||
// }
|
||||
|
||||
private static void generateDelegateMethods(EclipseNode typeNode, List<BindingTuple> methods) {
|
||||
private static void generateDelegateMethods(EclipseNode typeNode, List<BindingTuple> methods, DelegateReceiver delegateReceiver) {
|
||||
CompilationUnitDeclaration top = (CompilationUnitDeclaration) typeNode.top().get();
|
||||
for (BindingTuple pair : methods) {
|
||||
EclipseNode annNode = typeNode.getAst().get(pair.responsible);
|
||||
MethodDeclaration method = createDelegateMethod(pair.fieldName, typeNode, pair, top.compilationResult, annNode);
|
||||
MethodDeclaration method = createDelegateMethod(pair.fieldName, typeNode, pair, top.compilationResult, annNode, delegateReceiver);
|
||||
if (method != null) {
|
||||
SetGeneratedByVisitor visitor = new SetGeneratedByVisitor(annNode.get());
|
||||
method.traverse(visitor, ((TypeDeclaration)typeNode.get()).scope);
|
||||
@@ -473,7 +555,7 @@ public class PatchDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodDeclaration createDelegateMethod(char[] name, EclipseNode typeNode, BindingTuple pair, CompilationResult compilationResult, EclipseNode annNode) {
|
||||
private static MethodDeclaration createDelegateMethod(char[] name, EclipseNode typeNode, BindingTuple pair, CompilationResult compilationResult, EclipseNode annNode, DelegateReceiver delegateReceiver) {
|
||||
/* public <T, U, ...> ReturnType methodName(ParamType1 name1, ParamType2 name2, ...) throws T1, T2, ... {
|
||||
* (return) delegate.<T, U>methodName(name1, name2);
|
||||
* }
|
||||
@@ -514,11 +596,7 @@ public class PatchDelegate {
|
||||
call.sourceStart = pS; call.sourceEnd = pE;
|
||||
call.nameSourcePosition = pos(source);
|
||||
setGeneratedBy(call, source);
|
||||
FieldReference fieldRef = new FieldReference(name, pos(source));
|
||||
fieldRef.receiver = new ThisReference(pS, pE);
|
||||
setGeneratedBy(fieldRef, source);
|
||||
setGeneratedBy(fieldRef.receiver, source);
|
||||
call.receiver = fieldRef;
|
||||
call.receiver = delegateReceiver.get(source, name);
|
||||
call.selector = binding.selector;
|
||||
|
||||
if (binding.typeVariables != null && binding.typeVariables.length > 0) {
|
||||
@@ -742,7 +820,31 @@ public class PatchDelegate {
|
||||
if (s.length() != c.length) return false;
|
||||
for (int i = 0; i < s.length(); i++) if (s.charAt(i) != c[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private enum DelegateReceiver {
|
||||
METHOD {
|
||||
public Expression get(final ASTNode source, char[] name) {
|
||||
MessageSend call = new MessageSend();
|
||||
call.sourceStart = source.sourceStart; call.sourceEnd = source.sourceEnd;
|
||||
call.nameSourcePosition = pos(source);
|
||||
setGeneratedBy(call, source);
|
||||
call.selector = name;
|
||||
call.receiver = new ThisReference(source.sourceStart, source.sourceEnd);
|
||||
setGeneratedBy(call.receiver, source);
|
||||
return call;
|
||||
}
|
||||
},
|
||||
FIELD {
|
||||
public Expression get(final ASTNode source, char[] name) {
|
||||
FieldReference fieldRef = new FieldReference(name, pos(source));
|
||||
setGeneratedBy(fieldRef, source);
|
||||
fieldRef.receiver = new ThisReference(source.sourceStart, source.sourceEnd);
|
||||
setGeneratedBy(fieldRef.receiver, source);
|
||||
return fieldRef;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public abstract Expression get(final ASTNode source, char[] name);
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package lombok.eclipse.agent;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
@@ -91,17 +90,23 @@ public class PatchFixes {
|
||||
return list;
|
||||
}
|
||||
|
||||
/* Very practical implementation, but works for getter and setter even with type parameters */
|
||||
public static java.lang.String getRealMethodDeclarationSource(java.lang.String original, org.eclipse.jdt.core.dom.MethodDeclaration declaration) {
|
||||
public static java.lang.String getRealMethodDeclarationSource(java.lang.String original, Object processor, org.eclipse.jdt.core.dom.MethodDeclaration declaration) throws Exception {
|
||||
if (!isGenerated(declaration)) return original;
|
||||
|
||||
List<org.eclipse.jdt.core.dom.Annotation> annotations = new ArrayList<org.eclipse.jdt.core.dom.Annotation>();
|
||||
for (Object modifier : declaration.modifiers()) {
|
||||
if (modifier instanceof org.eclipse.jdt.core.dom.Annotation) {
|
||||
org.eclipse.jdt.core.dom.Annotation annotation = (org.eclipse.jdt.core.dom.Annotation)modifier;
|
||||
String qualifiedAnnotationName = annotation.resolveTypeBinding().getQualifiedName();
|
||||
if (!"java.lang.Override".equals(qualifiedAnnotationName) && !"java.lang.SuppressWarnings".equals(qualifiedAnnotationName)) annotations.add(annotation);
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder signature = new StringBuilder();
|
||||
addAnnotations(annotations, signature);
|
||||
|
||||
// We should get these from the refactor action
|
||||
boolean needsPublic = true, needsAbstract = true;
|
||||
|
||||
if (needsPublic) signature.append("public ");
|
||||
if (needsAbstract) signature.append("abstract ");
|
||||
if ((Boolean)processor.getClass().getDeclaredField("fPublic").get(processor)) signature.append("public ");
|
||||
if ((Boolean)processor.getClass().getDeclaredField("fAbstract").get(processor)) signature.append("abstract ");
|
||||
|
||||
signature
|
||||
.append(declaration.getReturnType2().toString())
|
||||
@@ -112,9 +117,7 @@ public class PatchFixes {
|
||||
for (Object parameter : declaration.parameters()) {
|
||||
if (!first) signature.append(", ");
|
||||
first = false;
|
||||
// The annotations are still missing
|
||||
// Note: what happens to imports for the annotations?
|
||||
// I assume they have been taken care of by the default extraction system
|
||||
// We should also add the annotations of the parameters
|
||||
signature.append(parameter);
|
||||
}
|
||||
|
||||
@@ -122,6 +125,47 @@ public class PatchFixes {
|
||||
return signature.toString();
|
||||
}
|
||||
|
||||
// part of getRealMethodDeclarationSource(...)
|
||||
public static void addAnnotations(List<org.eclipse.jdt.core.dom.Annotation> annotations, StringBuilder signature) {
|
||||
/*
|
||||
* We SHOULD be able to handle the following cases:
|
||||
* @Override
|
||||
* @Override()
|
||||
* @SuppressWarnings("all")
|
||||
* @SuppressWarnings({"all", "unused"})
|
||||
* @SuppressWarnings(value = "all")
|
||||
* @SuppressWarnings(value = {"all", "unused"})
|
||||
* @EqualsAndHashCode(callSuper=true, of="id")
|
||||
*
|
||||
* Currently, we only seem to correctly support:
|
||||
* @Override
|
||||
* @Override() N.B. We lose the parentheses here, since there are no values. No big deal.
|
||||
* @SuppressWarnings("all")
|
||||
*/
|
||||
for (org.eclipse.jdt.core.dom.Annotation annotation : annotations) {
|
||||
List<String> values = new ArrayList<String>();
|
||||
if (annotation.isSingleMemberAnnotation()) {
|
||||
org.eclipse.jdt.core.dom.SingleMemberAnnotation smAnn = (org.eclipse.jdt.core.dom.SingleMemberAnnotation) annotation;
|
||||
values.add(smAnn.getValue().toString());
|
||||
} else if (annotation.isNormalAnnotation()) {
|
||||
org.eclipse.jdt.core.dom.NormalAnnotation normalAnn = (org.eclipse.jdt.core.dom.NormalAnnotation) annotation;
|
||||
for (Object value : normalAnn.values()) values.add(value.toString());
|
||||
}
|
||||
|
||||
signature.append("@").append(annotation.resolveTypeBinding().getQualifiedName());
|
||||
if (!values.isEmpty()) {
|
||||
signature.append("(");
|
||||
boolean first = true;
|
||||
for (String string : values) {
|
||||
if (!first) signature.append(", ");
|
||||
first = false;
|
||||
signature.append('"').append(string).append('"');
|
||||
}
|
||||
signature.append(")");
|
||||
}
|
||||
signature.append(" ");
|
||||
}
|
||||
}
|
||||
|
||||
public static org.eclipse.jdt.core.dom.MethodDeclaration getRealMethodDeclarationNode(org.eclipse.jdt.core.IMethod sourceMethod, org.eclipse.jdt.core.dom.CompilationUnit cuUnit) throws JavaModelException {
|
||||
MethodDeclaration methodDeclarationNode = ASTNodeSearchUtil.getMethodDeclarationNode(sourceMethod, cuUnit);
|
||||
@@ -154,7 +198,8 @@ public class PatchFixes {
|
||||
return methodDeclarationNode;
|
||||
}
|
||||
|
||||
private static org.eclipse.jdt.core.dom.AbstractTypeDeclaration findTypeDeclaration(IType searchType, List<?> nodes) {
|
||||
// part of getRealMethodDeclarationNode
|
||||
public static org.eclipse.jdt.core.dom.AbstractTypeDeclaration findTypeDeclaration(IType searchType, List<?> nodes) {
|
||||
for (Object object : nodes) {
|
||||
if (object instanceof org.eclipse.jdt.core.dom.AbstractTypeDeclaration) {
|
||||
org.eclipse.jdt.core.dom.AbstractTypeDeclaration typeDeclaration = (org.eclipse.jdt.core.dom.AbstractTypeDeclaration) object;
|
||||
@@ -188,7 +233,8 @@ public class PatchFixes {
|
||||
}
|
||||
|
||||
public static int fixRetrieveRightBraceOrSemiColonPosition(int original, int end) {
|
||||
return original == -1 ? end : original;
|
||||
// return original;
|
||||
return original == -1 ? end : original; // Need to fix: see issue 325.
|
||||
}
|
||||
|
||||
public static final int ALREADY_PROCESSED_FLAG = 0x800000; //Bit 24
|
||||
@@ -212,7 +258,7 @@ public class PatchFixes {
|
||||
}
|
||||
}
|
||||
|
||||
public static void setIsGeneratedFlagForSimpleName(SimpleName name, Object internalNode) throws Exception {
|
||||
public static void setIsGeneratedFlagForName(org.eclipse.jdt.core.dom.Name name, Object internalNode) throws Exception {
|
||||
if (internalNode instanceof org.eclipse.jdt.internal.compiler.ast.ASTNode) {
|
||||
if (internalNode.getClass().getField("$generatedBy").get(internalNode) != null) {
|
||||
name.getClass().getField("$isGenerated").set(name, true);
|
||||
@@ -258,9 +304,9 @@ public class PatchFixes {
|
||||
public static IMethod[] removeGeneratedMethods(IMethod[] methods) throws Exception {
|
||||
List<IMethod> result = new ArrayList<IMethod>();
|
||||
for (IMethod m : methods) {
|
||||
if (m.getNameRange().getLength() > 0) result.add(m);
|
||||
if (m.getNameRange().getLength() > 0 && !m.getNameRange().equals(m.getSourceRange())) result.add(m);
|
||||
}
|
||||
return result.size() == methods.length ? methods : result.toArray(new IMethod[0]);
|
||||
return result.size() == methods.length ? methods : result.toArray(new IMethod[result.size()]);
|
||||
}
|
||||
|
||||
public static SimpleName[] removeGeneratedSimpleNames(SimpleName[] in) throws Exception {
|
||||
|
||||
@@ -43,6 +43,7 @@ import org.eclipse.jdt.internal.compiler.ast.TypeReference;
|
||||
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
|
||||
|
||||
public class Eclipse {
|
||||
private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY = new Annotation[0];
|
||||
/**
|
||||
* Eclipse's Parser class is instrumented to not attempt to fill in the body of any method or initializer
|
||||
* or field initialization if this flag is set. Set it on the flag field of
|
||||
@@ -120,7 +121,7 @@ public class Eclipse {
|
||||
*/
|
||||
public static Annotation[] findAnnotations(FieldDeclaration field, Pattern namePattern) {
|
||||
List<Annotation> result = new ArrayList<Annotation>();
|
||||
if (field.annotations == null) return new Annotation[0];
|
||||
if (field.annotations == null) return EMPTY_ANNOTATIONS_ARRAY;
|
||||
for (Annotation annotation : field.annotations) {
|
||||
TypeReference typeRef = annotation.type;
|
||||
if (typeRef != null && typeRef.getTypeName()!= null) {
|
||||
@@ -131,7 +132,7 @@ public class Eclipse {
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toArray(new Annotation[0]);
|
||||
return result.toArray(EMPTY_ANNOTATIONS_ARRAY);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
public class Foo implements java.util.RandomAccess {
|
||||
private static final long LONG = 123L;
|
||||
private static final String ONE = "Eén";
|
||||
private static final long LONG_OVERFLOW = 0x1FFFFFFFFL;
|
||||
private static final String ONE = "E\u00e9n";
|
||||
private static final int INT = 123;
|
||||
private static final double DOUBLE = 1.23;
|
||||
private static final double DOUBLE_NAN = Double.NaN;
|
||||
|
||||
@@ -169,6 +169,7 @@ public class TestClassFileMetaData {
|
||||
@Test
|
||||
public void testContainsLong() {
|
||||
assertTrue(foo.containsLong(123));
|
||||
assertTrue(foo.containsLong(0x1FFFFFFFFL));
|
||||
|
||||
assertFalse(foo.containsLong(1));
|
||||
assertFalse(buux.containsLong(1));
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
class DelegateOnGetter {
|
||||
private final java.util.concurrent.atomic.AtomicReference<java.util.concurrent.atomic.AtomicReference<Bar>> bar = new java.util.concurrent.atomic.AtomicReference<java.util.concurrent.atomic.AtomicReference<Bar>>();
|
||||
private interface Bar {
|
||||
void setList(java.util.ArrayList<java.lang.String> list);
|
||||
int getInt();
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public Bar getBar() {
|
||||
java.util.concurrent.atomic.AtomicReference<Bar> value = this.bar.get();
|
||||
if (value == null) {
|
||||
synchronized (this.bar) {
|
||||
value = this.bar.get();
|
||||
if (value == null) {
|
||||
value = new java.util.concurrent.atomic.AtomicReference<Bar>(new Bar(){
|
||||
public void setList(java.util.ArrayList<String> list) {
|
||||
}
|
||||
public int getInt() {
|
||||
return 42;
|
||||
}
|
||||
});
|
||||
this.bar.set(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value.get();
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public void setList(final java.util.ArrayList<java.lang.String> list) {
|
||||
this.getBar().setList(list);
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public int getInt() {
|
||||
return this.getBar().getInt();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
class DelegateOnGetterNone {
|
||||
private final Bar bar;
|
||||
private interface Bar {
|
||||
void setList(java.util.ArrayList<java.lang.String> list);
|
||||
int getInt();
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public void setList(final java.util.ArrayList<java.lang.String> list) {
|
||||
this.bar.setList(list);
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public int getInt() {
|
||||
return this.bar.getInt();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
abstract class DelegateOnMethods {
|
||||
public abstract Bar getBar();
|
||||
|
||||
public static interface Bar {
|
||||
void bar(java.util.ArrayList<java.lang.String> list);
|
||||
}
|
||||
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public void bar(final java.util.ArrayList<java.lang.String> list) {
|
||||
this.getBar().bar(list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class GetterNone {
|
||||
int i;
|
||||
int foo;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public int getI() {
|
||||
return this.i;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
//ignore
|
||||
@@ -0,0 +1 @@
|
||||
//ignore
|
||||
@@ -0,0 +1 @@
|
||||
//ignore
|
||||
@@ -0,0 +1,12 @@
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
@Getter class GetterNone {
|
||||
int i;
|
||||
@Getter(AccessLevel.NONE) int foo;
|
||||
public @java.lang.SuppressWarnings("all") int getI() {
|
||||
return this.i;
|
||||
}
|
||||
GetterNone() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import lombok.Delegate;
|
||||
import lombok.Getter;
|
||||
class DelegateOnGetter {
|
||||
private interface Bar {
|
||||
void setList(java.util.ArrayList<java.lang.String> list);
|
||||
int getInt();
|
||||
}
|
||||
private final @Delegate @Getter(lazy = true) java.util.concurrent.atomic.AtomicReference<java.util.concurrent.atomic.AtomicReference<Bar>> bar = new java.util.concurrent.atomic.AtomicReference<java.util.concurrent.atomic.AtomicReference<Bar>>();
|
||||
public @Delegate @java.lang.SuppressWarnings("all") Bar getBar() {
|
||||
java.util.concurrent.atomic.AtomicReference<Bar> value = this.bar.get();
|
||||
if ((value == null))
|
||||
{
|
||||
synchronized (this.bar)
|
||||
{
|
||||
value = this.bar.get();
|
||||
if ((value == null))
|
||||
{
|
||||
value = new java.util.concurrent.atomic.AtomicReference<Bar>(new Bar() {
|
||||
public void setList(java.util.ArrayList<String> list) {
|
||||
}
|
||||
public int getInt() {
|
||||
return 42;
|
||||
}
|
||||
});
|
||||
this.bar.set(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value.get();
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") int getInt() {
|
||||
return this.getBar().getInt();
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") void setList(final java.util.ArrayList<java.lang.String> list) {
|
||||
this.getBar().setList(list);
|
||||
}
|
||||
DelegateOnGetter() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Delegate;
|
||||
import lombok.Getter;
|
||||
@Getter class DelegateOnGetterNone {
|
||||
private interface Bar {
|
||||
void setList(java.util.ArrayList<java.lang.String> list);
|
||||
int getInt();
|
||||
}
|
||||
private final @Delegate @Getter(AccessLevel.NONE) Bar bar;
|
||||
public @java.lang.SuppressWarnings("all") int getInt() {
|
||||
return this.bar.getInt();
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") void setList(final java.util.ArrayList<java.lang.String> list) {
|
||||
this.bar.setList(list);
|
||||
}
|
||||
DelegateOnGetterNone() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import lombok.Delegate;
|
||||
abstract class DelegateOnMethods {
|
||||
public static interface Bar {
|
||||
void bar(java.util.ArrayList<java.lang.String> list);
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") void bar(final java.util.ArrayList<java.lang.String> list) {
|
||||
this.getBar().bar(list);
|
||||
}
|
||||
DelegateOnMethods() {
|
||||
super();
|
||||
}
|
||||
public abstract @Delegate Bar getBar();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
@Getter class GetterNone {
|
||||
int i;
|
||||
@Getter(AccessLevel.NONE) int foo;
|
||||
public @java.lang.SuppressWarnings("all") int getI() {
|
||||
return this.i;
|
||||
}
|
||||
GetterNone() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import lombok.Delegate;
|
||||
import lombok.Getter;
|
||||
|
||||
class DelegateOnGetter {
|
||||
|
||||
@Delegate @Getter(lazy=true) private final Bar bar = new Bar() {
|
||||
public void setList(java.util.ArrayList<String> list) {
|
||||
}
|
||||
public int getInt() {
|
||||
return 42;
|
||||
}
|
||||
};
|
||||
|
||||
private interface Bar {
|
||||
void setList(java.util.ArrayList<java.lang.String> list);
|
||||
int getInt();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Delegate;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
class DelegateOnGetterNone {
|
||||
|
||||
@Delegate @Getter(AccessLevel.NONE) private final Bar bar;
|
||||
|
||||
private interface Bar {
|
||||
void setList(java.util.ArrayList<java.lang.String> list);
|
||||
int getInt();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import lombok.Delegate;
|
||||
|
||||
abstract class DelegateOnMethods {
|
||||
|
||||
@Delegate
|
||||
public abstract Bar getBar();
|
||||
|
||||
public static interface Bar {
|
||||
void bar(java.util.ArrayList<java.lang.String> list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
class GetterNone {
|
||||
int i;
|
||||
@Getter(AccessLevel.NONE) int foo;
|
||||
}
|
||||
@@ -15,20 +15,20 @@
|
||||
<div class="overview">
|
||||
<h3>Overview</h3>
|
||||
<p>
|
||||
<em> NEW IN Lombok 0.10: </em> Any field can be annotated with <code>@Delegate</code> to let lombok generate delegate methods that forward the call
|
||||
to this field.
|
||||
<em> NEW IN Lombok 0.10: </em> Any field or no-argument method can be annotated with <code>@Delegate</code> to let lombok generate delegate methods
|
||||
that forward the call to this field (or the result of invoking this method).
|
||||
</p>
|
||||
<p>
|
||||
Lombok delegates all <code>public</code> methods of the field's type, as well as those of its supertype except for all methods declared
|
||||
in <code>java.lang.Object</code>.
|
||||
Lombok delegates all <code>public</code> methods of the field's type (or method's return type), as well as those of its supertype except for all
|
||||
methods declared in <code>java.lang.Object</code>.
|
||||
</p>
|
||||
<p>
|
||||
You can pass any number of classes into the <code>@Delegate</code> annotation's <code>types</code> parameter.
|
||||
If you do that, then lombok will delegate all <code>public</code> methods in those types (and their supertypes, except
|
||||
<code>java.lang.Object</code>) instead of looking at the field's type.
|
||||
<code>java.lang.Object</code>) instead of looking at the field/method's type.
|
||||
</p>
|
||||
<p>
|
||||
All public non-Object methods that are part of the field's type (or, if you used <code>types</code> parameter, the methods of those types) are
|
||||
All public non-<code>Object</code> methods that are part of the calculated type(s) are
|
||||
copied, whether or not you also wrote implementations for those methods. That would thus result in duplicate method errors. You can avoid these
|
||||
by using the <code>@Delegate(excludes=SomeType.class)</code> parameter to exclude all public methods in the excluded type(s), and their supertypes.
|
||||
</p>
|
||||
@@ -59,6 +59,8 @@
|
||||
<p>
|
||||
When passing classes to the annotation, these classes do not need to be supertypes of the field. See the example.
|
||||
</p>
|
||||
<p>
|
||||
<code>@Delegate</code> cannot be used on static fields or methods.
|
||||
<div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
|
||||
Reference in new issue
Block a user