diff options
author | Reinier Zwitserloot <r.zwitserloot@projectlombok.org> | 2021-04-18 05:45:28 +0200 |
---|---|---|
committer | Reinier Zwitserloot <r.zwitserloot@projectlombok.org> | 2021-04-18 05:45:28 +0200 |
commit | ba9ffce89841e6fdbec7c2d234c3a70a2db7f80d (patch) | |
tree | 9b2040710997bb1270a9c03b0a49b9f830621b86 | |
parent | 01702f70d063b7c7685f8c4de94e6d1718047390 (diff) | |
parent | 6782aceeb0bc082357bbd3ff20b166c379afb380 (diff) | |
download | lombok-ba9ffce89841e6fdbec7c2d234c3a70a2db7f80d.tar.gz lombok-ba9ffce89841e6fdbec7c2d234c3a70a2db7f80d.tar.bz2 lombok-ba9ffce89841e6fdbec7c2d234c3a70a2db7f80d.zip |
Merge branch 'enter-types-methods-fields' of git://github.com/Rawi01/lombok into Rawi01-enter-types-methods-fields
-rw-r--r-- | src/core/lombok/javac/handlers/HandleConstructor.java | 24 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleGetter.java | 3 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleSetter.java | 14 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleSuperBuilder.java | 2 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleUtilityClass.java | 5 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleWith.java | 7 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleWithBy.java | 7 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/JavacHandlerUtil.java | 190 | ||||
-rw-r--r-- | test/core/src/lombok/RunTestsViaDelombok.java | 59 |
9 files changed, 186 insertions, 125 deletions
diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java index 9c74ca0e..dc70e2ce 100644 --- a/src/core/lombok/javac/handlers/HandleConstructor.java +++ b/src/core/lombok/javac/handlers/HandleConstructor.java @@ -26,8 +26,6 @@ import static lombok.javac.Javac.*; import static lombok.javac.handlers.JavacHandlerUtil.*; import com.sun.tools.javac.code.Flags; -import com.sun.tools.javac.code.Symbol.ClassSymbol; -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.JCBlock; @@ -55,7 +53,6 @@ import lombok.core.AST.Kind; import lombok.core.AnnotationValues; import lombok.core.configuration.CheckerFrameworkVersion; import lombok.delombok.LombokOptionsFactory; -import lombok.javac.Javac; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; import lombok.javac.JavacTreeMaker; @@ -243,30 +240,17 @@ public class HandleConstructor { if (noArgs && noArgsConstructorExists(typeNode)) return; - ListBuffer<Type> argTypes = new ListBuffer<Type>(); - for (JavacNode fieldNode : fields) { - Type mirror = getMirrorForFieldType(fieldNode); - if (mirror == null) { - argTypes = null; - break; - } - argTypes.append(mirror); - } - List<Type> argTypes_ = argTypes == null ? null : argTypes.toList(); - if (!(skipIfConstructorExists != SkipIfConstructorExists.NO && constructorExists(typeNode) != MemberExistsResult.NOT_EXISTS)) { JCMethodDecl constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, onConstructor, typeNode, fields, allToDefault, source); - injectMethod(typeNode, constr, argTypes_, Javac.createVoidType(typeNode.getSymbolTable(), CTC_VOID)); + injectMethod(typeNode, constr); } - generateStaticConstructor(staticConstrRequired, typeNode, staticName, level, allToDefault, fields, source, argTypes_); + generateStaticConstructor(staticConstrRequired, typeNode, staticName, level, allToDefault, fields, source); } - private void generateStaticConstructor(boolean staticConstrRequired, JavacNode typeNode, String staticName, AccessLevel level, boolean allToDefault, List<JavacNode> fields, JavacNode source, List<Type> argTypes_) { + private void generateStaticConstructor(boolean staticConstrRequired, JavacNode typeNode, String staticName, AccessLevel level, boolean allToDefault, List<JavacNode> fields, JavacNode source) { if (staticConstrRequired) { - ClassSymbol sym = ((JCClassDecl) typeNode.get()).sym; - Type returnType = sym == null ? null : sym.type; JCMethodDecl staticConstr = createStaticConstructor(staticName, level, typeNode, allToDefault ? List.<JavacNode>nil() : fields, source); - injectMethod(typeNode, staticConstr, argTypes_, returnType); + injectMethod(typeNode, staticConstr); } } diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index 8f6de9bb..7a7e41f9 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -46,7 +46,6 @@ import lombok.javac.JavacTreeMaker.TypeTag; import lombok.spi.Provides; 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.JCBinary; @@ -214,7 +213,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC); - injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), source, lazy, onMethod), List.<Type>nil(), getMirrorForFieldType(fieldNode)); + injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), source, lazy, onMethod)); } public JCMethodDecl createGetter(long access, JavacNode field, JavacTreeMaker treeMaker, JavacNode source, boolean lazy, List<JCAnnotation> onMethod) { diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index 5c34f9f5..a0634494 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -40,8 +40,6 @@ import lombok.javac.JavacTreeMaker; import lombok.spi.Provides; import com.sun.tools.javac.code.Flags; -import com.sun.tools.javac.code.Symbol.ClassSymbol; -import com.sun.tools.javac.code.Type; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCAssign; import com.sun.tools.javac.tree.JCTree.JCBlock; @@ -184,17 +182,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC); JCMethodDecl createdSetter = createSetter(access, fieldNode, fieldNode.getTreeMaker(), sourceNode, onMethod, onParam); - Type fieldType = getMirrorForFieldType(fieldNode); - Type returnType; - - if (shouldReturnThis(fieldNode)) { - ClassSymbol sym = ((JCClassDecl) fieldNode.up().get()).sym; - returnType = sym == null ? null : sym.type; - } else { - returnType = Javac.createVoidType(fieldNode.getSymbolTable(), CTC_VOID); - } - - injectMethod(fieldNode.up(), createdSetter, fieldType == null ? null : List.of(fieldType), returnType); + injectMethod(fieldNode.up(), createdSetter); } public static JCMethodDecl createSetter(long access, JavacNode field, JavacTreeMaker treeMaker, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index 8974cd68..87b18576 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -583,7 +583,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(), maker.Block(0L, statements.toList()), null), job.sourceNode); - injectMethod(job.parentType, constr, null, Javac.createVoidType(job.builderType.getSymbolTable(), CTC_VOID)); + injectMethod(job.parentType, constr); } private JCMethodDecl generateBuilderMethod(SuperBuilderJob job) { diff --git a/src/core/lombok/javac/handlers/HandleUtilityClass.java b/src/core/lombok/javac/handlers/HandleUtilityClass.java index e006cc47..6fa630e2 100644 --- a/src/core/lombok/javac/handlers/HandleUtilityClass.java +++ b/src/core/lombok/javac/handlers/HandleUtilityClass.java @@ -22,11 +22,9 @@ package lombok.javac.handlers; import static lombok.core.handlers.HandlerUtil.handleExperimentalFlagUsage; -import static lombok.javac.Javac.CTC_VOID; import static lombok.javac.handlers.JavacHandlerUtil.*; import com.sun.tools.javac.code.Flags; -import com.sun.tools.javac.code.Type; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCClassDecl; @@ -44,7 +42,6 @@ import lombok.core.AST.Kind; import lombok.core.AnnotationValues; import lombok.core.HandlerPriority; import lombok.experimental.UtilityClass; -import lombok.javac.Javac; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; import lombok.javac.JavacTreeMaker; @@ -141,7 +138,7 @@ public class HandleUtilityClass extends JavacAnnotationHandler<UtilityClass> { JCBlock block = maker.Block(0L, createThrowStatement(typeNode, maker)); JCMethodDecl methodDef = maker.MethodDef(mods, name, null, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), block, null); JCMethodDecl constructor = recursiveSetGeneratedBy(methodDef, typeNode); - JavacHandlerUtil.injectMethod(typeNode, constructor, List.<Type>nil(), Javac.createVoidType(typeNode.getSymbolTable(), CTC_VOID)); + JavacHandlerUtil.injectMethod(typeNode, constructor); } private List<JCStatement> createThrowStatement(JavacNode typeNode, JavacTreeMaker maker) { diff --git a/src/core/lombok/javac/handlers/HandleWith.java b/src/core/lombok/javac/handlers/HandleWith.java index f914b4c7..47f78b1e 100644 --- a/src/core/lombok/javac/handlers/HandleWith.java +++ b/src/core/lombok/javac/handlers/HandleWith.java @@ -40,8 +40,6 @@ import lombok.javac.handlers.JavacHandlerUtil.CopyJavadoc; import lombok.spi.Provides; import com.sun.tools.javac.code.Flags; -import com.sun.tools.javac.code.Type; -import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCClassDecl; @@ -211,11 +209,8 @@ public class HandleWith extends JavacAnnotationHandler<With> { JCMethodDecl createdWith = createWith(access, fieldNode, fieldNode.getTreeMaker(), source, onMethod, onParam, makeAbstract); createRelevantNonNullAnnotation(fieldNode, createdWith); - ClassSymbol sym = ((JCClassDecl) fieldNode.up().get()).sym; - Type returnType = sym == null ? null : sym.type; - recursiveSetGeneratedBy(createdWith, source); - injectMethod(typeNode, createdWith, List.<Type>of(getMirrorForFieldType(fieldNode)), returnType); + injectMethod(typeNode, createdWith); } public JCMethodDecl createWith(long access, JavacNode field, JavacTreeMaker maker, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam, boolean makeAbstract) { diff --git a/src/core/lombok/javac/handlers/HandleWithBy.java b/src/core/lombok/javac/handlers/HandleWithBy.java index f1f953b3..4ba4337e 100644 --- a/src/core/lombok/javac/handlers/HandleWithBy.java +++ b/src/core/lombok/javac/handlers/HandleWithBy.java @@ -45,8 +45,6 @@ import lombok.spi.Provides; import com.sun.tools.javac.code.BoundKind; import com.sun.tools.javac.code.Flags; -import com.sun.tools.javac.code.Type; -import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCClassDecl; @@ -204,11 +202,8 @@ public class HandleWithBy extends JavacAnnotationHandler<WithBy> { long access = toJavacModifier(level); JCMethodDecl createdWithBy = createWithBy(access, fieldNode, fieldNode.getTreeMaker(), source, onMethod, makeAbstract); - ClassSymbol sym = ((JCClassDecl) fieldNode.up().get()).sym; - Type returnType = sym == null ? null : sym.type; - recursiveSetGeneratedBy(createdWithBy, source); - injectMethod(typeNode, createdWithBy, List.<Type>of(getMirrorForFieldType(fieldNode)), returnType); + injectMethod(typeNode, createdWithBy); } private static final LombokImmutableList<String> NAME_JUF_FUNCTION = LombokImmutableList.of("java", "util", "function", "Function"); diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 32eae4e9..fba13133 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -37,19 +37,19 @@ import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; -import javax.lang.model.element.Element; - import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.BoundKind; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Scope; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; -import com.sun.tools.javac.code.Symbol.MethodSymbol; -import com.sun.tools.javac.code.Symbol.VarSymbol; -import com.sun.tools.javac.code.Symtab; +import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.code.Type; -import com.sun.tools.javac.code.Type.MethodType; +import com.sun.tools.javac.comp.Annotate; +import com.sun.tools.javac.comp.AttrContext; +import com.sun.tools.javac.comp.Enter; +import com.sun.tools.javac.comp.Env; +import com.sun.tools.javac.comp.MemberEnter; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree; @@ -1010,12 +1010,6 @@ public class JavacHandlerUtil { return call; } - public static Type getMirrorForFieldType(JavacNode fieldNode) { - Element fieldElement = fieldNode.getElement(); - if (fieldElement instanceof VarSymbol) return ((VarSymbol) fieldElement).type; - return null; - } - /** * Adds the given new field declaration to the provided type AST Node. * The field carries the @{@link SuppressWarnings}("all") annotation. @@ -1071,6 +1065,8 @@ public class JavacHandlerUtil { insertAfter.tail = fieldEntry; } + EnterReflect.memberEnter(field, typeNode); + return typeNode.add(field, Kind.FIELD); } @@ -1148,19 +1144,30 @@ public class JavacHandlerUtil { } static class JCAnnotationReflect { - private static Field ATTRIBUTE; - + private static final Field ATTRIBUTE; + static { - try { - ATTRIBUTE = Permit.getField(JCAnnotation.class, "attribute"); - } catch (Exception ignore) {} + ATTRIBUTE = Permit.permissiveGetField(JCAnnotation.class, "attribute"); } static Attribute.Compound getAttribute(JCAnnotation jcAnnotation) { - try { - return (Attribute.Compound) ATTRIBUTE.get(jcAnnotation); - } catch (Exception e) { - return null; + if (ATTRIBUTE != null) { + try { + return (Attribute.Compound) ATTRIBUTE.get(jcAnnotation); + } catch (Exception e) { + // Ignore + } + } + return null; + } + + static void setAttribute(JCAnnotation jcAnnotation, Attribute.Compound attribute) { + if (ATTRIBUTE != null) { + try { + Permit.set(ATTRIBUTE, jcAnnotation, attribute); + } catch (Exception e) { + // Ignore + } } } } @@ -1204,8 +1211,10 @@ public class JavacHandlerUtil { } } - public static void injectMethod(JavacNode typeNode, JCMethodDecl method) { - injectMethod(typeNode, method, null, null); + + @Deprecated + public static void injectMethod(JavacNode typeNode, JCMethodDecl method, List<Type> paramTypes, Type returnType) { + injectMethod(typeNode, method); } /** @@ -1214,9 +1223,7 @@ public class JavacHandlerUtil { * * Also takes care of updating the JavacAST. */ - public static void injectMethod(JavacNode typeNode, JCMethodDecl method, List<Type> paramTypes, Type returnType) { - Context context = typeNode.getContext(); - Symtab symtab = Symtab.instance(context); + public static void injectMethod(JavacNode typeNode, JCMethodDecl method) { JCClassDecl type = (JCClassDecl) typeNode.get(); if (method.getName().contentEquals("<init>")) { @@ -1240,55 +1247,11 @@ public class JavacHandlerUtil { addGenerated(method.mods, typeNode, typeNode.getNodeFor(getGeneratedBy(method)), typeNode.getContext()); type.defs = type.defs.append(method); - List<Symbol.VarSymbol> params = null; - if (method.getParameters() != null && !method.getParameters().isEmpty()) { - ListBuffer<Symbol.VarSymbol> newParams = new ListBuffer<Symbol.VarSymbol>(); - for (int i = 0; i < method.getParameters().size(); i++) { - JCTree.JCVariableDecl param = method.getParameters().get(i); - if (param.sym == null) { - Type paramType = paramTypes == null ? param.getType().type : paramTypes.get(i); - VarSymbol varSymbol = new VarSymbol(param.mods.flags, param.name, paramType, symtab.noSymbol); - varSymbol.adr = 1 << i; - List<JCAnnotation> annotations = param.getModifiers().getAnnotations(); - if (annotations != null && !annotations.isEmpty()) { - ListBuffer<Attribute.Compound> newAnnotations = new ListBuffer<Attribute.Compound>(); - for (JCAnnotation jcAnnotation : annotations) { - Attribute.Compound attribute = JCAnnotationReflect.getAttribute(jcAnnotation); - if (attribute != null) { - newAnnotations.append(attribute); - } - } - if (annotations.length() == newAnnotations.length()) { - varSymbol.appendAttributes(newAnnotations.toList()); - } - } - newParams.append(varSymbol); - } else { - newParams.append(param.sym); - } - } - params = newParams.toList(); - if (params.length() != method.getParameters().length()) params = null; - } - - fixMethodMirror(typeNode.getContext(), typeNode.getElement(), method.getModifiers().flags, method.getName(), paramTypes, params, returnType); + EnterReflect.memberEnter(method, typeNode); typeNode.add(method, Kind.METHOD); } - private static void fixMethodMirror(Context context, Element typeMirror, long access, Name methodName, List<Type> paramTypes, List<Symbol.VarSymbol> params, Type returnType) { - if (typeMirror == null || paramTypes == null || returnType == null) return; - ClassSymbol cs = (ClassSymbol) typeMirror; - MethodSymbol methodSymbol = new MethodSymbol(access, methodName, new MethodType(paramTypes, returnType, List.<Type>nil(), Symtab.instance(context).methodClass), cs); - if (params != null && !params.isEmpty()) { - methodSymbol.params = params; - for (VarSymbol varSymbol : params) { - varSymbol.owner = methodSymbol; - } - } - ClassSymbolMembersField.enter(cs, methodSymbol); - } - /** * Adds an inner type (class, interface, enum) to the given type. Cannot inject top-level types. * @@ -1301,9 +1264,55 @@ public class JavacHandlerUtil { addSuppressWarningsAll(type.mods, typeNode, typeNode.getNodeFor(getGeneratedBy(type)), typeNode.getContext()); addGenerated(type.mods, typeNode, typeNode.getNodeFor(getGeneratedBy(type)), typeNode.getContext()); typeDecl.defs = typeDecl.defs.append(type); + + EnterReflect.classEnter(type, typeNode); + return typeNode.add(type, Kind.TYPE); } + static class EnterReflect { + private static final Method classEnter; + private static final Method memberEnter; + private static final Method blockAnnotations; + private static final Method unblockAnnotations; + + static { + classEnter = Permit.permissiveGetMethod(Enter.class, "classEnter", JCTree.class, Env.class); + memberEnter = Permit.permissiveGetMethod(MemberEnter.class, "memberEnter", JCTree.class, Env.class); + + Method block = Permit.permissiveGetMethod(Annotate.class, "blockAnnotations"); + if (block == null) block = Permit.permissiveGetMethod(Annotate.class, "enterStart"); + blockAnnotations = block; + + Method unblock = Permit.permissiveGetMethod(Annotate.class, "unblockAnnotations"); + if (unblock == null) unblock = Permit.permissiveGetMethod(Annotate.class, "enterDone"); + unblockAnnotations = unblock; + } + + static Type classEnter(JCTree tree, JavacNode parent) { + Enter enter = Enter.instance(parent.getContext()); + Env<AttrContext> classEnv = enter.getEnv((TypeSymbol) parent.getElement()); + Type type = (Type) Permit.invokeSneaky(classEnter, enter, tree, classEnv); + if (type == null) return null; + type.complete(); + return type; + } + + static void memberEnter(JCTree tree, JavacNode parent) { + Context context = parent.getContext(); + MemberEnter me = MemberEnter.instance(context); + Annotate annotate = Annotate.instance(context); + Enter enter = Enter.instance(context); + + Env<AttrContext> classEnv = enter.getEnv((TypeSymbol) parent.getElement()); + if (classEnv == null) return; + + Permit.invokeSneaky(blockAnnotations, annotate); + Permit.invokeSneaky(memberEnter, me, tree, classEnv); + Permit.invokeSneaky(unblockAnnotations, annotate); + } + } + public static long addFinalIfNeeded(long flags, Context context) { boolean addFinal = LombokOptionsFactory.getDelombokOptions(context).getFormatPreferences().generateFinalParams(); @@ -1802,10 +1811,49 @@ public class JavacHandlerUtil { addError(errorName, annotationNode); } } + for (JCAnnotation annotation : result) { + clearTypes(annotation); + } ast.args = params.toList(); return result.toList(); } + /** + * Removes all type information from the provided tree. + */ + private static void clearTypes(JCTree tree) { + tree.accept(new TreeScanner() { + @Override public void scan(JCTree tree) { + tree.type = null; + super.scan(tree); + } + @Override public void visitClassDef(JCClassDecl tree) { + tree.sym = null; + super.visitClassDef(tree); + } + @Override public void visitMethodDef(JCMethodDecl tree) { + tree.sym = null; + super.visitMethodDef(tree); + } + @Override public void visitVarDef(JCVariableDecl tree) { + tree.sym = null; + super.visitVarDef(tree); + } + @Override public void visitSelect(JCFieldAccess tree) { + tree.sym = null; + super.visitSelect(tree); + } + @Override public void visitIdent(JCIdent tree) { + tree.sym = null; + super.visitIdent(tree); + } + @Override public void visitAnnotation(JCAnnotation tree) { + JCAnnotationReflect.setAttribute(tree, null); + super.visitAnnotation(tree); + } + }); + } + private static void addError(String errorName, JavacNode node) { if (node.getLatestJavaSpecSupported() < 8) { node.addError("The correct format up to JDK7 is " + errorName + "=@__({@SomeAnnotation, @SomeOtherAnnotation}))"); diff --git a/test/core/src/lombok/RunTestsViaDelombok.java b/test/core/src/lombok/RunTestsViaDelombok.java index 46eb54a0..c10ef4d3 100644 --- a/test/core/src/lombok/RunTestsViaDelombok.java +++ b/test/core/src/lombok/RunTestsViaDelombok.java @@ -35,19 +35,21 @@ import java.util.Deque; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.Stack; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import com.sun.source.util.TreePath; import com.sun.source.util.Trees; import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.TreeScanner; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCAssign; import com.sun.tools.javac.tree.JCTree.JCClassDecl; @@ -57,11 +59,12 @@ import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCModifiers; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.tree.JCTree.TypeBoundKind; +import com.sun.tools.javac.tree.TreeScanner; import lombok.delombok.Delombok; import lombok.javac.CapturingDiagnosticListener; -import lombok.javac.Javac; import lombok.javac.CapturingDiagnosticListener.CompilerMessage; +import lombok.javac.Javac; public class RunTestsViaDelombok extends AbstractRunTests { private Delombok delombok = new Delombok(); @@ -78,6 +81,7 @@ public class RunTestsViaDelombok extends AbstractRunTests { delombok.setDiagnosticsListener(new CapturingDiagnosticListener(file, messages)); if (checkPositions) delombok.addAdditionalAnnotationProcessor(new ValidatePositionProcessor(version)); + delombok.addAdditionalAnnotationProcessor(new ValidateTypesProcessor()); delombok.addFile(file.getAbsoluteFile().getParentFile(), file.getName()); delombok.setSourcepath(file.getAbsoluteFile().getParent()); @@ -178,6 +182,57 @@ public class RunTestsViaDelombok extends AbstractRunTests { } } + public static class ValidateTypesProcessor extends TreeProcessor { + @Override void processCompilationUnit(final JCCompilationUnit unit) { + final Stack<JCTree> parents = new Stack<JCTree>(); + parents.add(unit); + + unit.accept(new TreeScanner() { + private JCTree parent; + @Override public void scan(JCTree tree) { + parent = parents.peek(); + + parents.push(tree); + super.scan(tree); + parents.pop(); + } + + @Override public void visitClassDef(JCClassDecl tree) { + // Skip anonymous or local classes, they have no symbol + if (!(parent instanceof JCClassDecl || parent instanceof JCCompilationUnit)) return; + + validateSymbol(tree, tree.sym); + super.visitClassDef(tree); + }; + + @Override public void visitMethodDef(JCMethodDecl tree) { + validateSymbol(tree, tree.sym); + super.visitMethodDef(tree); + } + + @Override public void visitVarDef(JCVariableDecl tree) { + // Skip non-field variables + if (!(parent instanceof JCClassDecl)) return; + + validateSymbol(tree, tree.sym); + super.visitVarDef(tree); + } + + private void validateSymbol(JCTree tree, Symbol sym) { + if (sym == null) { + fail("Missing symbol for " + tree); + } + // Skip top level classes + if (sym.owner.getKind() == ElementKind.PACKAGE) return; + + if (!sym.owner.getEnclosedElements().contains(sym)) { + fail(tree + " not added to parent"); + } + } + }); + } + } + public static abstract class TreeProcessor extends AbstractProcessor { private Trees trees; @Override public synchronized void init(ProcessingEnvironment processingEnv) { |