mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-14 02:16:18 +00:00
Fix for issue 328: @Delegate on a field for which we also generate a getter will use the getter for delegation
This commit is contained in:
1 parent
3e7bb145d3
commit
2242de2bf9
8 files changed
+149
-4
No files matched your search
@@ -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) {
|
||||
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
@@ -188,6 +188,10 @@ public class PatchDelegate {
|
||||
private static Map<ASTNode, Object> alreadyApplied = new WeakHashMap<ASTNode, Object>();
|
||||
private static final Object MARKER = new Object();
|
||||
|
||||
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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 @@
|
||||
//ignore
|
||||
@@ -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,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();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user