diff options
90 files changed, 1150 insertions, 364 deletions
diff --git a/src/core/lombok/AllArgsConstructor.java b/src/core/lombok/AllArgsConstructor.java index 2147bdae..068b7a68 100644 --- a/src/core/lombok/AllArgsConstructor.java +++ b/src/core/lombok/AllArgsConstructor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 The Project Lombok Authors. + * Copyright (C) 2010-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -49,6 +49,11 @@ public @interface AllArgsConstructor { String staticName() default ""; /** + * Any annotations listed here are put on the generated constructor. The syntax for this feature is: {@code @AllArgsConstructor(onConstructor=@_({@AnnotationsGoHere}))} + */ + AnyAnnotation[] onConstructor() default {}; + + /** * Sets the access level of the constructor. By default, generated constructors are {@code public}. */ AccessLevel access() default lombok.AccessLevel.PUBLIC; @@ -63,4 +68,13 @@ public @interface AllArgsConstructor { */ @Deprecated boolean suppressConstructorProperties() default false; + + /** + * Placeholder annotation to enable the placement of annotations on the generated code. + * @deprecated Don't use this annotation, ever - Read the documentation. + */ + @Deprecated + @Retention(RetentionPolicy.SOURCE) + @Target({}) + @interface AnyAnnotation {} } diff --git a/src/core/lombok/Getter.java b/src/core/lombok/Getter.java index fa12ce1b..57f5e40a 100644 --- a/src/core/lombok/Getter.java +++ b/src/core/lombok/Getter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2012 The Project Lombok Authors. + * Copyright (C) 2009-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -57,5 +57,19 @@ public @interface Getter { */ lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC; + /** + * Any annotations listed here are put on the generated method. The syntax for this feature is: {@code @Getter(onMethod=@_({@AnnotationsGoHere}))} + */ + AnyAnnotation[] onMethod() default @AnyAnnotation; + boolean lazy() default false; + + /** + * Placeholder annotation to enable the placement of annotations on the generated code. + * @deprecated Don't use this annotation, ever - Read the documentation. + */ + @Deprecated + @Retention(RetentionPolicy.SOURCE) + @Target({}) + @interface AnyAnnotation {} } diff --git a/src/core/lombok/NoArgsConstructor.java b/src/core/lombok/NoArgsConstructor.java index ba53e39f..bbf2d9e6 100644 --- a/src/core/lombok/NoArgsConstructor.java +++ b/src/core/lombok/NoArgsConstructor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 The Project Lombok Authors. + * Copyright (C) 2010-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -51,7 +51,21 @@ public @interface NoArgsConstructor { String staticName() default ""; /** + * Any annotations listed here are put on the generated constructor. The syntax for this feature is: {@code @NoArgsConstructor(onConstructor=@_({@AnnotationsGoHere}))} + */ + AnyAnnotation[] onConstructor() default {}; + + /** * Sets the access level of the constructor. By default, generated constructors are {@code public}. */ AccessLevel access() default lombok.AccessLevel.PUBLIC; + + /** + * Placeholder annotation to enable the placement of annotations on the generated code. + * @deprecated Don't use this annotation, ever - Read the documentation. + */ + @Deprecated + @Retention(RetentionPolicy.SOURCE) + @Target({}) + @interface AnyAnnotation {} } diff --git a/src/core/lombok/RequiredArgsConstructor.java b/src/core/lombok/RequiredArgsConstructor.java index afe9773e..31c4b81d 100644 --- a/src/core/lombok/RequiredArgsConstructor.java +++ b/src/core/lombok/RequiredArgsConstructor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 The Project Lombok Authors. + * Copyright (C) 2010-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -49,6 +49,11 @@ public @interface RequiredArgsConstructor { String staticName() default ""; /** + * Any annotations listed here are put on the generated constructor. The syntax for this feature is: {@code @RequiredArgsConstructor(onConstructor=@_({@AnnotationsGoHere}))} + */ + AnyAnnotation[] onConstructor() default {}; + + /** * Sets the access level of the constructor. By default, generated constructors are {@code public}. */ AccessLevel access() default lombok.AccessLevel.PUBLIC; @@ -63,4 +68,13 @@ public @interface RequiredArgsConstructor { */ @Deprecated boolean suppressConstructorProperties() default false; + + /** + * Placeholder annotation to enable the placement of annotations on the generated code. + * @deprecated Don't use this annotation, ever - Read the documentation. + */ + @Deprecated + @Retention(RetentionPolicy.SOURCE) + @Target({}) + @interface AnyAnnotation {} } diff --git a/src/core/lombok/Setter.java b/src/core/lombok/Setter.java index 59ed9346..22622520 100644 --- a/src/core/lombok/Setter.java +++ b/src/core/lombok/Setter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2012 The Project Lombok Authors. + * Copyright (C) 2009-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -57,4 +57,23 @@ public @interface Setter { * If you want your setter to be non-public, you can specify an alternate access level here. */ lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC; + + /** + * Any annotations listed here are put on the generated method. The syntax for this feature is: {@code @Setter(onMethod=@_({@AnnotationsGoHere}))} + */ + AnyAnnotation[] onMethod() default {}; + + /** + * Any annotations listed here are put on the generated method's parameter. The syntax for this feature is: {@code @Setter(onParam=@_({@AnnotationsGoHere}))} + */ + AnyAnnotation[] onParam() default {}; + + /** + * Placeholder annotation to enable the placement of annotations on the generated code. + * @deprecated Don't use this annotation, ever - Read the documentation. + */ + @Deprecated + @Retention(RetentionPolicy.SOURCE) + @Target({}) + @interface AnyAnnotation {} }
\ No newline at end of file diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 96795fe1..78780522 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2012 The Project Lombok Authors. + * Copyright (C) 2009-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -473,7 +473,7 @@ public class EclipseHandlerUtil { } } if (allNull) return null; - return result.toArray(EMPTY_ANNOTATION_ARRAY); + return result.toArray(new Annotation[0]); } public static boolean hasAnnotation(Class<? extends java.lang.annotation.Annotation> type, EclipseNode node) { @@ -1492,40 +1492,102 @@ public class EclipseHandlerUtil { intLiteralFactoryMethod = intLiteralFactoryMethod_; } - private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0]; - static Annotation[] getAndRemoveAnnotationParameter(Annotation annotation, String annotationName) { - - List<Annotation> result = new ArrayList<Annotation>(); - if (annotation instanceof NormalAnnotation) { - NormalAnnotation normalAnnotation = (NormalAnnotation)annotation; - MemberValuePair[] memberValuePairs = normalAnnotation.memberValuePairs; - List<MemberValuePair> pairs = new ArrayList<MemberValuePair>(); - if (memberValuePairs != null) for (MemberValuePair memberValuePair : memberValuePairs) { - if (annotationName.equals(new String(memberValuePair.name))) { - Expression value = memberValuePair.value; - if (value instanceof ArrayInitializer) { - ArrayInitializer array = (ArrayInitializer) value; - for(Expression expression : array.expressions) { - if (expression instanceof Annotation) { - result.add((Annotation)expression); - } - } - } - else if (value instanceof Annotation) { - result.add((Annotation)value); - } - continue; + private static boolean isAllUnderscores(char[] in) { + if (in == null || in.length == 0) return false; + for (char c : in) if (c != '_') return false; + return true; + } + + static List<Annotation> unboxAndRemoveAnnotationParameter(Annotation annotation, String annotationName, String errorName, EclipseNode errorNode) { + if ("value".equals(annotationName)) { + // We can't unbox this, because SingleMemberAnnotation REQUIRES a value, and this method + // is supposed to remove the value. That means we need to replace the SMA with either + // MarkerAnnotation or NormalAnnotation and that is beyond the scope of this method as we + // don't need that at the time of writing this method; we only unbox onMethod, onParameter + // and onConstructor. Let's exit early and very obviously: + throw new UnsupportedOperationException("Lombok cannot unbox 'value' from SingleMemberAnnotation at this time."); + } + if (!NormalAnnotation.class.equals(annotation.getClass())) { + // Prevent MarkerAnnotation, SingleMemberAnnotation, and + // CompletionOnAnnotationMemberValuePair from triggering this handler. + return Collections.emptyList(); + } + + NormalAnnotation normalAnnotation = (NormalAnnotation) annotation; + MemberValuePair[] pairs = normalAnnotation.memberValuePairs; + + if (pairs == null) return Collections.emptyList(); + + char[] nameAsCharArray = annotationName.toCharArray(); + + for (int i = 0; i < pairs.length; i++) { + if (pairs[i].name == null || !Arrays.equals(nameAsCharArray, pairs[i].name)) continue; + Expression value = pairs[i].value; + MemberValuePair[] newPairs = new MemberValuePair[pairs.length - 1]; + if (i > 0) System.arraycopy(pairs, 0, newPairs, 0, i); + if (i < pairs.length - 1) System.arraycopy(pairs, i + 1, newPairs, i, pairs.length - i - 1); + normalAnnotation.memberValuePairs = newPairs; + // We have now removed the annotation parameter and stored '@_({... annotations ...})', + // which we must now unbox. + if (!(value instanceof Annotation)) { + errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + return Collections.emptyList(); + } + + Annotation atUnderscore = (Annotation) value; + if (!(atUnderscore.type instanceof SingleTypeReference) || + !isAllUnderscores(((SingleTypeReference) atUnderscore.type).token)) { + errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + return Collections.emptyList(); + } + + if (atUnderscore instanceof MarkerAnnotation) { + // It's @getter(onMethod=@_). This is weird, but fine. + return Collections.emptyList(); + } + + Expression content = null; + + if (atUnderscore instanceof NormalAnnotation) { + MemberValuePair[] mvps = ((NormalAnnotation) atUnderscore).memberValuePairs; + if (mvps == null || mvps.length == 0) { + // It's @getter(onMethod=@_()). This is weird, but fine. + return Collections.emptyList(); + } + if (mvps.length == 1 && Arrays.equals("value".toCharArray(), mvps[0].name)) { + content = mvps[0].value; } - pairs.add(memberValuePair); } - if (!result.isEmpty()) { - normalAnnotation.memberValuePairs = pairs.isEmpty() ? null : pairs.toArray(new MemberValuePair[0]); - return result.toArray(EMPTY_ANNOTATION_ARRAY); + if (atUnderscore instanceof SingleMemberAnnotation) { + content = ((SingleMemberAnnotation) atUnderscore).memberValue; + } + + if (content == null) { + errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + return Collections.emptyList(); + } + + if (content instanceof Annotation) { + return Collections.singletonList((Annotation) content); + } else if (content instanceof ArrayInitializer) { + Expression[] expressions = ((ArrayInitializer) content).expressions; + List<Annotation> result = new ArrayList<Annotation>(); + if (expressions != null) for (Expression ex : expressions) { + if (ex instanceof Annotation) result.add((Annotation) ex); + else { + errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + return Collections.emptyList(); + } + } + return result; + } else { + errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + return Collections.emptyList(); } } - return EMPTY_ANNOTATION_ARRAY; + return Collections.emptyList(); } static NameReference createNameReference(String name, Annotation source) { diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java index 5d4656b6..8ccad77f 100644 --- a/src/core/lombok/eclipse/handlers/HandleConstructor.java +++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 The Project Lombok Authors. + * Copyright (C) 2010-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -79,7 +79,10 @@ public class HandleConstructor { String staticName = ann.staticName(); if (level == AccessLevel.NONE) return; List<EclipseNode> fields = new ArrayList<EclipseNode>(); - new HandleConstructor().generateConstructor(typeNode, level, fields, staticName, false, false, ast); + + List<Annotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@NoArgsConstructor(onConstructor=", annotationNode); + + new HandleConstructor().generateConstructor(typeNode, level, fields, staticName, false, false, onConstructor, ast); } } @@ -94,7 +97,10 @@ public class HandleConstructor { @SuppressWarnings("deprecation") boolean suppressConstructorProperties = ann.suppressConstructorProperties(); if (level == AccessLevel.NONE) return; - new HandleConstructor().generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, false, suppressConstructorProperties, ast); + + List<Annotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@RequiredArgsConstructor(onConstructor=", annotationNode); + + new HandleConstructor().generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, false, suppressConstructorProperties, onConstructor, ast); } } @@ -137,7 +143,10 @@ public class HandleConstructor { @SuppressWarnings("deprecation") boolean suppressConstructorProperties = ann.suppressConstructorProperties(); if (level == AccessLevel.NONE) return; - new HandleConstructor().generateConstructor(typeNode, level, findAllFields(typeNode), staticName, false, suppressConstructorProperties, ast); + + List<Annotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@AllArgsConstructor(onConstructor=", annotationNode); + + new HandleConstructor().generateConstructor(typeNode, level, findAllFields(typeNode), staticName, false, suppressConstructorProperties, onConstructor, ast); } } @@ -155,15 +164,15 @@ public class HandleConstructor { return true; } - public void generateRequiredArgsConstructor(EclipseNode typeNode, AccessLevel level, String staticName, boolean skipIfConstructorExists, ASTNode source) { - generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, skipIfConstructorExists, false, source); + public void generateRequiredArgsConstructor(EclipseNode typeNode, AccessLevel level, String staticName, boolean skipIfConstructorExists, List<Annotation> onConstructor, ASTNode source) { + generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, skipIfConstructorExists, false, onConstructor, source); } - public void generateAllArgsConstructor(EclipseNode typeNode, AccessLevel level, String staticName, boolean skipIfConstructorExists, ASTNode source) { - generateConstructor(typeNode, level, findAllFields(typeNode), staticName, skipIfConstructorExists, false, source); + public void generateAllArgsConstructor(EclipseNode typeNode, AccessLevel level, String staticName, boolean skipIfConstructorExists, List<Annotation> onConstructor, ASTNode source) { + generateConstructor(typeNode, level, findAllFields(typeNode), staticName, skipIfConstructorExists, false, onConstructor, source); } - public void generateConstructor(EclipseNode typeNode, AccessLevel level, List<EclipseNode> fields, String staticName, boolean skipIfConstructorExists, boolean suppressConstructorProperties, ASTNode source) { + public void generateConstructor(EclipseNode typeNode, AccessLevel level, List<EclipseNode> fields, String staticName, boolean skipIfConstructorExists, boolean suppressConstructorProperties, List<Annotation> onConstructor, ASTNode source) { boolean staticConstrRequired = staticName != null && !staticName.equals(""); if (skipIfConstructorExists && constructorExists(typeNode) != MemberExistsResult.NOT_EXISTS) return; @@ -187,7 +196,7 @@ public class HandleConstructor { } } - ConstructorDeclaration constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, typeNode, fields, suppressConstructorProperties, source); + ConstructorDeclaration constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, typeNode, fields, suppressConstructorProperties, source, onConstructor); injectMethod(typeNode, constr); if (staticConstrRequired) { MethodDeclaration staticConstr = createStaticConstructor(level, staticName, typeNode, fields, source); @@ -196,8 +205,8 @@ public class HandleConstructor { } private static final char[][] JAVA_BEANS_CONSTRUCTORPROPERTIES = new char[][] { "java".toCharArray(), "beans".toCharArray(), "ConstructorProperties".toCharArray() }; - private static Annotation[] createConstructorProperties(ASTNode source, Annotation[] originalAnnotationArray, Collection<EclipseNode> fields) { - if (fields.isEmpty()) return originalAnnotationArray; + private static Annotation[] createConstructorProperties(ASTNode source, Collection<EclipseNode> fields) { + if (fields.isEmpty()) return null; int pS = source.sourceStart, pE = source.sourceEnd; long p = (long)pS << 32 | pE; @@ -223,14 +232,14 @@ public class HandleConstructor { ann.memberValue = fieldNames; setGeneratedBy(ann, source); setGeneratedBy(ann.memberValue, source); - if (originalAnnotationArray == null) return new Annotation[] { ann }; - Annotation[] newAnnotationArray = Arrays.copyOf(originalAnnotationArray, originalAnnotationArray.length + 1); - newAnnotationArray[originalAnnotationArray.length] = ann; - return newAnnotationArray; + return new Annotation[] { ann }; } - private ConstructorDeclaration createConstructor(AccessLevel level, - EclipseNode type, Collection<EclipseNode> fields, boolean suppressConstructorProperties, ASTNode source) { + private ConstructorDeclaration createConstructor( + AccessLevel level, EclipseNode type, Collection<EclipseNode> fields, + boolean suppressConstructorProperties, ASTNode source, List<Annotation> onConstructor) { + + TypeDeclaration typeDeclaration = ((TypeDeclaration)type.get()); long p = (long)source.sourceStart << 32 | source.sourceEnd; boolean isEnum = (((TypeDeclaration)type.get()).modifiers & ClassFileConstants.AccEnum) != 0; @@ -239,12 +248,10 @@ public class HandleConstructor { ConstructorDeclaration constructor = new ConstructorDeclaration( ((CompilationUnitDeclaration) type.top().get()).compilationResult); - setGeneratedBy(constructor, source); constructor.modifiers = toEclipseModifier(level); - constructor.selector = ((TypeDeclaration)type.get()).name; + constructor.selector = typeDeclaration.name; constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper); - setGeneratedBy(constructor.constructorCall, source); constructor.constructorCall.sourceStart = source.sourceStart; constructor.constructorCall.sourceEnd = source.sourceEnd; constructor.thrownExceptions = null; @@ -261,19 +268,14 @@ public class HandleConstructor { for (EclipseNode fieldNode : fields) { FieldDeclaration field = (FieldDeclaration) fieldNode.get(); FieldReference thisX = new FieldReference(field.name, p); - setGeneratedBy(thisX, source); thisX.receiver = new ThisReference((int)(p >> 32), (int)p); - setGeneratedBy(thisX.receiver, source); SingleNameReference assignmentNameRef = new SingleNameReference(field.name, p); - setGeneratedBy(assignmentNameRef, source); Assignment assignment = new Assignment(thisX, assignmentNameRef, (int)p); assignment.sourceStart = (int)(p >> 32); assignment.sourceEnd = assignment.statementEnd = (int)(p >> 32); - setGeneratedBy(assignment, source); assigns.add(assignment); long fieldPos = (((long)field.sourceStart) << 32) | field.sourceEnd; Argument parameter = new Argument(field.name, fieldPos, copyType(field.type, source), Modifier.FINAL); - setGeneratedBy(parameter, source); Annotation[] nonNulls = findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN); Annotation[] nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN); if (nonNulls.length != 0) { @@ -289,10 +291,19 @@ public class HandleConstructor { constructor.statements = nullChecks.isEmpty() ? null : nullChecks.toArray(new Statement[nullChecks.size()]); constructor.arguments = params.isEmpty() ? null : params.toArray(new Argument[params.size()]); - if (!suppressConstructorProperties && level != AccessLevel.PRIVATE && !isLocalType(type)) { - constructor.annotations = createConstructorProperties(source, constructor.annotations, fields); + /* Generate annotations that must be put on the generated method, and attach them. */ { + Annotation[] constructorProperties = null; + if (!suppressConstructorProperties && level != AccessLevel.PRIVATE && !isLocalType(type)) { + constructorProperties = createConstructorProperties(source, fields); + } + + Annotation[] copiedAnnotations = copyAnnotations(source, + onConstructor.toArray(new Annotation[0]), + constructorProperties); + if (copiedAnnotations.length != 0) constructor.annotations = copiedAnnotations; } + constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope); return constructor; } @@ -309,7 +320,6 @@ public class HandleConstructor { MethodDeclaration constructor = new MethodDeclaration( ((CompilationUnitDeclaration) type.top().get()).compilationResult); - setGeneratedBy(constructor, source); constructor.modifiers = toEclipseModifier(level) | Modifier.STATIC; TypeDeclaration typeDecl = (TypeDeclaration) type.get(); @@ -323,7 +333,6 @@ public class HandleConstructor { } constructor.returnType = new ParameterizedSingleTypeReference(typeDecl.name, refs, 0, p); } else constructor.returnType = new SingleTypeReference(((TypeDeclaration)type.get()).name, p); - setGeneratedBy(constructor.returnType, source); constructor.annotations = null; constructor.selector = name.toCharArray(); constructor.thrownExceptions = null; @@ -336,18 +345,15 @@ public class HandleConstructor { List<Expression> assigns = new ArrayList<Expression>(); AllocationExpression statement = new AllocationExpression(); statement.sourceStart = pS; statement.sourceEnd = pE; - setGeneratedBy(statement, source); statement.type = copyType(constructor.returnType, source); for (EclipseNode fieldNode : fields) { FieldDeclaration field = (FieldDeclaration) fieldNode.get(); long fieldPos = (((long)field.sourceStart) << 32) | field.sourceEnd; SingleNameReference nameRef = new SingleNameReference(field.name, fieldPos); - setGeneratedBy(nameRef, source); assigns.add(nameRef); Argument parameter = new Argument(field.name, fieldPos, copyType(field.type, source), Modifier.FINAL); - setGeneratedBy(parameter, source); Annotation[] copiedAnnotations = copyAnnotations(source, findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN), findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN)); if (copiedAnnotations.length != 0) parameter.annotations = copiedAnnotations; @@ -357,7 +363,8 @@ public class HandleConstructor { statement.arguments = assigns.isEmpty() ? null : assigns.toArray(new Expression[assigns.size()]); constructor.arguments = params.isEmpty() ? null : params.toArray(new Argument[params.size()]); constructor.statements = new Statement[] { new ReturnStatement(statement, (int)(p >> 32), (int)p) }; - setGeneratedBy(constructor.statements[0], source); + + constructor.traverse(new SetGeneratedByVisitor(source), typeDecl.scope); return constructor; } } diff --git a/src/core/lombok/eclipse/handlers/HandleData.java b/src/core/lombok/eclipse/handlers/HandleData.java index ba29b30b..3a43bd3f 100644 --- a/src/core/lombok/eclipse/handlers/HandleData.java +++ b/src/core/lombok/eclipse/handlers/HandleData.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2011 The Project Lombok Authors. + * Copyright (C) 2009-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -21,6 +21,8 @@ */ package lombok.eclipse.handlers; +import java.util.Collections; + import lombok.AccessLevel; import lombok.Data; import lombok.core.AnnotationValues; @@ -62,6 +64,6 @@ public class HandleData extends EclipseAnnotationHandler<Data> { new HandleSetter().generateSetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true); new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode); new HandleToString().generateToStringForType(typeNode, annotationNode); - new HandleConstructor().generateRequiredArgsConstructor(typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), true, ast); + new HandleConstructor().generateRequiredArgsConstructor(typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), true, Collections.<Annotation>emptyList(), ast); } } diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java index df05fc7e..7f788c5d 100644 --- a/src/core/lombok/eclipse/handlers/HandleGetter.java +++ b/src/core/lombok/eclipse/handlers/HandleGetter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2012 The Project Lombok Authors. + * Copyright (C) 2009-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -125,7 +125,7 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> { return; } - createGetterForField(level, fieldNode, fieldNode, pos, false, lazy); + createGetterForField(level, fieldNode, fieldNode, pos, false, lazy, Collections.<Annotation>emptyList()); } public void handle(AnnotationValues<Getter> annotation, Annotation ast, EclipseNode annotationNode) { @@ -142,25 +142,30 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> { if (node == null) return; + List<Annotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Getter(onMethod=", annotationNode); + switch (node.getKind()) { case FIELD: - createGetterForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true, lazy); + createGetterForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true, lazy, onMethod); break; case TYPE: + if (!onMethod.isEmpty()) { + annotationNode.addError("'onMethod' is not supported for @Getter on a type."); + } if (lazy) annotationNode.addError("'lazy' is not supported for @Getter on a type."); generateGetterForType(node, annotationNode, level, false); break; } } - private void createGetterForFields(AccessLevel level, Collection<EclipseNode> fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists, boolean lazy) { + private void createGetterForFields(AccessLevel level, Collection<EclipseNode> fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists, boolean lazy, List<Annotation> onMethod) { for (EclipseNode fieldNode : fieldNodes) { - createGetterForField(level, fieldNode, errorNode, source, whineIfExists, lazy); + createGetterForField(level, fieldNode, errorNode, source, whineIfExists, lazy, onMethod); } } private void createGetterForField(AccessLevel level, - EclipseNode fieldNode, EclipseNode errorNode, ASTNode source, boolean whineIfExists, boolean lazy) { + EclipseNode fieldNode, EclipseNode errorNode, ASTNode source, boolean whineIfExists, boolean lazy, List<Annotation> onMethod) { if (fieldNode.getKind() != Kind.FIELD) { errorNode.addError("@Getter is only supported on a class or a field."); return; @@ -207,17 +212,7 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> { } } - MethodDeclaration method = generateGetter((TypeDeclaration) fieldNode.up().get(), fieldNode, getterName, modifier, source, lazy); - - Annotation[] deprecated = null; - if (isFieldDeprecated(fieldNode)) { - deprecated = new Annotation[] { generateDeprecatedAnnotation(source) }; - } - - Annotation[] copiedAnnotations = copyAnnotations(source, findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN), findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN), findDelegatesAndMarkAsHandled(fieldNode), deprecated); - if (copiedAnnotations.length != 0) { - method.annotations = copiedAnnotations; - } + MethodDeclaration method = createGetter((TypeDeclaration) fieldNode.up().get(), fieldNode, getterName, modifier, source, lazy, onMethod); injectMethod(fieldNode.up(), method); } @@ -234,7 +229,8 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> { return delegates.toArray(EMPTY_ANNOTATIONS_ARRAY); } - private MethodDeclaration generateGetter(TypeDeclaration parent, EclipseNode fieldNode, String name, int modifier, ASTNode source, boolean lazy) { + private MethodDeclaration createGetter(TypeDeclaration parent, EclipseNode fieldNode, String name, int modifier, ASTNode source, boolean lazy, List<Annotation> onMethod) { + FieldDeclaration field = (FieldDeclaration) fieldNode.get(); // Remember the type; lazy will change it; TypeReference returnType = copyType(((FieldDeclaration) fieldNode.get()).type, source); @@ -247,7 +243,6 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> { } MethodDeclaration method = new MethodDeclaration(parent.compilationResult); - setGeneratedBy(method, source); method.modifiers = modifier; method.returnType = returnType; method.annotations = null; @@ -263,6 +258,23 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> { EclipseHandlerUtil.registerCreatedLazyGetter((FieldDeclaration) fieldNode.get(), method.selector, returnType); + /* Generate annotations that must be put on the generated method, and attach them. */ { + Annotation[] deprecated = null; + if (isFieldDeprecated(fieldNode)) { + deprecated = new Annotation[] { generateDeprecatedAnnotation(source) }; + } + + Annotation[] copiedAnnotations = copyAnnotations(source, + onMethod.toArray(new Annotation[0]), + findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN), + findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN), + findDelegatesAndMarkAsHandled(fieldNode), + deprecated); + + if (copiedAnnotations.length != 0) method.annotations = copiedAnnotations; + } + + method.traverse(new SetGeneratedByVisitor(source), parent.scope); return method; } @@ -270,7 +282,6 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> { FieldDeclaration field = (FieldDeclaration) fieldNode.get(); Expression fieldRef = createFieldAccessor(fieldNode, FieldAccess.ALWAYS_FIELD, source); Statement returnStatement = new ReturnStatement(fieldRef, field.sourceStart, field.sourceEnd); - setGeneratedBy(returnStatement, source); return new Statement[] {returnStatement}; } @@ -319,7 +330,6 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> { char[][] newType = TYPE_MAP.get(new String(((SingleTypeReference)field.type).token)); if (newType != null) { componentType = new QualifiedTypeReference(newType, poss(source, 3)); - setGeneratedBy(componentType, source); } } @@ -327,21 +337,17 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> { /* java.util.concurrent.atomic.AtomicReference<ValueType> value = this.fieldName.get(); */ { LocalDeclaration valueDecl = new LocalDeclaration(valueName, pS, pE); - setGeneratedBy(valueDecl, source); TypeReference[][] typeParams = AR_PARAMS.clone(); typeParams[4] = new TypeReference[] {copyType(componentType, source)}; valueDecl.type = new ParameterizedQualifiedTypeReference(AR, typeParams, 0, poss(source, 5)); valueDecl.type.sourceStart = pS; valueDecl.type.sourceEnd = valueDecl.type.statementEnd = pE; - setGeneratedBy(valueDecl.type, source); MessageSend getter = new MessageSend(); - setGeneratedBy(getter, source); getter.sourceStart = pS; getter.statementEnd = getter.sourceEnd = pE; getter.selector = new char[] {'g', 'e', 't'}; getter.receiver = createFieldAccessor(fieldNode, FieldAccess.ALWAYS_FIELD, source); valueDecl.initialization = getter; - setGeneratedBy(valueDecl.initialization, source); statements[0] = valueDecl; } @@ -360,102 +366,75 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> { EqualExpression cond = new EqualExpression( new SingleNameReference(valueName, p), new NullLiteral(pS, pE), BinaryExpression.EQUAL_EQUAL); - setGeneratedBy(cond.left, source); - setGeneratedBy(cond.right, source); - setGeneratedBy(cond, source); Block then = new Block(0); - setGeneratedBy(then, source); Expression lock = createFieldAccessor(fieldNode, FieldAccess.ALWAYS_FIELD, source); Block inner = new Block(0); - setGeneratedBy(inner, source); inner.statements = new Statement[2]; /* value = this.fieldName.get(); */ { MessageSend getter = new MessageSend(); - setGeneratedBy(getter, source); getter.sourceStart = pS; getter.sourceEnd = getter.statementEnd = pE; getter.selector = new char[] {'g', 'e', 't'}; getter.receiver = createFieldAccessor(fieldNode, FieldAccess.ALWAYS_FIELD, source); Assignment assign = new Assignment(new SingleNameReference(valueName, p), getter, pE); assign.sourceStart = pS; assign.statementEnd = assign.sourceEnd = pE; - setGeneratedBy(assign, source); - setGeneratedBy(assign.lhs, source); inner.statements[0] = assign; } /* if (value == null) */ { EqualExpression innerCond = new EqualExpression( new SingleNameReference(valueName, p), new NullLiteral(pS, pE), BinaryExpression.EQUAL_EQUAL); - setGeneratedBy(innerCond.left, source); - setGeneratedBy(innerCond.right, source); - setGeneratedBy(innerCond, source); Block innerThen = new Block(0); - setGeneratedBy(innerThen, source); innerThen.statements = new Statement[3]; /* final ValueType actualValue = new ValueType(); */ { LocalDeclaration actualValueDecl = new LocalDeclaration(actualValueName, pS, pE); - setGeneratedBy(actualValueDecl, source); actualValueDecl.type = copyType(field.type, source); actualValueDecl.type.sourceStart = pS; actualValueDecl.type.sourceEnd = actualValueDecl.type.statementEnd = pE; - setGeneratedBy(actualValueDecl.type, source); actualValueDecl.initialization = field.initialization; actualValueDecl.modifiers = ClassFileConstants.AccFinal; innerThen.statements[0] = actualValueDecl; } /* value = new java.util.concurrent.atomic.AtomicReference<ValueType>(actualValue); */ { AllocationExpression create = new AllocationExpression(); - setGeneratedBy(create, source); create.sourceStart = pS; create.sourceEnd = create.statementEnd = pE; TypeReference[][] typeParams = AR_PARAMS.clone(); typeParams[4] = new TypeReference[] {copyType(componentType, source)}; create.type = new ParameterizedQualifiedTypeReference(AR, typeParams, 0, poss(source, 5)); create.type.sourceStart = pS; create.type.sourceEnd = create.type.statementEnd = pE; - setGeneratedBy(create.type, source); create.arguments = new Expression[] {new SingleNameReference(actualValueName, p)}; - setGeneratedBy(create.arguments[0], source); Assignment innerAssign = new Assignment(new SingleNameReference(valueName, p), create, pE); innerAssign.sourceStart = pS; innerAssign.statementEnd = innerAssign.sourceEnd = pE; - setGeneratedBy(innerAssign, source); - setGeneratedBy(innerAssign.lhs, source); innerThen.statements[1] = innerAssign; } /* this.fieldName.set(value); */ { MessageSend setter = new MessageSend(); - setGeneratedBy(setter, source); setter.sourceStart = pS; setter.sourceEnd = setter.statementEnd = pE; setter.receiver = createFieldAccessor(fieldNode, FieldAccess.ALWAYS_FIELD, source); setter.selector = new char[] { 's', 'e', 't' }; setter.arguments = new Expression[] { new SingleNameReference(valueName, p)}; - setGeneratedBy(setter.arguments[0], source); innerThen.statements[2] = setter; } IfStatement innerIf = new IfStatement(innerCond, innerThen, pS, pE); - setGeneratedBy(innerIf, source); inner.statements[1] = innerIf; } SynchronizedStatement sync = new SynchronizedStatement(lock, inner, pS, pE); - setGeneratedBy(sync, source); then.statements = new Statement[] {sync}; IfStatement ifStatement = new IfStatement(cond, then, pS, pE); - setGeneratedBy(ifStatement, source); statements[1] = ifStatement; } /* return value.get(); */ { MessageSend getter = new MessageSend(); - setGeneratedBy(getter, source); getter.sourceStart = pS; getter.sourceEnd = getter.statementEnd = pE; getter.selector = new char[] {'g', 'e', 't'}; getter.receiver = new SingleNameReference(valueName, p); - setGeneratedBy(getter.receiver, source); statements[2] = new ReturnStatement(getter, pS, pE); - setGeneratedBy(statements[2], source); } @@ -471,7 +450,6 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> { TypeReference type = new ParameterizedQualifiedTypeReference(AR, typeParams, 0, poss(source, 5)); // Some magic here type.sourceStart = -1; type.sourceEnd = -2; - setGeneratedBy(type, source); field.type = type; AllocationExpression init = new AllocationExpression(); diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java index 8037ed23..9b46b704 100644 --- a/src/core/lombok/eclipse/handlers/HandleSetter.java +++ b/src/core/lombok/eclipse/handlers/HandleSetter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2011 The Project Lombok Authors. + * Copyright (C) 2009-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,6 +27,7 @@ import static lombok.eclipse.handlers.EclipseHandlerUtil.*; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; import lombok.AccessLevel; @@ -111,7 +112,9 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> { return; } - createSetterForField(level, fieldNode, fieldNode, pos, false); + List<Annotation> empty = Collections.emptyList(); + + createSetterForField(level, fieldNode, fieldNode, pos, false, empty, empty); } public void handle(AnnotationValues<Setter> annotation, Annotation ast, EclipseNode annotationNode) { @@ -119,24 +122,36 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> { AccessLevel level = annotation.getInstance().value(); if (level == AccessLevel.NONE || node == null) return; + List<Annotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Setter(onMethod=", annotationNode); + List<Annotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Setter(onParam=", annotationNode); + switch (node.getKind()) { case FIELD: - createSetterForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true); + createSetterForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true, onMethod, onParam); break; case TYPE: + if (!onMethod.isEmpty()) { + annotationNode.addError("'onMethod' is not supported for @Setter on a type."); + } + if (!onParam.isEmpty()) { + annotationNode.addError("'onParam' is not supported for @Setter on a type."); + } generateSetterForType(node, annotationNode, level, false); break; } } - private void createSetterForFields(AccessLevel level, Collection<EclipseNode> fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists) { + private void createSetterForFields(AccessLevel level, Collection<EclipseNode> fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists, List<Annotation> onMethod, List<Annotation> onParam) { for (EclipseNode fieldNode : fieldNodes) { - createSetterForField(level, fieldNode, errorNode, source, whineIfExists); + createSetterForField(level, fieldNode, errorNode, source, whineIfExists, onMethod, onParam); } } - private void createSetterForField(AccessLevel level, - EclipseNode fieldNode, EclipseNode errorNode, ASTNode source, boolean whineIfExists) { + private void createSetterForField( + AccessLevel level, EclipseNode fieldNode, EclipseNode errorNode, + ASTNode source, boolean whineIfExists, List<Annotation> onMethod, + List<Annotation> onParam) { + if (fieldNode.getKind() != Kind.FIELD) { errorNode.addError("@Setter is only supported on a class or a field."); return; @@ -147,6 +162,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> { boolean isBoolean = nameEquals(fieldType.getTypeName(), "boolean") && fieldType.dimensions() == 0; String setterName = toSetterName(fieldNode, isBoolean); boolean shouldReturnThis = shouldReturnThis(fieldNode); + if (setterName == null) { errorNode.addWarning("Not generating setter for this field: It does not fit your @Accessors prefix list."); return; @@ -172,16 +188,15 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> { } } - MethodDeclaration method = createSetter((TypeDeclaration) fieldNode.up().get(), fieldNode, setterName, shouldReturnThis, modifier, source); + MethodDeclaration method = createSetter((TypeDeclaration) fieldNode.up().get(), fieldNode, setterName, shouldReturnThis, modifier, source, onMethod, onParam); injectMethod(fieldNode.up(), method); } - private MethodDeclaration createSetter(TypeDeclaration parent, EclipseNode fieldNode, String name, boolean shouldReturnThis, int modifier, ASTNode source) { + private MethodDeclaration createSetter(TypeDeclaration parent, EclipseNode fieldNode, String name, boolean shouldReturnThis, int modifier, ASTNode source, List<Annotation> onMethod, List<Annotation> onParam) { FieldDeclaration field = (FieldDeclaration) fieldNode.get(); int pS = source.sourceStart, pE = source.sourceEnd; long p = (long)pS << 32 | pE; MethodDeclaration method = new MethodDeclaration(parent.compilationResult); - setGeneratedBy(method, source); method.modifiers = modifier; if (shouldReturnThis) { method.returnType = cloneSelfType(fieldNode, source); @@ -190,15 +205,18 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> { if (method.returnType == null) { method.returnType = TypeReference.baseTypeReference(TypeIds.T_void, 0); method.returnType.sourceStart = pS; method.returnType.sourceEnd = pE; - setGeneratedBy(method.returnType, source); shouldReturnThis = false; } + Annotation[] deprecated = null; if (isFieldDeprecated(fieldNode)) { - method.annotations = new Annotation[] { generateDeprecatedAnnotation(source) }; + deprecated = new Annotation[] { generateDeprecatedAnnotation(source) }; + } + Annotation[] copiedAnnotations = copyAnnotations(source, onMethod.toArray(new Annotation[0]), deprecated); + if (copiedAnnotations.length != 0) { + method.annotations = copiedAnnotations; } Argument param = new Argument(field.name, p, copyType(field.type, source), Modifier.FINAL); param.sourceStart = pS; param.sourceEnd = pE; - setGeneratedBy(param, source); method.arguments = new Argument[] { param }; method.selector = name.toCharArray(); method.binding = null; @@ -207,10 +225,8 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> { method.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; Expression fieldRef = createFieldAccessor(fieldNode, FieldAccess.ALWAYS_FIELD, source); NameReference fieldNameRef = new SingleNameReference(field.name, p); - setGeneratedBy(fieldNameRef, source); Assignment assignment = new Assignment(fieldRef, fieldNameRef, (int)p); assignment.sourceStart = pS; assignment.sourceEnd = assignment.statementEnd = pE; - setGeneratedBy(assignment, source); method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart; method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd; @@ -227,15 +243,15 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> { if (shouldReturnThis) { ThisReference thisRef = new ThisReference(pS, pE); - setGeneratedBy(thisRef, source); ReturnStatement returnThis = new ReturnStatement(thisRef, pS, pE); - setGeneratedBy(returnThis, source); statements.add(returnThis); } method.statements = statements.toArray(new Statement[0]); - Annotation[] copiedAnnotations = copyAnnotations(source, nonNulls, nullables); - if (copiedAnnotations.length != 0) param.annotations = copiedAnnotations; + Annotation[] copiedAnnotationsParam = copyAnnotations(source, nonNulls, nullables, onParam.toArray(new Annotation[0])); + if (copiedAnnotationsParam.length != 0) param.annotations = copiedAnnotationsParam; + + method.traverse(new SetGeneratedByVisitor(source), parent.scope); return method; } } diff --git a/src/core/lombok/eclipse/handlers/HandleValue.java b/src/core/lombok/eclipse/handlers/HandleValue.java index 4c293dc0..b74fbede 100644 --- a/src/core/lombok/eclipse/handlers/HandleValue.java +++ b/src/core/lombok/eclipse/handlers/HandleValue.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 The Project Lombok Authors. + * Copyright (C) 2012-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,6 +22,9 @@ package lombok.eclipse.handlers; import static lombok.eclipse.handlers.EclipseHandlerUtil.*; + +import java.util.Collections; + import lombok.AccessLevel; import lombok.core.AnnotationValues; import lombok.core.HandlerPriority; @@ -76,6 +79,6 @@ public class HandleValue extends EclipseAnnotationHandler<Value> { new HandleWither().generateWitherForType(typeNode, annotationNode, AccessLevel.PUBLIC, true); new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode); new HandleToString().generateToStringForType(typeNode, annotationNode); - new HandleConstructor().generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), true, ast); + new HandleConstructor().generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), true, Collections.<Annotation>emptyList(), ast); } } diff --git a/src/core/lombok/eclipse/handlers/HandleWither.java b/src/core/lombok/eclipse/handlers/HandleWither.java index 1441a5f2..9d74cbd1 100644 --- a/src/core/lombok/eclipse/handlers/HandleWither.java +++ b/src/core/lombok/eclipse/handlers/HandleWither.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 The Project Lombok Authors. + * Copyright (C) 2012-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,6 +27,7 @@ import static lombok.eclipse.handlers.EclipseHandlerUtil.*; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; import lombok.AccessLevel; @@ -114,7 +115,8 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> { } } - createWitherForField(level, fieldNode, fieldNode, pos, false); + List<Annotation> empty = Collections.emptyList(); + createWitherForField(level, fieldNode, fieldNode, pos, false, empty, empty); } @Override public void handle(AnnotationValues<Wither> annotation, Annotation ast, EclipseNode annotationNode) { @@ -122,24 +124,35 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> { AccessLevel level = annotation.getInstance().value(); if (level == AccessLevel.NONE || node == null) return; + List<Annotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Setter(onMethod=", annotationNode); + List<Annotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Setter(onParam=", annotationNode); + switch (node.getKind()) { case FIELD: - createWitherForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true); + createWitherForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true, onMethod, onParam); break; case TYPE: + if (!onMethod.isEmpty()) { + annotationNode.addError("'onMethod' is not supported for @Wither on a type."); + } + if (!onParam.isEmpty()) { + annotationNode.addError("'onParam' is not supported for @Wither on a type."); + } generateWitherForType(node, annotationNode, level, false); break; } } - private void createWitherForFields(AccessLevel level, Collection<EclipseNode> fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists) { + private void createWitherForFields(AccessLevel level, Collection<EclipseNode> fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists, List<Annotation> onMethod, List<Annotation> onParam) { for (EclipseNode fieldNode : fieldNodes) { - createWitherForField(level, fieldNode, errorNode, source, whineIfExists); + createWitherForField(level, fieldNode, errorNode, source, whineIfExists, onMethod, onParam); } } - private void createWitherForField(AccessLevel level, - EclipseNode fieldNode, EclipseNode errorNode, ASTNode source, boolean whineIfExists) { + private void createWitherForField( + AccessLevel level, EclipseNode fieldNode, EclipseNode errorNode, + ASTNode source, boolean whineIfExists, List<Annotation> onMethod, + List<Annotation> onParam) { if (fieldNode.getKind() != Kind.FIELD) { errorNode.addError("@Wither is only supported on a class or a field."); return; @@ -190,11 +203,11 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> { int modifier = toEclipseModifier(level); - MethodDeclaration method = createWither((TypeDeclaration) fieldNode.up().get(), fieldNode, witherName, modifier, source); + MethodDeclaration method = createWither((TypeDeclaration) fieldNode.up().get(), fieldNode, witherName, modifier, source, onMethod, onParam); injectMethod(fieldNode.up(), method); } - private MethodDeclaration createWither(TypeDeclaration parent, EclipseNode fieldNode, String name, int modifier, ASTNode source) { + private MethodDeclaration createWither(TypeDeclaration parent, EclipseNode fieldNode, String name, int modifier, ASTNode source, List<Annotation> onMethod, List<Annotation> onParam) { if (name == null) return null; FieldDeclaration field = (FieldDeclaration) fieldNode.get(); int pS = source.sourceStart, pE = source.sourceEnd; @@ -204,8 +217,13 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> { method.returnType = cloneSelfType(fieldNode, source); if (method.returnType == null) return null; + Annotation[] deprecated = null; if (isFieldDeprecated(fieldNode)) { - method.annotations = new Annotation[] { generateDeprecatedAnnotation(source) }; + deprecated = new Annotation[] { generateDeprecatedAnnotation(source) }; + } + Annotation[] copiedAnnotations = copyAnnotations(source, onMethod.toArray(new Annotation[0]), deprecated); + if (copiedAnnotations.length != 0) { + method.annotations = copiedAnnotations; } Argument param = new Argument(field.name, p, copyType(field.type, source), Modifier.FINAL); param.sourceStart = pS; param.sourceEnd = pE; @@ -259,8 +277,9 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> { method.statements = statements.toArray(new Statement[0]); - Annotation[] copiedAnnotations = copyAnnotations(source, nonNulls, nullables); - if (copiedAnnotations.length != 0) param.annotations = copiedAnnotations; + Annotation[] copiedAnnotationsParam = copyAnnotations(source, nonNulls, nullables, onParam.toArray(new Annotation[0])); + if (copiedAnnotationsParam.length != 0) param.annotations = copiedAnnotationsParam; + method.traverse(new SetGeneratedByVisitor(source), parent.scope); return method; } diff --git a/src/core/lombok/experimental/Wither.java b/src/core/lombok/experimental/Wither.java index 58be660a..f667cb1f 100644 --- a/src/core/lombok/experimental/Wither.java +++ b/src/core/lombok/experimental/Wither.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 The Project Lombok Authors. + * Copyright (C) 2012-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -58,4 +58,23 @@ public @interface Wither { * If you want your wither to be non-public, you can specify an alternate access level here. */ AccessLevel value() default AccessLevel.PUBLIC; + + /** + * Any annotations listed here are put on the generated method. The syntax for this feature is: {@code @Setter(onMethod=@_({@AnnotationsGoHere}))} + */ + AnyAnnotation[] onMethod() default {}; + + /** + * Any annotations listed here are put on the generated method's parameter. The syntax for this feature is: {@code @Setter(onParam=@_({@AnnotationsGoHere}))} + */ + AnyAnnotation[] onParam() default {}; + + /** + * Placeholder annotation to enable the placement of annotations on the generated code. + * @deprecated Don't use this annotation, ever - Read the documentation. + */ + @Deprecated + @Retention(RetentionPolicy.SOURCE) + @Target({}) + @interface AnyAnnotation {} } diff --git a/src/core/lombok/javac/CapturingDiagnosticListener.java b/src/core/lombok/javac/CapturingDiagnosticListener.java new file mode 100644 index 00000000..45b4047a --- /dev/null +++ b/src/core/lombok/javac/CapturingDiagnosticListener.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2012-2013 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.javac; + +import java.io.File; +import java.util.Collection; +import java.util.Iterator; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.tools.Diagnostic; +import javax.tools.Diagnostic.Kind; +import javax.tools.DiagnosticListener; +import javax.tools.JavaFileObject; + +/** + * This class stores any reported errors as {@code CompilerMessage} objects and supports removing some of these. + * Currently this class is only used for testing purposes. + */ +public class CapturingDiagnosticListener implements DiagnosticListener<JavaFileObject> { + private final File file; + private final Collection<CompilerMessage> messages; + + public CapturingDiagnosticListener(File file, Collection<CompilerMessage> messages) { + this.file = file; + this.messages = messages; + } + + @Override public void report(Diagnostic<? extends JavaFileObject> d) { + String msg = d.getMessage(Locale.ENGLISH); + Matcher m = Pattern.compile( + "^" + Pattern.quote(file.getAbsolutePath()) + + "\\s*:\\s*\\d+\\s*:\\s*(?:warning:\\s*)?(.*)$", Pattern.DOTALL).matcher(msg); + if (m.matches()) msg = m.group(1); + messages.add(new CompilerMessage(d.getLineNumber(), d.getColumnNumber(), d.getStartPosition(), d.getKind() == Kind.ERROR, msg)); + } + + public void suppress(int start, int end) { + Iterator<CompilerMessage> it = messages.iterator(); + while (it.hasNext()) { + long pos = it.next().getPosition(); + if (pos >= start && pos < end) it.remove(); + } + } + + public static final class CompilerMessage { + /** Line Number (starting at 1) */ + private final long line; + + /** Preferably column, but if that is hard to calculate (e.g. in ecj), then position is acceptable. */ + private final long columnOrPosition; + private final long position; + private final boolean isError; + private final String message; + + public CompilerMessage(long line, long columnOrPosition, long position, boolean isError, String message) { + this.line = line; + this.columnOrPosition = columnOrPosition; + this.position = position; + this.isError = isError; + this.message = message; + } + + public long getLine() { + return line; + } + + public long getPosition() { + return position; + } + + public long getColumnOrPosition() { + return columnOrPosition; + } + + public boolean isError() { + return isError; + } + + public String getMessage() { + return message; + } + + @Override public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (isError ? 1231 : 1237); + result = prime * result + (int) (line ^ (line >>> 32)); + result = prime * result + ((message == null) ? 0 : message.hashCode()); + result = prime * result + (int) (columnOrPosition ^ (columnOrPosition >>> 32)); + return result; + } + + @Override public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + CompilerMessage other = (CompilerMessage) obj; + if (isError != other.isError) return false; + if (line != other.line) return false; + if (message == null) { + if (other.message != null) return false; + } else if (!message.equals(other.message)) return false; + if (columnOrPosition != other.columnOrPosition) return false; + return true; + } + + @Override public String toString() { + return String.format("%d:%d %s %s", line, columnOrPosition, isError ? "ERROR" : "WARNING", message); + } + } +} diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java index c2c55f1d..71c17538 100644 --- a/src/core/lombok/javac/JavacAST.java +++ b/src/core/lombok/javac/JavacAST.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2010 The Project Lombok Authors. + * Copyright (C) 2009-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,6 +28,7 @@ import java.util.List; import javax.annotation.processing.Messager; import javax.tools.Diagnostic; +import javax.tools.DiagnosticListener; import javax.tools.JavaFileObject; import lombok.core.AST; @@ -50,6 +51,8 @@ import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.JCDiagnostic; +import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; @@ -287,8 +290,28 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { if (node != null) nodes.add(node); } + private static final Field JAVAC7_DEFERRED_DIAGNOSTICS; + + static { + Field f = null; + try { + f = Log.class.getField("deferredDiagnostics"); + if (!ListBuffer.class.isAssignableFrom(f.getType())) throw new NoSuchFieldException("deferredDiagnostics does not have the expected type."); + } catch (NoSuchFieldException e) {} + JAVAC7_DEFERRED_DIAGNOSTICS = f; + } + + /** + * Attempts to remove any compiler errors generated by java whose reporting position is located anywhere between the start and end of the supplied node. + */ + void removeDeferredErrors(JavacNode node) { + DiagnosticPosition pos = node.get().pos(); + JCCompilationUnit top = (JCCompilationUnit) top().get(); + removeFromDeferredDiagnostics(pos.getStartPosition(), pos.getEndPosition(top.endPositions)); + } + /** Supply either a position or a node (in that case, position of the node is used) */ - void printMessage(Diagnostic.Kind kind, String message, JavacNode node, DiagnosticPosition pos) { + void printMessage(Diagnostic.Kind kind, String message, JavacNode node, DiagnosticPosition pos, boolean attemptToRemoveErrorsInRange) { JavaFileObject oldSource = null; JavaFileObject newSource = null; JCTree astObject = node == null ? null : node.get(); @@ -298,6 +321,9 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { oldSource = log.useSource(newSource); if (pos == null) pos = astObject.pos(); } + if (pos != null && attemptToRemoveErrorsInRange) { + removeFromDeferredDiagnostics(pos.getStartPosition(), pos.getEndPosition(top.endPositions)); + } try { switch (kind) { case ERROR: @@ -319,6 +345,35 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { if (oldSource != null) log.useSource(oldSource); } } + + private void removeFromDeferredDiagnostics(int startPos, int endPos) { + DiagnosticListener<?> listener = getContext().get(DiagnosticListener.class); + if (listener instanceof CapturingDiagnosticListener) { + ((CapturingDiagnosticListener) listener).suppress(startPos, endPos); + } + try { + if (JAVAC7_DEFERRED_DIAGNOSTICS != null) { + ListBuffer<?> deferredDiagnostics = (ListBuffer<?>) JAVAC7_DEFERRED_DIAGNOSTICS.get(log); + ListBuffer<Object> newDeferredDiagnostics = ListBuffer.lb(); + for (Object diag : deferredDiagnostics) { + if (!(diag instanceof JCDiagnostic)) { + newDeferredDiagnostics.add(diag); + continue; + } + long here = ((JCDiagnostic) diag).getStartPosition(); + if (here >= startPos && here < endPos) { + // We eliminate it + } else { + newDeferredDiagnostics.add(diag); + } + } + JAVAC7_DEFERRED_DIAGNOSTICS.set(log, newDeferredDiagnostics); + } + } catch (Exception e) { + // We do not expect failure here; if failure does occur, the best course of action is to silently continue; the result will be that the error output of + // javac will contain rather a lot of messages, but this is a lot better than just crashing during compilation! + } + } /** {@inheritDoc} */ @Override protected void setElementInASTCollection(Field field, Object refField, List<Collection<?>> chain, Collection<?> collection, int idx, JCTree newN) throws IllegalAccessException { diff --git a/src/core/lombok/javac/JavacNode.java b/src/core/lombok/javac/JavacNode.java index b478781b..16c06430 100644 --- a/src/core/lombok/javac/JavacNode.java +++ b/src/core/lombok/javac/JavacNode.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2010 The Project Lombok Authors. + * Copyright (C) 2009-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -209,31 +209,35 @@ public class JavacNode extends lombok.core.LombokNode<JavacAST, JavacNode, JCTre return ast.toName(name); } + public void removeDeferredErrors() { + ast.removeDeferredErrors(this); + } + /** * Generates an compiler error focused on the AST node represented by this node object. */ @Override public void addError(String message) { - ast.printMessage(Diagnostic.Kind.ERROR, message, this, null); + ast.printMessage(Diagnostic.Kind.ERROR, message, this, null, true); } /** * Generates an compiler error focused on the AST node represented by this node object. */ public void addError(String message, DiagnosticPosition pos) { - ast.printMessage(Diagnostic.Kind.ERROR, message, null, pos); + ast.printMessage(Diagnostic.Kind.ERROR, message, null, pos, true); } /** * Generates a compiler warning focused on the AST node represented by this node object. */ @Override public void addWarning(String message) { - ast.printMessage(Diagnostic.Kind.WARNING, message, this, null); + ast.printMessage(Diagnostic.Kind.WARNING, message, this, null, false); } /** * Generates a compiler warning focused on the AST node represented by this node object. */ public void addWarning(String message, DiagnosticPosition pos) { - ast.printMessage(Diagnostic.Kind.WARNING, message, null, pos); + ast.printMessage(Diagnostic.Kind.WARNING, message, null, pos, false); } } diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java index b6c31f83..bb883ca4 100644 --- a/src/core/lombok/javac/handlers/HandleConstructor.java +++ b/src/core/lombok/javac/handlers/HandleConstructor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 The Project Lombok Authors. + * Copyright (C) 2010-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -60,12 +60,13 @@ public class HandleConstructor { deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); JavacNode typeNode = annotationNode.up(); if (!checkLegality(typeNode, annotationNode, NoArgsConstructor.class.getSimpleName())) return; + List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@NoArgsConstructor(onConstructor=", annotationNode); NoArgsConstructor ann = annotation.getInstance(); AccessLevel level = ann.access(); String staticName = ann.staticName(); if (level == AccessLevel.NONE) return; List<JavacNode> fields = List.nil(); - new HandleConstructor().generateConstructor(typeNode, level, fields, staticName, false, false, annotationNode); + new HandleConstructor().generateConstructor(typeNode, level, onConstructor, fields, staticName, false, false, annotationNode); } } @@ -76,13 +77,14 @@ public class HandleConstructor { deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); JavacNode typeNode = annotationNode.up(); if (!checkLegality(typeNode, annotationNode, RequiredArgsConstructor.class.getSimpleName())) return; + List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@RequiredArgsConstructor(onConstructor=", annotationNode); RequiredArgsConstructor ann = annotation.getInstance(); AccessLevel level = ann.access(); String staticName = ann.staticName(); @SuppressWarnings("deprecation") boolean suppressConstructorProperties = ann.suppressConstructorProperties(); if (level == AccessLevel.NONE) return; - new HandleConstructor().generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, false, suppressConstructorProperties, annotationNode); + new HandleConstructor().generateConstructor(typeNode, level, onConstructor, findRequiredFields(typeNode), staticName, false, suppressConstructorProperties, annotationNode); } } @@ -110,13 +112,14 @@ public class HandleConstructor { deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); JavacNode typeNode = annotationNode.up(); if (!checkLegality(typeNode, annotationNode, AllArgsConstructor.class.getSimpleName())) return; + List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@AllArgsConstructor(onConstructor=", annotationNode); AllArgsConstructor ann = annotation.getInstance(); AccessLevel level = ann.access(); String staticName = ann.staticName(); @SuppressWarnings("deprecation") boolean suppressConstructorProperties = ann.suppressConstructorProperties(); if (level == AccessLevel.NONE) return; - new HandleConstructor().generateConstructor(typeNode, level, findAllFields(typeNode), staticName, false, suppressConstructorProperties, annotationNode); + new HandleConstructor().generateConstructor(typeNode, level, onConstructor, findAllFields(typeNode), staticName, false, suppressConstructorProperties, annotationNode); } } @@ -152,14 +155,14 @@ public class HandleConstructor { } public void generateRequiredArgsConstructor(JavacNode typeNode, AccessLevel level, String staticName, boolean skipIfConstructorExists, JavacNode source) { - generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, skipIfConstructorExists, false, source); + generateConstructor(typeNode, level, List.<JCAnnotation>nil(), findRequiredFields(typeNode), staticName, skipIfConstructorExists, false, source); } public void generateAllArgsConstructor(JavacNode typeNode, AccessLevel level, String staticName, boolean skipIfConstructorExists, JavacNode source) { - generateConstructor(typeNode, level, findAllFields(typeNode), staticName, skipIfConstructorExists, false, source); + generateConstructor(typeNode, level, List.<JCAnnotation>nil(), findAllFields(typeNode), staticName, skipIfConstructorExists, false, source); } - public void generateConstructor(JavacNode typeNode, AccessLevel level, List<JavacNode> fields, String staticName, boolean skipIfConstructorExists, boolean suppressConstructorProperties, JavacNode source) { + public void generateConstructor(JavacNode typeNode, AccessLevel level, List<JCAnnotation> onConstructor, List<JavacNode> fields, String staticName, boolean skipIfConstructorExists, boolean suppressConstructorProperties, JavacNode source) { boolean staticConstrRequired = staticName != null && !staticName.equals(""); if (skipIfConstructorExists && constructorExists(typeNode) != MemberExistsResult.NOT_EXISTS) return; @@ -183,7 +186,7 @@ public class HandleConstructor { } } - JCMethodDecl constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, typeNode, fields, suppressConstructorProperties, source.get()); + JCMethodDecl constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, onConstructor, typeNode, fields, suppressConstructorProperties, source.get()); injectMethod(typeNode, constr); if (staticConstrRequired) { JCMethodDecl staticConstr = createStaticConstructor(staticName, level, typeNode, fields, source.get()); @@ -204,7 +207,7 @@ public class HandleConstructor { mods.annotations = mods.annotations.append(annotation); } - private JCMethodDecl createConstructor(AccessLevel level, JavacNode typeNode, List<JavacNode> fields, boolean suppressConstructorProperties, JCTree source) { + private JCMethodDecl createConstructor(AccessLevel level, List<JCAnnotation> onConstructor, JavacNode typeNode, List<JavacNode> fields, boolean suppressConstructorProperties, JCTree source) { TreeMaker maker = typeNode.getTreeMaker(); boolean isEnum = (((JCClassDecl) typeNode.get()).mods.flags & Flags.ENUM) != 0; @@ -234,6 +237,8 @@ public class HandleConstructor { if (!suppressConstructorProperties && level != AccessLevel.PRIVATE && !isLocalType(typeNode)) { addConstructorProperties(mods, typeNode, fields); } + if (onConstructor != null) mods.annotations = mods.annotations.appendList(copyAnnotations(onConstructor)); + return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("<init>"), null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(), maker.Block(0L, nullChecks.appendList(assigns).toList()), null), source); } diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index 65947c72..bc68d5ad 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2012 The Project Lombok Authors. + * Copyright (C) 2009-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -21,8 +21,8 @@ */ package lombok.javac.handlers; -import static lombok.javac.handlers.JavacHandlerUtil.*; import static lombok.javac.Javac.*; +import static lombok.javac.handlers.JavacHandlerUtil.*; import java.util.Collection; import java.util.Collections; @@ -32,9 +32,9 @@ 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.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; import lombok.javac.handlers.JavacHandlerUtil.FieldAccess; @@ -43,7 +43,6 @@ import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCBinary; import com.sun.tools.javac.tree.JCTree.JCBlock; @@ -60,10 +59,11 @@ import com.sun.tools.javac.tree.JCTree.JCSynchronized; import com.sun.tools.javac.tree.JCTree.JCTypeApply; import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; -import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; /** * Handles the {@code lombok.Getter} annotation for javac. @@ -123,8 +123,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { //The annotation will make it happen, so we can skip it. return; } - - createGetterForField(level, fieldNode, fieldNode, false, lazy); + createGetterForField(level, fieldNode, fieldNode, false, lazy, List.<JCAnnotation>nil()); } @Override public void handle(AnnotationValues<Getter> annotation, JCAnnotation ast, JavacNode annotationNode) { @@ -144,25 +143,30 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { if (node == null) return; + List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Getter(onMethod=", annotationNode); + switch (node.getKind()) { case FIELD: - createGetterForFields(level, fields, annotationNode, true, lazy); + createGetterForFields(level, fields, annotationNode, true, lazy, onMethod); break; case TYPE: + if (!onMethod.isEmpty()) { + annotationNode.addError("'onMethod' is not supported for @Getter on a type."); + } if (lazy) annotationNode.addError("'lazy' is not supported for @Getter on a type."); generateGetterForType(node, annotationNode, level, false); break; } } - private void createGetterForFields(AccessLevel level, Collection<JavacNode> fieldNodes, JavacNode errorNode, boolean whineIfExists, boolean lazy) { + private void createGetterForFields(AccessLevel level, Collection<JavacNode> fieldNodes, JavacNode errorNode, boolean whineIfExists, boolean lazy, List<JCAnnotation> onMethod) { for (JavacNode fieldNode : fieldNodes) { - createGetterForField(level, fieldNode, errorNode, whineIfExists, lazy); + createGetterForField(level, fieldNode, errorNode, whineIfExists, lazy, onMethod); } } private void createGetterForField(AccessLevel level, - JavacNode fieldNode, JavacNode source, boolean whineIfExists, boolean lazy) { + JavacNode fieldNode, JavacNode source, boolean whineIfExists, boolean lazy, List<JCAnnotation> onMethod) { if (fieldNode.getKind() != Kind.FIELD) { source.addError("@Getter is only supported on a class or a field."); return; @@ -208,10 +212,10 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC); - injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), lazy, source.get())); + injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), source.get(), lazy, onMethod)); } - private JCMethodDecl createGetter(long access, JavacNode field, TreeMaker treeMaker, boolean lazy, JCTree source) { + private JCMethodDecl createGetter(long access, JavacNode field, TreeMaker treeMaker, JCTree source, boolean lazy, List<JCAnnotation> onMethod) { JCVariableDecl fieldNode = (JCVariableDecl) field.get(); // Remember the type; lazy will change it @@ -240,7 +244,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { List<JCAnnotation> delegates = findDelegatesAndRemoveFromField(field); - List<JCAnnotation> annsOnMethod = nonNulls.appendList(nullables); + List<JCAnnotation> annsOnMethod = copyAnnotations(onMethod).appendList(nonNulls).appendList(nullables); if (isFieldDeprecated(field)) { annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(chainDots(field, "java", "lang", "Deprecated"), List.<JCExpression>nil())); } diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index e2c75e2e..c1e03c35 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2012 The Project Lombok Authors. + * Copyright (C) 2009-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -118,7 +118,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { return; } - createSetterForField(level, fieldNode, fieldNode, false); + createSetterForField(level, fieldNode, fieldNode, false, List.<JCAnnotation>nil(), List.<JCAnnotation>nil()); } @Override public void handle(AnnotationValues<Setter> annotation, JCAnnotation ast, JavacNode annotationNode) { @@ -130,26 +130,28 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { if (level == AccessLevel.NONE || node == null) return; + List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Setter(onMethod=", annotationNode); + List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Setter(onParam=", annotationNode); + switch (node.getKind()) { case FIELD: - createSetterForFields(level, fields, annotationNode, true); + createSetterForFields(level, fields, annotationNode, true, onMethod, onParam); break; case TYPE: + if (!onMethod.isEmpty()) annotationNode.addError("'onMethod' is not supported for @Setter on a type."); + if (!onParam.isEmpty()) annotationNode.addError("'onParam' is not supported for @Setter on a type."); generateSetterForType(node, annotationNode, level, false); break; } } - private void createSetterForFields(AccessLevel level, Collection<JavacNode> fieldNodes, JavacNode errorNode, boolean whineIfExists) { - + private void createSetterForFields(AccessLevel level, Collection<JavacNode> fieldNodes, JavacNode errorNode, boolean whineIfExists, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { for (JavacNode fieldNode : fieldNodes) { - createSetterForField(level, fieldNode, errorNode, whineIfExists); + createSetterForField(level, fieldNode, errorNode, whineIfExists, onMethod, onParam); } } - private void createSetterForField(AccessLevel level, - JavacNode fieldNode, JavacNode source, boolean whineIfExists) { - + private void createSetterForField(AccessLevel level, JavacNode fieldNode, JavacNode source, boolean whineIfExists, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { if (fieldNode.getKind() != Kind.FIELD) { fieldNode.addError("@Setter is only supported on a class or a field."); return; @@ -188,11 +190,11 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC); - JCMethodDecl createdSetter = createSetter(access, fieldNode, fieldNode.getTreeMaker(), source.get()); + JCMethodDecl createdSetter = createSetter(access, fieldNode, fieldNode.getTreeMaker(), source.get(), onMethod, onParam); injectMethod(fieldNode.up(), createdSetter); } - private JCMethodDecl createSetter(long access, JavacNode field, TreeMaker treeMaker, JCTree source) { + private JCMethodDecl createSetter(long access, JavacNode field, TreeMaker treeMaker, JCTree source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { String setterName = toSetterName(field); boolean returnThis = shouldReturnThis(field); if (setterName == null) return null; @@ -207,7 +209,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { List<JCAnnotation> nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN); Name methodName = field.toName(setterName); - List<JCAnnotation> annsOnParam = nonNulls.appendList(nullables); + List<JCAnnotation> annsOnParam = copyAnnotations(onParam).appendList(nonNulls).appendList(nullables); JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(Flags.FINAL, annsOnParam), fieldDecl.name, fieldDecl.vartype, null); @@ -241,10 +243,11 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { List<JCExpression> throwsClauses = List.nil(); JCExpression annotationMethodDefaultValue = null; - List<JCAnnotation> annsOnMethod = List.nil(); + List<JCAnnotation> annsOnMethod = copyAnnotations(onMethod); if (isFieldDeprecated(field)) { annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(chainDots(field, "java", "lang", "Deprecated"), List.<JCExpression>nil())); } + return recursiveSetGeneratedBy(treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType, methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source); } diff --git a/src/core/lombok/javac/handlers/HandleWither.java b/src/core/lombok/javac/handlers/HandleWither.java index 64011f91..ba5aa72d 100644 --- a/src/core/lombok/javac/handlers/HandleWither.java +++ b/src/core/lombok/javac/handlers/HandleWither.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 The Project Lombok Authors. + * Copyright (C) 2012-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -109,16 +109,12 @@ public class HandleWither extends JavacAnnotationHandler<Wither> { * @param pos The node responsible for generating the wither (the {@code @Value} or {@code @Wither} annotation). */ public void generateWitherForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level) { - for (JavacNode child : fieldNode.down()) { - if (child.getKind() == Kind.ANNOTATION) { - if (annotationTypeMatches(Wither.class, child)) { - //The annotation will make it happen, so we can skip it. - return; - } - } + if (hasAnnotation(Wither.class, fieldNode)) { + //The annotation will make it happen, so we can skip it. + return; } - createWitherForField(level, fieldNode, fieldNode, false); + createWitherForField(level, fieldNode, fieldNode, false, List.<JCAnnotation>nil(), List.<JCAnnotation>nil()); } @Override public void handle(AnnotationValues<Wither> annotation, JCAnnotation ast, JavacNode annotationNode) { @@ -130,25 +126,28 @@ public class HandleWither extends JavacAnnotationHandler<Wither> { if (level == AccessLevel.NONE || node == null) return; + List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Setter(onMethod=", annotationNode); + List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Setter(onParam=", annotationNode); + switch (node.getKind()) { case FIELD: - createWitherForFields(level, fields, annotationNode, true); + createWitherForFields(level, fields, annotationNode, true, onMethod, onParam); break; case TYPE: + if (!onMethod.isEmpty()) annotationNode.addError("'onMethod' is not supported for @Wither on a type."); + if (!onParam.isEmpty()) annotationNode.addError("'onParam' is not supported for @Wither on a type."); generateWitherForType(node, annotationNode, level, false); break; } } - private void createWitherForFields(AccessLevel level, Collection<JavacNode> fieldNodes, JavacNode errorNode, boolean whineIfExists) { + private void createWitherForFields(AccessLevel level, Collection<JavacNode> fieldNodes, JavacNode errorNode, boolean whineIfExists, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { for (JavacNode fieldNode : fieldNodes) { - createWitherForField(level, fieldNode, errorNode, whineIfExists); + createWitherForField(level, fieldNode, errorNode, whineIfExists, onMethod, onParam); } } - private void createWitherForField(AccessLevel level, - JavacNode fieldNode, JavacNode source, boolean whineIfExists) { - + private void createWitherForField(AccessLevel level, JavacNode fieldNode, JavacNode source, boolean whineIfExists, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { if (fieldNode.getKind() != Kind.FIELD) { fieldNode.addError("@Wither is only supported on a class or a field."); return; @@ -197,11 +196,11 @@ public class HandleWither extends JavacAnnotationHandler<Wither> { long access = toJavacModifier(level); - JCMethodDecl createdWither = createWither(access, fieldNode, fieldNode.getTreeMaker(), source.get()); + JCMethodDecl createdWither = createWither(access, fieldNode, fieldNode.getTreeMaker(), source.get(), onMethod, onParam); injectMethod(fieldNode.up(), createdWither); } - private JCMethodDecl createWither(long access, JavacNode field, TreeMaker treeMaker, JCTree source) { + private JCMethodDecl createWither(long access, JavacNode field, TreeMaker treeMaker, JCTree source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { String witherName = toWitherName(field); if (witherName == null) return null; @@ -212,7 +211,7 @@ public class HandleWither extends JavacAnnotationHandler<Wither> { List<JCAnnotation> nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN); Name methodName = field.toName(witherName); - List<JCAnnotation> annsOnParam = nonNulls.appendList(nullables); + List<JCAnnotation> annsOnParam = copyAnnotations(onParam).appendList(nonNulls).appendList(nullables); JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(Flags.FINAL, annsOnParam), fieldDecl.name, fieldDecl.vartype, null); @@ -260,7 +259,8 @@ public class HandleWither extends JavacAnnotationHandler<Wither> { List<JCExpression> throwsClauses = List.nil(); JCExpression annotationMethodDefaultValue = null; - List<JCAnnotation> annsOnMethod = List.nil(); + List<JCAnnotation> annsOnMethod = copyAnnotations(onMethod); + if (isFieldDeprecated(field)) { annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(chainDots(field, "java", "lang", "Deprecated"), List.<JCExpression>nil())); } diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index ad3e4a17..c2de5b05 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2012 The Project Lombok Authors. + * Copyright (C) 2009-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -63,8 +63,8 @@ import com.sun.tools.javac.tree.JCTree.JCModifiers; import com.sun.tools.javac.tree.JCTree.JCNewArray; import com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree; import com.sun.tools.javac.tree.JCTree.JCStatement; -import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCTypeApply; +import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.tree.JCTree.JCWildcard; import com.sun.tools.javac.tree.JCTree.TypeBoundKind; @@ -920,33 +920,77 @@ public class JavacHandlerUtil { return problematic.toList(); } - static List<JCExpression> getAndRemoveAnnotationParameter(JCAnnotation ast, String parameterName) { + static List<JCAnnotation> unboxAndRemoveAnnotationParameter(JCAnnotation ast, String parameterName, String errorName, JavacNode errorNode) { ListBuffer<JCExpression> params = ListBuffer.lb(); - List<JCExpression> result = List.nil(); + ListBuffer<JCAnnotation> result = ListBuffer.lb(); + errorNode.removeDeferredErrors(); + + outer: for (JCExpression param : ast.args) { + String nameOfParam = "value"; + JCExpression valueOfParam = null; if (param instanceof JCAssign) { JCAssign assign = (JCAssign) param; if (assign.lhs instanceof JCIdent) { JCIdent ident = (JCIdent) assign.lhs; - if (parameterName.equals(ident.name.toString())) { - if (assign.rhs instanceof JCNewArray) { - result = ((JCNewArray) assign.rhs).elems; + nameOfParam = ident.name.toString(); + } + valueOfParam = assign.rhs; + } + + if (!parameterName.equals(nameOfParam)) { + params.append(param); + continue outer; + } + + if (valueOfParam instanceof JCAnnotation) { + String dummyAnnotationName = ((JCAnnotation) valueOfParam).annotationType.toString(); + dummyAnnotationName = dummyAnnotationName.replace("_", ""); + if (dummyAnnotationName.length() > 0) { + errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + continue outer; + } + for (JCExpression expr : ((JCAnnotation) valueOfParam).args) { + if (expr instanceof JCAssign && ((JCAssign) expr).lhs instanceof JCIdent) { + JCIdent id = (JCIdent) ((JCAssign) expr).lhs; + if ("value".equals(id.name.toString())) { + expr = ((JCAssign) expr).rhs; } else { - result = result.append(assign.rhs); + errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + continue outer; } - continue; + } + + if (expr instanceof JCAnnotation) { + result.append((JCAnnotation) expr); + } else if (expr instanceof JCNewArray) { + for (JCExpression expr2 : ((JCNewArray) expr).elems) { + if (expr2 instanceof JCAnnotation) { + result.append((JCAnnotation) expr2); + } else { + errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + continue outer; + } + } + } else { + errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + continue outer; } } + } else { + if (valueOfParam instanceof JCNewArray && ((JCNewArray) valueOfParam).elems.isEmpty()) { + // Then we just remove it and move on (it's onMethod={} for example). + } else { + errorNode.addError("The correct format is " + errorName + "@_({@SomeAnnotation, @SomeOtherAnnotation}))"); + } } - - params.append(param); } ast.args = params.toList(); - return result; + return result.toList(); } - static List<JCAnnotation> copyAnnotations(List<JCExpression> in) { + static List<JCAnnotation> copyAnnotations(List<? extends JCExpression> in) { ListBuffer<JCAnnotation> out = ListBuffer.lb(); for (JCExpression expr : in) { if (!(expr instanceof JCAnnotation)) continue; diff --git a/src/stubs/com/sun/tools/javac/parser/EndPosParser.java b/src/stubs/com/sun/tools/javac/parser/EndPosParser.java index 1ffd6ec5..d7a352d6 100644 --- a/src/stubs/com/sun/tools/javac/parser/EndPosParser.java +++ b/src/stubs/com/sun/tools/javac/parser/EndPosParser.java @@ -1,3 +1,6 @@ +/* + * These are stub versions of various bits of javac-internal API (for various different versions of javac). Lombok is compiled against these. + */ package com.sun.tools.javac.parser; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; diff --git a/src/stubs/com/sun/tools/javac/parser/Lexer.java b/src/stubs/com/sun/tools/javac/parser/Lexer.java index b0824501..0d432c01 100644 --- a/src/stubs/com/sun/tools/javac/parser/Lexer.java +++ b/src/stubs/com/sun/tools/javac/parser/Lexer.java @@ -1,3 +1,6 @@ +/* + * These are stub versions of various bits of javac-internal API (for various different versions of javac). Lombok is compiled against these. + */ package com.sun.tools.javac.parser; public interface Lexer { diff --git a/src/stubs/com/sun/tools/javac/parser/Parser.java b/src/stubs/com/sun/tools/javac/parser/Parser.java new file mode 100644 index 00000000..c8bc5e63 --- /dev/null +++ b/src/stubs/com/sun/tools/javac/parser/Parser.java @@ -0,0 +1,21 @@ +/* + * These are stub versions of various bits of javac-internal API (for various different versions of javac). Lombok is compiled against these. + */ +package com.sun.tools.javac.parser; + +import com.sun.tools.javac.util.Context; + +public class Parser { + public static class Factory { + public static Context.Key<Parser.Factory> parserFactoryKey; + + public Factory(Context context) { + + } + + public Parser newParser(Lexer S, boolean keepDocComments, boolean genEndPos) { + return null; + } + + } +} diff --git a/src/stubs/com/sun/tools/javac/parser/ParserFactory.java b/src/stubs/com/sun/tools/javac/parser/ParserFactory.java index 193f2333..2f693271 100644 --- a/src/stubs/com/sun/tools/javac/parser/ParserFactory.java +++ b/src/stubs/com/sun/tools/javac/parser/ParserFactory.java @@ -1,3 +1,6 @@ +/* + * These are stub versions of various bits of javac-internal API (for various different versions of javac). Lombok is compiled against these. + */ package com.sun.tools.javac.parser; import com.sun.tools.javac.util.Context; diff --git a/src/stubs/com/sun/tools/javac/util/BaseFileObject.java b/src/stubs/com/sun/tools/javac/util/BaseFileObject.java new file mode 100644 index 00000000..315e7ab1 --- /dev/null +++ b/src/stubs/com/sun/tools/javac/util/BaseFileObject.java @@ -0,0 +1,8 @@ +/* + * These are stub versions of various bits of javac-internal API (for various different versions of javac). Lombok is compiled against these. + */ +package com.sun.tools.javac.util; + +import javax.tools.JavaFileObject; + +public abstract class BaseFileObject implements JavaFileObject {} diff --git a/test/core/src/lombok/AbstractRunTests.java b/test/core/src/lombok/AbstractRunTests.java index 229d321a..a3f52cdd 100644 --- a/test/core/src/lombok/AbstractRunTests.java +++ b/test/core/src/lombok/AbstractRunTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2010 The Project Lombok Authors. + * Copyright (C) 2009-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -40,6 +40,8 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; +import lombok.javac.CapturingDiagnosticListener.CompilerMessage; + public abstract class AbstractRunTests { protected static final String LINE_SEPARATOR = System.getProperty("line.separator"); private final File dumpActualFilesHere; @@ -130,7 +132,7 @@ public abstract class AbstractRunTests { FileOutputStream fos = new FileOutputStream(file); try { for (CompilerMessage message : content) { - fos.write(message.asCompilerMessageMatcher().toString().getBytes("UTF-8")); + fos.write(CompilerMessageMatcher.asCompilerMessageMatcher(message).toString().getBytes("UTF-8")); fos.write('\n'); } } finally { @@ -151,7 +153,9 @@ public abstract class AbstractRunTests { System.out.println(actualFile); if (actualMessages != null && !actualMessages.isEmpty()) { System.out.println("**** Actual Errors *****"); - System.out.println(actualMessages); + for (CompilerMessage actualMessage : actualMessages) { + System.out.println(actualMessage); + } } System.out.println("*******************"); } @@ -168,9 +172,13 @@ public abstract class AbstractRunTests { System.out.println("***** " + name + " *****"); System.out.println(e.getMessage()); System.out.println("**** Expected ******"); - System.out.println(expectedMessages); + for (CompilerMessageMatcher expectedMessage : expectedMessages) { + System.out.println(expectedMessage); + } System.out.println("**** Actual ******"); - System.out.println(actualMessages); + for (CompilerMessage actualMessage : actualMessages) { + System.out.println(actualMessage); + } System.out.println("*******************"); } if (dumpActualFilesHere != null) { diff --git a/test/core/src/lombok/CompilerMessage.java b/test/core/src/lombok/CompilerMessage.java deleted file mode 100644 index d04d17f1..00000000 --- a/test/core/src/lombok/CompilerMessage.java +++ /dev/null @@ -1,50 +0,0 @@ -package lombok; - -public final class CompilerMessage { - /** Line Number (starting at 1) */ - final long line; - - /** Position is either column number, OR position in file starting from the first byte. */ - final long position; - final boolean isError; - final String message; - - public CompilerMessage(long line, long position, boolean isError, String message) { - this.line = line; - this.position = position; - this.isError = isError; - this.message = message; - } - - @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (isError ? 1231 : 1237); - result = prime * result + (int) (line ^ (line >>> 32)); - result = prime * result + ((message == null) ? 0 : message.hashCode()); - result = prime * result + (int) (position ^ (position >>> 32)); - return result; - } - - @Override public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - CompilerMessage other = (CompilerMessage) obj; - if (isError != other.isError) return false; - if (line != other.line) return false; - if (message == null) { - if (other.message != null) return false; - } else if (!message.equals(other.message)) return false; - if (position != other.position) return false; - return true; - } - - public CompilerMessageMatcher asCompilerMessageMatcher() { - return new CompilerMessageMatcher(line, position, message); - } - - @Override public String toString() { - return String.format("%d:%d %s %s", line, position, isError ? "ERROR" : "WARNING", message); - } -} diff --git a/test/core/src/lombok/CompilerMessageMatcher.java b/test/core/src/lombok/CompilerMessageMatcher.java index b7902395..af12e199 100644 --- a/test/core/src/lombok/CompilerMessageMatcher.java +++ b/test/core/src/lombok/CompilerMessageMatcher.java @@ -1,3 +1,24 @@ +/* + * Copyright (C) 2012-2013 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package lombok; import java.io.BufferedReader; @@ -11,6 +32,8 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import lombok.javac.CapturingDiagnosticListener.CompilerMessage; + public class CompilerMessageMatcher { /** Line Number (starting at 1) */ private final long line; @@ -25,6 +48,10 @@ public class CompilerMessageMatcher { this.messageParts = Arrays.asList(message.split("\\s+")); } + public static CompilerMessageMatcher asCompilerMessageMatcher(CompilerMessage message) { + return new CompilerMessageMatcher(message.getLine(), message.getColumnOrPosition(), message.getMessage()); + } + @Override public String toString() { StringBuilder parts = new StringBuilder(); for (String part : messageParts) parts.append(part).append(" "); @@ -33,10 +60,10 @@ public class CompilerMessageMatcher { } public boolean matches(CompilerMessage message) { - if (message.line != this.line) return false; - if (message.position != this.position) return false; + if (message.getLine() != this.line) return false; + if (message.getColumnOrPosition() != this.position) return false; for (String token : messageParts) { - if (!message.message.contains(token)) return false; + if (!message.getMessage().contains(token)) return false; } return true; } diff --git a/test/core/src/lombok/DirectoryRunner.java b/test/core/src/lombok/DirectoryRunner.java index c896d327..191a7b63 100644 --- a/test/core/src/lombok/DirectoryRunner.java +++ b/test/core/src/lombok/DirectoryRunner.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2010 The Project Lombok Authors. + * Copyright (C) 2009-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -40,12 +40,16 @@ public class DirectoryRunner extends Runner { DELOMBOK, JAVAC, ECJ; } - public interface TestParams { - Compiler getCompiler(); - boolean printErrors(); - File getBeforeDirectory(); - File getAfterDirectory(); - File getMessagesDirectory(); + public static abstract class TestParams { + public abstract Compiler getCompiler(); + public abstract boolean printErrors(); + public abstract File getBeforeDirectory(); + public abstract File getAfterDirectory(); + public abstract File getMessagesDirectory(); + + public boolean accept(File file) { + return true; + } } private static final FileFilter JAVA_FILE_FILTER = new FileFilter() { @@ -76,6 +80,7 @@ public class DirectoryRunner extends Runner { private void addTests(Class<?> testClass) throws Exception { for (File file : params.getBeforeDirectory().listFiles(JAVA_FILE_FILTER)) { + if (!params.accept(file)) continue; Description testDescription = Description.createTestDescription(testClass, file.getName()); description.addChild(testDescription); tests.put(file.getName(), testDescription); diff --git a/test/core/src/lombok/RunTestsViaDelombok.java b/test/core/src/lombok/RunTestsViaDelombok.java index 16eae8d3..17665173 100644 --- a/test/core/src/lombok/RunTestsViaDelombok.java +++ b/test/core/src/lombok/RunTestsViaDelombok.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2010 The Project Lombok Authors. + * Copyright (C) 2009-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,35 +25,21 @@ import java.io.File; import java.io.StringWriter; import java.util.Collection; import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.tools.Diagnostic; -import javax.tools.Diagnostic.Kind; -import javax.tools.DiagnosticListener; -import javax.tools.JavaFileObject; import lombok.delombok.Delombok; +import lombok.javac.CapturingDiagnosticListener; +import lombok.javac.CapturingDiagnosticListener.CompilerMessage; public class RunTestsViaDelombok extends AbstractRunTests { private Delombok delombok = new Delombok(); @Override - public void transformCode(final Collection<CompilerMessage> messages, StringWriter result, final File file) throws Throwable { + public void transformCode(Collection<CompilerMessage> messages, StringWriter result, final File file) throws Throwable { delombok.setVerbose(false); delombok.setForceProcess(true); delombok.setCharset("UTF-8"); - delombok.setDiagnosticsListener(new DiagnosticListener<JavaFileObject>() { - @Override public void report(Diagnostic<? extends JavaFileObject> d) { - String msg = d.getMessage(Locale.ENGLISH); - Matcher m = Pattern.compile( - "^" + Pattern.quote(file.getAbsolutePath()) + - "\\s*:\\s*\\d+\\s*:\\s*(?:warning:\\s*)?(.*)$", Pattern.DOTALL).matcher(msg); - if (m.matches()) msg = m.group(1); - messages.add(new CompilerMessage(d.getLineNumber(), d.getColumnNumber(), d.getKind() == Kind.ERROR, msg)); - } - }); + delombok.setDiagnosticsListener(new CapturingDiagnosticListener(file, messages)); delombok.addFile(file.getAbsoluteFile().getParentFile(), file.getName()); delombok.setSourcepath(file.getAbsoluteFile().getParent()); diff --git a/test/core/src/lombok/RunTestsViaEcj.java b/test/core/src/lombok/RunTestsViaEcj.java index b081d54a..0bf97213 100644 --- a/test/core/src/lombok/RunTestsViaEcj.java +++ b/test/core/src/lombok/RunTestsViaEcj.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 The Project Lombok Authors. + * Copyright (C) 2010-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,6 +33,8 @@ import java.util.Locale; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; +import lombok.javac.CapturingDiagnosticListener.CompilerMessage; + import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.internal.compiler.CompilationResult; import org.eclipse.jdt.internal.compiler.Compiler; @@ -110,7 +112,7 @@ public class RunTestsViaEcj extends AbstractRunTests { CategorizedProblem[] problems = compilationResult.getAllProblems(); if (problems != null) for (CategorizedProblem p : problems) { - messages.add(new CompilerMessage(p.getSourceLineNumber(), p.getSourceStart(), p.isError(), p.getMessage())); + messages.add(new CompilerMessage(p.getSourceLineNumber(), p.getSourceStart(), p.getSourceStart(), p.isError(), p.getMessage())); } CompilationUnitDeclaration cud = compilationUnit_.get(); diff --git a/test/transform/resource/after-delombok/Constructors.java b/test/transform/resource/after-delombok/Constructors.java index d4633dbc..12aa75ab 100644 --- a/test/transform/resource/after-delombok/Constructors.java +++ b/test/transform/resource/after-delombok/Constructors.java @@ -28,6 +28,16 @@ class RequiredArgsConstructorStaticName { return new RequiredArgsConstructorStaticName(x); } } +class RequiredArgsConstructorWithAnnotations { + final int x; + String name; + @java.beans.ConstructorProperties({"x"}) + @Deprecated + @java.lang.SuppressWarnings("all") + public RequiredArgsConstructorWithAnnotations(final int x) { + this.x = x; + } +} class AllArgsConstructor1 { final int x; String name; diff --git a/test/transform/resource/after-delombok/GetterOnMethod.java b/test/transform/resource/after-delombok/GetterOnMethod.java new file mode 100644 index 00000000..4a5b3622 --- /dev/null +++ b/test/transform/resource/after-delombok/GetterOnMethod.java @@ -0,0 +1,24 @@ +class GetterOnMethod { + int i; + int j; + int k; + public @interface Test { + } + @Deprecated + @java.lang.SuppressWarnings("all") + public int getI() { + return this.i; + } + @java.lang.Deprecated + @Test + @java.lang.SuppressWarnings("all") + public int getJ() { + return this.j; + } + @java.lang.Deprecated + @Test + @java.lang.SuppressWarnings("all") + public int getK() { + return this.k; + } +} diff --git a/test/transform/resource/after-delombok/GetterOnMethodErrors.java b/test/transform/resource/after-delombok/GetterOnMethodErrors.java new file mode 100644 index 00000000..86813bd2 --- /dev/null +++ b/test/transform/resource/after-delombok/GetterOnMethodErrors.java @@ -0,0 +1,9 @@ +class PlaceFillerToMakeSurePositionIsRelevant { +} +class GetterOnMethodErrors { + private int test; + @java.lang.SuppressWarnings("all") + public int getTest() { + return this.test; + } +}
\ No newline at end of file diff --git a/test/transform/resource/after-delombok/GetterOnMethodErrors2.java b/test/transform/resource/after-delombok/GetterOnMethodErrors2.java new file mode 100644 index 00000000..639022d0 --- /dev/null +++ b/test/transform/resource/after-delombok/GetterOnMethodErrors2.java @@ -0,0 +1,48 @@ +class GetterOnMethodErrors2 { + private int bad1; + private int bad2; + private int bad3; + private int bad4; + private int good1; + private int good2; + private int good3; + private int good4; + public @interface Test { + } + @java.lang.SuppressWarnings("all") + public int getBad1() { + return this.bad1; + } + @java.lang.SuppressWarnings("all") + public int getBad2() { + return this.bad2; + } + @Deprecated + @java.lang.SuppressWarnings("all") + public int getBad3() { + return this.bad3; + } + @java.lang.SuppressWarnings("all") + public int getBad4() { + return this.bad4; + } + @java.lang.SuppressWarnings("all") + public int getGood1() { + return this.good1; + } + @java.lang.SuppressWarnings("all") + public int getGood2() { + return this.good2; + } + @Deprecated + @java.lang.SuppressWarnings("all") + public int getGood3() { + return this.good3; + } + @Deprecated + @Test + @java.lang.SuppressWarnings("all") + public int getGood4() { + return this.good4; + } +} diff --git a/test/transform/resource/after-delombok/SetterOnMethodOnParam.java b/test/transform/resource/after-delombok/SetterOnMethodOnParam.java new file mode 100644 index 00000000..555bf698 --- /dev/null +++ b/test/transform/resource/after-delombok/SetterOnMethodOnParam.java @@ -0,0 +1,24 @@ +class SetterOnMethodOnParam { + int i; + int j; + int k; + public @interface Test { + } + @Deprecated + @java.lang.SuppressWarnings("all") + public void setI(final int i) { + this.i = i; + } + @java.lang.Deprecated + @Test + @java.lang.SuppressWarnings("all") + public void setJ(@Test final int j) { + this.j = j; + } + @java.lang.Deprecated + @Test + @java.lang.SuppressWarnings("all") + public void setK(@Test final int k) { + this.k = k; + } +} diff --git a/test/transform/resource/after-ecj/Constructors.java b/test/transform/resource/after-ecj/Constructors.java index e994702f..540c2407 100644 --- a/test/transform/resource/after-ecj/Constructors.java +++ b/test/transform/resource/after-ecj/Constructors.java @@ -25,6 +25,14 @@ return new RequiredArgsConstructorStaticName(x); } } +@lombok.RequiredArgsConstructor() class RequiredArgsConstructorWithAnnotations { + final int x; + String name; + public @Deprecated @java.beans.ConstructorProperties({"x"}) @java.lang.SuppressWarnings("all") RequiredArgsConstructorWithAnnotations(final int x) { + super(); + this.x = x; + } +} @lombok.AllArgsConstructor class AllArgsConstructor1 { final int x; String name; diff --git a/test/transform/resource/after-ecj/GetterOnMethod.java b/test/transform/resource/after-ecj/GetterOnMethod.java new file mode 100644 index 00000000..a21f628c --- /dev/null +++ b/test/transform/resource/after-ecj/GetterOnMethod.java @@ -0,0 +1,19 @@ +class GetterOnMethod { + public @interface Test { + } + @lombok.Getter() int i; + @lombok.Getter() int j; + @lombok.Getter() int k; + GetterOnMethod() { + super(); + } + public @Deprecated @java.lang.SuppressWarnings("all") int getI() { + return this.i; + } + public @java.lang.Deprecated @Test @java.lang.SuppressWarnings("all") int getJ() { + return this.j; + } + public @java.lang.Deprecated @Test @java.lang.SuppressWarnings("all") int getK() { + return this.k; + } +} diff --git a/test/transform/resource/after-ecj/GetterOnMethodErrors.java b/test/transform/resource/after-ecj/GetterOnMethodErrors.java new file mode 100644 index 00000000..16c625b5 --- /dev/null +++ b/test/transform/resource/after-ecj/GetterOnMethodErrors.java @@ -0,0 +1,14 @@ +class PlaceFillerToMakeSurePositionIsRelevant { + PlaceFillerToMakeSurePositionIsRelevant() { + super(); + } +} +@lombok.Getter() class GetterOnMethodErrors { + private int test; + GetterOnMethodErrors() { + super(); + } + public @java.lang.SuppressWarnings("all") int getTest() { + return this.test; + } +}
\ No newline at end of file diff --git a/test/transform/resource/after-ecj/GetterOnMethodErrors2.java b/test/transform/resource/after-ecj/GetterOnMethodErrors2.java new file mode 100644 index 00000000..bfaa5dd4 --- /dev/null +++ b/test/transform/resource/after-ecj/GetterOnMethodErrors2.java @@ -0,0 +1,39 @@ +class GetterOnMethodErrors2 { + public @interface Test { + } + private @lombok.Getter() int bad1; + private @lombok.Getter() int bad2; + private @lombok.Getter() int bad3; + private @lombok.Getter() int bad4; + private @lombok.Getter() int good1; + private @lombok.Getter() int good2; + private @lombok.Getter() int good3; + private @lombok.Getter() int good4; + GetterOnMethodErrors2() { + super(); + } + public @java.lang.SuppressWarnings("all") int getBad1() { + return this.bad1; + } + public @java.lang.SuppressWarnings("all") int getBad2() { + return this.bad2; + } + public @java.lang.SuppressWarnings("all") int getBad3() { + return this.bad3; + } + public @java.lang.SuppressWarnings("all") int getBad4() { + return this.bad4; + } + public @java.lang.SuppressWarnings("all") int getGood1() { + return this.good1; + } + public @java.lang.SuppressWarnings("all") int getGood2() { + return this.good2; + } + public @Deprecated @java.lang.SuppressWarnings("all") int getGood3() { + return this.good3; + } + public @Deprecated @Test @java.lang.SuppressWarnings("all") int getGood4() { + return this.good4; + } +}
\ No newline at end of file diff --git a/test/transform/resource/after-ecj/SetterOnMethod.java b/test/transform/resource/after-ecj/SetterOnMethod.java new file mode 100644 index 00000000..8bdff212 --- /dev/null +++ b/test/transform/resource/after-ecj/SetterOnMethod.java @@ -0,0 +1,40 @@ +import lombok.Setter; +class SetterOnMethod { + @lombok.Setter() int i; + @lombok.Setter() int j; + public @Deprecated @java.lang.SuppressWarnings("all") void setI(final int i) { + this.i = i; + } + public @java.lang.Deprecated @java.lang.SuppressWarnings("all") void setJ(final int j) { + this.j = j; + } + SetterOnMethod() { + super(); + } +} +@lombok.Setter() class SetterOnClassOnMethod { + int i; + int j; + public @java.lang.SuppressWarnings("all") void setI(final int i) { + this.i = i; + } + public @java.lang.SuppressWarnings("all") void setJ(final int j) { + this.j = j; + } + SetterOnClassOnMethod() { + super(); + } +} +@lombok.Setter() class SetterOnClassAndOnAField { + int i; + @lombok.Setter() int j; + public @java.lang.Deprecated @java.lang.SuppressWarnings("all") void setJ(final int j) { + this.j = j; + } + public @java.lang.SuppressWarnings("all") void setI(final int i) { + this.i = i; + } + SetterOnClassAndOnAField() { + super(); + } +}
\ No newline at end of file diff --git a/test/transform/resource/after-ecj/SetterOnMethodOnParam.java b/test/transform/resource/after-ecj/SetterOnMethodOnParam.java new file mode 100644 index 00000000..d4ea9f5d --- /dev/null +++ b/test/transform/resource/after-ecj/SetterOnMethodOnParam.java @@ -0,0 +1,19 @@ +class SetterOnMethodOnParam { + public @interface Test { + } + @lombok.Setter() int i; + @lombok.Setter() int j; + @lombok.Setter() int k; + SetterOnMethodOnParam() { + super(); + } + public @Deprecated @java.lang.SuppressWarnings("all") void setI(final int i) { + this.i = i; + } + public @java.lang.Deprecated @Test @java.lang.SuppressWarnings("all") void setJ(final @Test int j) { + this.j = j; + } + public @java.lang.Deprecated @Test @java.lang.SuppressWarnings("all") void setK(final @Test int k) { + this.k = k; + } +}
\ No newline at end of file diff --git a/test/transform/resource/after-ecj/SetterOnParam.java b/test/transform/resource/after-ecj/SetterOnParam.java new file mode 100644 index 00000000..119c8fc3 --- /dev/null +++ b/test/transform/resource/after-ecj/SetterOnParam.java @@ -0,0 +1,40 @@ +import lombok.Setter; +class SetterOnParam { + @lombok.Setter() int i; + @lombok.Setter() int j; + public @java.lang.SuppressWarnings("all") void setI(final @SuppressWarnings("all") int i) { + this.i = i; + } + public @java.lang.SuppressWarnings("all") void setJ(final @java.lang.SuppressWarnings("all") int j) { + this.j = j; + } + SetterOnParam() { + super(); + } +} +@lombok.Setter() class SetterOnClassOnParam { + int i; + int j; + public @java.lang.SuppressWarnings("all") void setI(final int i) { + this.i = i; + } + public @java.lang.SuppressWarnings("all") void setJ(final int j) { + this.j = j; + } + SetterOnClassOnParam() { + super(); + } +} +@lombok.Setter() class SetterOnClassAndOnAFieldParam { + int i; + @lombok.Setter() int j; + public @java.lang.SuppressWarnings("all") void setJ(final @java.lang.SuppressWarnings("all") int j) { + this.j = j; + } + public @java.lang.SuppressWarnings("all") void setI(final int i) { + this.i = i; + } + SetterOnClassAndOnAFieldParam() { + super(); + } +}
\ No newline at end of file diff --git a/test/transform/resource/after-ecj/SetterOnParamAndOnMethod.java b/test/transform/resource/after-ecj/SetterOnParamAndOnMethod.java new file mode 100644 index 00000000..21d22a8f --- /dev/null +++ b/test/transform/resource/after-ecj/SetterOnParamAndOnMethod.java @@ -0,0 +1,9 @@ +class SetterOnParamAndOnMethod { + @lombok.Setter() int i; + public @Deprecated @java.lang.SuppressWarnings("all") void setI(final @SuppressWarnings("all") int i) { + this.i = i; + } + SetterOnParamAndOnMethod() { + super(); + } +}
\ No newline at end of file diff --git a/test/transform/resource/before/Constructors.java b/test/transform/resource/before/Constructors.java index d3ed3504..0ab7b7f0 100644 --- a/test/transform/resource/before/Constructors.java +++ b/test/transform/resource/before/Constructors.java @@ -10,6 +10,10 @@ final int x; String name; } +@lombok.RequiredArgsConstructor(onConstructor=@_(@Deprecated)) class RequiredArgsConstructorWithAnnotations { + final int x; + String name; +} @lombok.AllArgsConstructor class AllArgsConstructor1 { final int x; String name; diff --git a/test/transform/resource/before/GetterOnMethod.java b/test/transform/resource/before/GetterOnMethod.java new file mode 100644 index 00000000..558f3f64 --- /dev/null +++ b/test/transform/resource/before/GetterOnMethod.java @@ -0,0 +1,7 @@ +class GetterOnMethod { + @lombok.Getter(onMethod=@_(@Deprecated)) int i; + @lombok.Getter(onMethod=@_({@java.lang.Deprecated, @Test})) int j, k; + + public @interface Test { + } +} diff --git a/test/transform/resource/before/GetterOnMethodErrors.java b/test/transform/resource/before/GetterOnMethodErrors.java new file mode 100644 index 00000000..ae5d5b54 --- /dev/null +++ b/test/transform/resource/before/GetterOnMethodErrors.java @@ -0,0 +1,6 @@ +class PlaceFillerToMakeSurePositionIsRelevant { +} +@lombok.Getter(onMethod=@_(@Deprecated)) +class GetterOnMethodErrors { + private int test; +} diff --git a/test/transform/resource/before/GetterOnMethodErrors2.java b/test/transform/resource/before/GetterOnMethodErrors2.java new file mode 100644 index 00000000..423183b9 --- /dev/null +++ b/test/transform/resource/before/GetterOnMethodErrors2.java @@ -0,0 +1,12 @@ +class GetterOnMethodErrors2 { + @lombok.Getter(onMethod=@_A_(@Deprecated)) private int bad1; + @lombok.Getter(onMethod=@_(5)) private int bad2; + @lombok.Getter(onMethod=@_({@Deprecated, 5})) private int bad3; + @lombok.Getter(onMethod=@_(bar=@Deprecated)) private int bad4; + @lombok.Getter(onMethod=@_) private int good1; + @lombok.Getter(onMethod=@_()) private int good2; + @lombok.Getter(onMethod=@_(value=@Deprecated)) private int good3; + @lombok.Getter(onMethod=@_(value={@Deprecated, @Test})) private int good4; + public @interface Test { + } +} diff --git a/test/transform/resource/before/SetterOnMethodOnParam.java b/test/transform/resource/before/SetterOnMethodOnParam.java new file mode 100644 index 00000000..70f3dc8c --- /dev/null +++ b/test/transform/resource/before/SetterOnMethodOnParam.java @@ -0,0 +1,7 @@ +class SetterOnMethodOnParam { + @lombok.Setter(onMethod=@_(@Deprecated)) int i; + @lombok.Setter(onMethod=@_({@java.lang.Deprecated, @Test}), onParam=@_(@Test)) int j, k; + + public @interface Test { + } +} diff --git a/test/transform/resource/messages-delombok/GetterOnMethod.java.messages b/test/transform/resource/messages-delombok/GetterOnMethod.java.messages deleted file mode 100644 index db5ef9a6..00000000 --- a/test/transform/resource/messages-delombok/GetterOnMethod.java.messages +++ /dev/null @@ -1,7 +0,0 @@ -3:34 incompatible types -4:44 incompatible types -6:26 incompatible types -11:26 incompatible types -14:44 incompatible types -6:1 'onMethod' is not supported for @Getter on a type. -11:1 'onMethod' is not supported for @Getter on a type. diff --git a/test/transform/resource/messages-delombok/GetterOnMethodErrors.java.messages b/test/transform/resource/messages-delombok/GetterOnMethodErrors.java.messages new file mode 100644 index 00000000..4c82f730 --- /dev/null +++ b/test/transform/resource/messages-delombok/GetterOnMethodErrors.java.messages @@ -0,0 +1 @@ +3:1 'onMethod' is not supported for @Getter on a type.
\ No newline at end of file diff --git a/test/transform/resource/messages-delombok/GetterOnMethodErrors2.java.messages b/test/transform/resource/messages-delombok/GetterOnMethodErrors2.java.messages new file mode 100644 index 00000000..ead040a5 --- /dev/null +++ b/test/transform/resource/messages-delombok/GetterOnMethodErrors2.java.messages @@ -0,0 +1,4 @@ +2:9 The correct format is @Getter(onMethod=@_({@SomeAnnotation, @SomeOtherAnnotation})) +3:9 The correct format is @Getter(onMethod=@_({@SomeAnnotation, @SomeOtherAnnotation})) +4:9 The correct format is @Getter(onMethod=@_({@SomeAnnotation, @SomeOtherAnnotation})) +5:9 The correct format is @Getter(onMethod=@_({@SomeAnnotation, @SomeOtherAnnotation})) diff --git a/test/transform/resource/messages-delombok/ValInBasicFor.java.messages b/test/transform/resource/messages-delombok/ValInBasicFor.java.messages index b69a4a13..9bca1be6 100644 --- a/test/transform/resource/messages-delombok/ValInBasicFor.java.messages +++ b/test/transform/resource/messages-delombok/ValInBasicFor.java.messages @@ -1,3 +1 @@ -6:26 'val' is not allowed in old-style for loops -6:40 'val' is not allowed in old-style for loops 6:53 'val' is not allowed in old-style for loops diff --git a/test/transform/resource/messages-ecj/GetterOnMethod.java.messages b/test/transform/resource/messages-ecj/GetterOnMethod.java.messages deleted file mode 100644 index 4b240da0..00000000 --- a/test/transform/resource/messages-ecj/GetterOnMethod.java.messages +++ /dev/null @@ -1,2 +0,0 @@ -6:0 'onMethod' is not supported for @Getter on a type. -11:0 'onMethod' is not supported for @Getter on a type.
\ No newline at end of file diff --git a/test/transform/resource/messages-ecj/GetterOnMethodErrors.java.messages b/test/transform/resource/messages-ecj/GetterOnMethodErrors.java.messages new file mode 100644 index 00000000..804e8a3c --- /dev/null +++ b/test/transform/resource/messages-ecj/GetterOnMethodErrors.java.messages @@ -0,0 +1 @@ +3:50 'onMethod' is not supported for @Getter on a type.
\ No newline at end of file diff --git a/test/transform/resource/messages-ecj/GetterOnMethodErrors2.java.messages b/test/transform/resource/messages-ecj/GetterOnMethodErrors2.java.messages new file mode 100644 index 00000000..6b949f41 --- /dev/null +++ b/test/transform/resource/messages-ecj/GetterOnMethodErrors2.java.messages @@ -0,0 +1,4 @@ +2:31 The correct format is @Getter(onMethod=@_({@SomeAnnotation, @SomeOtherAnnotation})) +3:93 The correct format is @Getter(onMethod=@_({@SomeAnnotation, @SomeOtherAnnotation})) +4:143 The correct format is @Getter(onMethod=@_({@SomeAnnotation, @SomeOtherAnnotation})) +5:208 The correct format is @Getter(onMethod=@_({@SomeAnnotation, @SomeOtherAnnotation})) diff --git a/test/transform/resource/messages-idempotent/ValInBasicFor.java.messages b/test/transform/resource/messages-idempotent/ValInBasicFor.java.messages index 313a33c0..fb675485 100644 --- a/test/transform/resource/messages-idempotent/ValInBasicFor.java.messages +++ b/test/transform/resource/messages-idempotent/ValInBasicFor.java.messages @@ -1,3 +1 @@ -5:26 'val' is not allowed in old-style for loops -5:40 'val' is not allowed in old-style for loops 5:53 'val' is not allowed in old-style for loops diff --git a/test/transform/src/lombok/transform/TestLombokFilesIdempotent.java b/test/transform/src/lombok/transform/TestLombokFilesIdempotent.java index b47fdefd..d2909943 100644 --- a/test/transform/src/lombok/transform/TestLombokFilesIdempotent.java +++ b/test/transform/src/lombok/transform/TestLombokFilesIdempotent.java @@ -28,7 +28,7 @@ import lombok.DirectoryRunner; import org.junit.runner.RunWith; @RunWith(DirectoryRunner.class) -public class TestLombokFilesIdempotent implements DirectoryRunner.TestParams { +public class TestLombokFilesIdempotent extends DirectoryRunner.TestParams { @Override public File getBeforeDirectory() { return getAfterDirectory(); diff --git a/test/transform/src/lombok/transform/TestSourceFiles.java b/test/transform/src/lombok/transform/TestSourceFiles.java index 3b405676..c3ac0a68 100644 --- a/test/transform/src/lombok/transform/TestSourceFiles.java +++ b/test/transform/src/lombok/transform/TestSourceFiles.java @@ -28,19 +28,23 @@ import lombok.DirectoryRunner; import org.junit.runner.RunWith; @RunWith(DirectoryRunner.class) -public class TestSourceFiles implements DirectoryRunner.TestParams { +public class TestSourceFiles extends DirectoryRunner.TestParams { + @Override public DirectoryRunner.Compiler getCompiler() { return DirectoryRunner.Compiler.DELOMBOK; } + @Override public boolean printErrors() { return true; } + @Override public File getBeforeDirectory() { return new File("test/pretty/resource/before"); } + @Override public File getAfterDirectory() { return new File("test/pretty/resource/after"); } diff --git a/test/transform/src/lombok/transform/TestWithDelombok.java b/test/transform/src/lombok/transform/TestWithDelombok.java index 44ea6ab5..bd8d9d09 100644 --- a/test/transform/src/lombok/transform/TestWithDelombok.java +++ b/test/transform/src/lombok/transform/TestWithDelombok.java @@ -28,7 +28,7 @@ import lombok.DirectoryRunner; import org.junit.runner.RunWith; @RunWith(DirectoryRunner.class) -public class TestWithDelombok implements DirectoryRunner.TestParams { +public class TestWithDelombok extends DirectoryRunner.TestParams { @Override public DirectoryRunner.Compiler getCompiler() { return DirectoryRunner.Compiler.DELOMBOK; diff --git a/test/transform/src/lombok/transform/TestWithEcj.java b/test/transform/src/lombok/transform/TestWithEcj.java index 9463b531..0a4057dd 100644 --- a/test/transform/src/lombok/transform/TestWithEcj.java +++ b/test/transform/src/lombok/transform/TestWithEcj.java @@ -32,7 +32,7 @@ import org.junit.runner.RunWith; // When running inside eclipse's junit tester, you don't actually need to run 'ant dist' after updating code, though. @RunWith(DirectoryRunner.class) -public class TestWithEcj implements DirectoryRunner.TestParams { +public class TestWithEcj extends DirectoryRunner.TestParams { @Override public DirectoryRunner.Compiler getCompiler() { return DirectoryRunner.Compiler.ECJ; diff --git a/website/download.html b/website/download.html index 526fdd3d..bb354c8f 100644 --- a/website/download.html +++ b/website/download.html @@ -81,7 +81,7 @@ <div class="endBar"> </div> <div class="footer"> - <a href="credits.html" class="creditsLink">credits</a> | Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>. + <a href="credits.html" class="creditsLink">credits</a> | Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>. </div> </div> <script type="text/javascript"> diff --git a/website/features/Cleanup.html b/website/features/Cleanup.html index 9094d8ba..d1637dd4 100644 --- a/website/features/Cleanup.html +++ b/website/features/Cleanup.html @@ -61,7 +61,7 @@ </div> <div class="footer"> <a href="index.html">Back to features</a> | <a href="Data.html">Previous feature (@Data)</a> | <a href="Synchronized.html">Next feature (@Synchronized)</a><br /> - <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/Constructor.html b/website/features/Constructor.html index c60d915f..051d730e 100644 --- a/website/features/Constructor.html +++ b/website/features/Constructor.html @@ -82,7 +82,7 @@ </div> <div class="footer"> <a href="index.html">Back to features</a> | <a href="EqualsAndHashCode.html">Previous feature (@EqualsAndHashCode)</a> | <a href="Data.html">Next feature (@Data)</a><br /> - <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2010-2011 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2010-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/Data.html b/website/features/Data.html index 7e694438..8ace96cb 100644 --- a/website/features/Data.html +++ b/website/features/Data.html @@ -76,7 +76,7 @@ </div> <div class="footer"> <a href="index.html">Back to features</a> | <a href="Constructor.html">Previous feature (@<em>X</em>Constructor)</a> | <a href="Cleanup.html">Next feature (@Cleanup)</a><br /> - <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/Delegate.html b/website/features/Delegate.html index 4872c2e9..532f3f54 100644 --- a/website/features/Delegate.html +++ b/website/features/Delegate.html @@ -65,7 +65,7 @@ </div> <div class="footer"> <a href="index.html">Back to features</a> | <a href="val.html">Previous feature (val)</a> | <span class="disabled">Next feature</span><br /> - <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2010-2011 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2010-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/EqualsAndHashCode.html b/website/features/EqualsAndHashCode.html index 12cf25fa..2ef88676 100644 --- a/website/features/EqualsAndHashCode.html +++ b/website/features/EqualsAndHashCode.html @@ -84,7 +84,7 @@ </div> <div class="footer"> <a href="index.html">Back to features</a> | <a href="ToString.html">Previous feature (@ToString)</a> | <a href="Constructor.html">Next feature (@<em>X</em>Constructor)</a><br /> - <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/GetterLazy.html b/website/features/GetterLazy.html index b1d44601..bc5ecb0c 100644 --- a/website/features/GetterLazy.html +++ b/website/features/GetterLazy.html @@ -47,7 +47,7 @@ </div> <div class="footer"> <a href="index.html">Back to features</a> | <a href="GetterSetter.html">Previous feature (@Getter / @Setter)</a> | <a href="ToString.html">Next feature (@ToString)</a><br /> - <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/GetterSetter.html b/website/features/GetterSetter.html index a7dda812..dde3456b 100644 --- a/website/features/GetterSetter.html +++ b/website/features/GetterSetter.html @@ -76,7 +76,7 @@ </div> <div class="footer"> <a href="index.html">Back to features</a> | <span class="disabled">Previous feature</span> | <a href="GetterLazy.html">Next feature (@Getter(lazy=true))</a><br /> - <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/Log.html b/website/features/Log.html index ba0a259c..fb529426 100644 --- a/website/features/Log.html +++ b/website/features/Log.html @@ -59,7 +59,7 @@ </div> <div class="footer"> <a href="index.html">Back to features</a> | <a href="SneakyThrows.html">Previous feature (@SneakyThrows)</a> | <a href="val.html">Next feature (val)</a><br /> - <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/SneakyThrows.html b/website/features/SneakyThrows.html index 9884466b..0f04b7d9 100644 --- a/website/features/SneakyThrows.html +++ b/website/features/SneakyThrows.html @@ -69,7 +69,7 @@ </div> <div class="footer"> <a href="index.html">Back to features</a> | <a href="Synchronized.html">Previous feature (@Synchronized)</a> | <a href="Log.html">Next feature (@Log)</a><br /> - <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/Synchronized.html b/website/features/Synchronized.html index 5970e1b3..4b6ef251 100644 --- a/website/features/Synchronized.html +++ b/website/features/Synchronized.html @@ -60,7 +60,7 @@ </div> <div class="footer"> <a href="index.html">Back to features</a> | <a href="Cleanup.html">Previous feature (@Cleanup)</a> | <a href="SneakyThrows.html">Next feature (@SneakyThrows)</a><br /> - <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/ToString.html b/website/features/ToString.html index 56c544f5..c3b389ba 100644 --- a/website/features/ToString.html +++ b/website/features/ToString.html @@ -69,7 +69,7 @@ </div> <div class="footer"> <a href="index.html">Back to features</a> | <a href="GetterLazy.html">Previous feature (@Getter(lazy=true))</a> | <a href="EqualsAndHashCode.html">Next feature (@EqualsAndHashCode)</a><br /> - <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/delombok.html b/website/features/delombok.html index f98871a4..d8353b9e 100644 --- a/website/features/delombok.html +++ b/website/features/delombok.html @@ -58,7 +58,7 @@ </div> <div class="footer"> <a href="index.html">Back to features</a><br /> - <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2010-2011 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2010-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/experimental/Accessors.html b/website/features/experimental/Accessors.html index f3a7878f..dce77d32 100644 --- a/website/features/experimental/Accessors.html +++ b/website/features/experimental/Accessors.html @@ -85,7 +85,7 @@ </div> <div class="footer"> <a href="index.html">Back to experimental features</a> | <span class="disabled">Previous feature</span> | <a href="ExtensionMethod.html">Next feature (@ExtensionMethod)</a><br /> - <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/experimental/ExtensionMethod.html b/website/features/experimental/ExtensionMethod.html index 0025d795..d5d65e2b 100644 --- a/website/features/experimental/ExtensionMethod.html +++ b/website/features/experimental/ExtensionMethod.html @@ -91,7 +91,7 @@ System.out.println(x.or("Hello, World!"));</pre> </div> <div class="footer"> <a href="index.html">Back to experimental features</a> | <a href="Accessors.html">Previous feature (@Accessors)</a> | <a href="FieldDefaults.html">Next feature (@FieldDefaults)</a><br /> - <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/experimental/FieldDefaults.html b/website/features/experimental/FieldDefaults.html index 94c23a27..eff709ca 100644 --- a/website/features/experimental/FieldDefaults.html +++ b/website/features/experimental/FieldDefaults.html @@ -66,7 +66,7 @@ </div> <div class="footer"> <a href="index.html">Back to experimental features</a> | <a href="ExtensionMethod.html">Previous feature (@ExtensionMethod)</a> | <a href="Wither.html">Next feature (@Wither)</a><br /> - <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/experimental/Value.html b/website/features/experimental/Value.html index 464f0966..a82808e2 100644 --- a/website/features/experimental/Value.html +++ b/website/features/experimental/Value.html @@ -69,7 +69,7 @@ </div> <div class="footer"> <a href="index.html">Back to experimental features</a> | <a href="Wither.html">Previous feature (@Wither)</a> | <span class="disabled">Next feature</span><br /> - <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/experimental/Wither.html b/website/features/experimental/Wither.html index a7b77dab..b0700aab 100644 --- a/website/features/experimental/Wither.html +++ b/website/features/experimental/Wither.html @@ -84,7 +84,7 @@ </div> <div class="footer"> <a href="index.html">Back to experimental features</a> | <a href="FieldDefaults.html">Previous feature (@FieldDefaults)</a> | <a href="Value.html">Next feature (@Value)</a><br /> - <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/experimental/index.html b/website/features/experimental/index.html index 6f180065..acbbdbf6 100644 --- a/website/features/experimental/index.html +++ b/website/features/experimental/index.html @@ -35,7 +35,7 @@ </dl> </div> <div class="footer"> - <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/index.html b/website/features/index.html index f5ba2869..37038ddb 100644 --- a/website/features/index.html +++ b/website/features/index.html @@ -63,7 +63,7 @@ your source files for source-level tools such as javadoc and GWT. More information about how to run delombok, including instructions for build tools can be found at the <a href="delombok.html">delombok page</a>.</div> <div class="footer"> - <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/onX.html b/website/features/onX.html index b001f294..ab72e6f5 100644 --- a/website/features/onX.html +++ b/website/features/onX.html @@ -46,12 +46,14 @@ <h3>Small print</h3><div class="smallprint"> <p> We can't think of any small print for this feature, other than to reiterate: This feature can disappear at any time; if you use this feature, be prepared to adjust your code when we find a nicer way of implementing this feature, or, if a future version of javac forces us to remove this feature entirely with no alternative. + </p><p> + The <code>onX</code> parameter is not legal on any type-wide variant. For example, a <code>@Getter</code> annotation on a class does not support <code>onMethod</code>. </p> </div> </div> <div class="footer"> <a href="index.html">Back to features</a><br /> - <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/features/val.html b/website/features/val.html index 4a04f6fb..cec799e9 100644 --- a/website/features/val.html +++ b/website/features/val.html @@ -51,7 +51,7 @@ </div> <div class="footer"> <a href="index.html">Back to features</a> | <a href="Log.html">Previous feature (@Log)</a> | <a href="Delegate.html">Next feature (@Delegate)</a><br /> - <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2010-2011 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2010-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> </div> diff --git a/website/index.html b/website/index.html index 008d4209..edce2a2d 100644 --- a/website/index.html +++ b/website/index.html @@ -90,7 +90,7 @@ <a href="novideo.html">I can't see the video</a> | <a href="slideshow.html">I don't want to see the video - show me a slideshow instead!</a> </div> <div class="footer"> - <a href="credits.html" class="creditsLink">credits</a> | Copyright © 2009-2012 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>. + <a href="credits.html" class="creditsLink">credits</a> | Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>. </div> </div> <script type="text/javascript"> diff --git a/website/setup/android.html b/website/setup/android.html index 0eb5853e..9aeddfc5 100644 --- a/website/setup/android.html +++ b/website/setup/android.html @@ -79,7 +79,7 @@ java -jar lombok.jar publicApi</pre> <div class="endBar"> </div> <div class="footer"> - <a href="../credits.html" class="creditsLink">credits</a> | Copyright © 2009-2011 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>. + <a href="../credits.html" class="creditsLink">credits</a> | Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>. </div> </div> <script type="text/javascript"> diff --git a/website/setup/ecj.html b/website/setup/ecj.html index a4d20973..774e6e83 100644 --- a/website/setup/ecj.html +++ b/website/setup/ecj.html @@ -49,7 +49,7 @@ java <strong>-javaagent:lombok.jar=ECJ -Xbootclasspath/p:lombok.jar</strong> -ja <div class="endBar"> </div> <div class="footer"> - <a href="../credits.html" class="creditsLink">credits</a> | Copyright © 2009-2011 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>. + <a href="../credits.html" class="creditsLink">credits</a> | Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>. </div> </div> <script type="text/javascript"> diff --git a/website/setup/gwt.html b/website/setup/gwt.html index 27fc2478..9277fef4 100644 --- a/website/setup/gwt.html +++ b/website/setup/gwt.html @@ -52,7 +52,7 @@ java <strong>-javaagent:lombok.jar=ECJ</strong> <em>(rest of arguments)</em> <div class="endBar"> </div> <div class="footer"> - <a href="../credits.html" class="creditsLink">credits</a> | Copyright © 2009-2011 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>. + <a href="../credits.html" class="creditsLink">credits</a> | Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>. </div> </div> <script type="text/javascript"> diff --git a/website/setup/netbeans.html b/website/setup/netbeans.html index 01ee7d4d..0c32968f 100644 --- a/website/setup/netbeans.html +++ b/website/setup/netbeans.html @@ -49,7 +49,7 @@ <div class="endBar"> </div> <div class="footer"> - <a href="../credits.html" class="creditsLink">credits</a> | Copyright © 2009-2011 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>. + <a href="../credits.html" class="creditsLink">credits</a> | Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>. </div> </div> <script type="text/javascript"> diff --git a/website/slideshow.html b/website/slideshow.html index 29cee78b..49e617ac 100644 --- a/website/slideshow.html +++ b/website/slideshow.html @@ -98,7 +98,7 @@ <a href="index.html">I changed my mind - I do want to see the video!</a> </div> <div class="footer"> - <a href="credits.html" class="creditsLink">credits</a> | Copyright © 2009 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>. + <a href="credits.html" class="creditsLink">credits</a> | Copyright © 2009-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>. </div> </div> <script type="text/javascript"> |