From a7bd812893ecb1fa603229d81c924823426ea973 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Fri, 30 Jan 2015 15:43:41 +0100 Subject: [i623] added eclipse code for generating @javax.annotation.Generated, and refactored java impl to reduce DRY violations. -f pretty now includes skipping generation of this annotation, and updated ALL the test cases. --- .../eclipse/handlers/EclipseHandlerUtil.java | 42 +++++++++++----- .../eclipse/handlers/HandleEqualsAndHashCode.java | 3 +- src/core/lombok/javac/handlers/HandleLog.java | 2 +- .../lombok/javac/handlers/HandleSynchronized.java | 2 +- .../lombok/javac/handlers/JavacHandlerUtil.java | 57 +++++++++++----------- src/delombok/lombok/delombok/Delombok.java | 5 +- .../lombok/delombok/FormatPreferences.java | 16 +++--- 7 files changed, 73 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 87e35269..1b27fce5 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -48,6 +48,7 @@ import lombok.core.TypeResolver; import lombok.core.configuration.NullCheckExceptionType; import lombok.core.debug.ProblemReporter; import lombok.core.handlers.HandlerUtil; +import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAST; import lombok.eclipse.EclipseNode; import lombok.experimental.Accessors; @@ -1213,8 +1214,9 @@ public class EclipseHandlerUtil { * Inserts a field into an existing type. The type must represent a {@code TypeDeclaration}. * The field carries the @{@link SuppressWarnings}("all") annotation. */ - public static EclipseNode injectFieldSuppressWarnings(EclipseNode type, FieldDeclaration field) { - field.annotations = createSuppressWarningsAll(field, field.annotations); + public static EclipseNode injectFieldAndMarkGenerated(EclipseNode type, FieldDeclaration field) { + field.annotations = addSuppressWarningsAll(field, field.annotations); + field.annotations = addGenerated(field, field.annotations); return injectField(type, field); } @@ -1259,7 +1261,8 @@ public class EclipseHandlerUtil { * Inserts a method into an existing type. The type must represent a {@code TypeDeclaration}. */ public static EclipseNode injectMethod(EclipseNode type, AbstractMethodDeclaration method) { - method.annotations = createSuppressWarningsAll(method, method.annotations); + method.annotations = addSuppressWarningsAll(method, method.annotations); + method.annotations = addGenerated(method, method.annotations); TypeDeclaration parent = (TypeDeclaration) type.get(); if (parent.methods == null) { @@ -1301,9 +1304,10 @@ public class EclipseHandlerUtil { * @param type New type (class, interface, etc) to inject. */ public static EclipseNode injectType(final EclipseNode typeNode, final TypeDeclaration type) { - type.annotations = createSuppressWarningsAll(type, type.annotations); + type.annotations = addSuppressWarningsAll(type, type.annotations); + type.annotations = addGenerated(type, type.annotations); TypeDeclaration parent = (TypeDeclaration) typeNode.get(); - + if (parent.memberTypes == null) { parent.memberTypes = new TypeDeclaration[] { type }; } else { @@ -1317,8 +1321,20 @@ public class EclipseHandlerUtil { } private static final char[] ALL = "all".toCharArray(); + private static final char[] LOMBOK = "lombok".toCharArray(); + private static final char[][] JAVAX_ANNOTATION_GENERATED = Eclipse.fromQualifiedName("javax.annotation.Generated"); + + public static Annotation[] addSuppressWarningsAll(ASTNode source, Annotation[] originalAnnotationArray) { + return addAnnotation(source, originalAnnotationArray, TypeConstants.JAVA_LANG_SUPPRESSWARNINGS, new StringLiteral(ALL, 0, 0, 0)); + } - public static Annotation[] createSuppressWarningsAll(ASTNode source, Annotation[] originalAnnotationArray) { + public static Annotation[] addGenerated(ASTNode source, Annotation[] originalAnnotationArray) { + return addAnnotation(source, originalAnnotationArray, JAVAX_ANNOTATION_GENERATED, new StringLiteral(LOMBOK, 0, 0, 0)); + } + + private static Annotation[] addAnnotation(ASTNode source, Annotation[] originalAnnotationArray, char[][] annotationTypeFqn, Expression arg) { + char[] simpleName = annotationTypeFqn[annotationTypeFqn.length - 1]; + if (originalAnnotationArray != null) for (Annotation ann : originalAnnotationArray) { char[] lastToken = null; @@ -1329,20 +1345,24 @@ public class EclipseHandlerUtil { lastToken = ((SingleTypeReference) ann.type).token; } - if (lastToken != null && new String(lastToken).equals("SuppressWarnings")) return originalAnnotationArray; + if (lastToken != null && Arrays.equals(simpleName, lastToken)) return originalAnnotationArray; } int pS = source.sourceStart, pE = source.sourceEnd; long p = (long)pS << 32 | pE; - long[] poss = new long[3]; + long[] poss = new long[annotationTypeFqn.length]; Arrays.fill(poss, p); - QualifiedTypeReference suppressWarningsType = new QualifiedTypeReference(TypeConstants.JAVA_LANG_SUPPRESSWARNINGS, poss); + QualifiedTypeReference suppressWarningsType = new QualifiedTypeReference(annotationTypeFqn, poss); setGeneratedBy(suppressWarningsType, source); SingleMemberAnnotation ann = new SingleMemberAnnotation(suppressWarningsType, pS); ann.declarationSourceEnd = pE; - ann.memberValue = new StringLiteral(ALL, pS, pE, 0); + if (arg != null) { + arg.sourceStart = pS; + arg.sourceEnd = pE; + ann.memberValue = arg; + setGeneratedBy(ann.memberValue, source); + } setGeneratedBy(ann, source); - setGeneratedBy(ann.memberValue, source); if (originalAnnotationArray == null) return new Annotation[] { ann }; Annotation[] newAnnotationArray = new Annotation[originalAnnotationArray.length + 1]; System.arraycopy(originalAnnotationArray, 0, newAnnotationArray, 0, originalAnnotationArray.length); diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java index e1b02051..7e2ff513 100644 --- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2014 The Project Lombok Authors. + * Copyright (C) 2009-2015 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 @@ -561,7 +561,6 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler { JCVariableDecl fieldDecl = recursiveSetGeneratedBy(maker.VarDef( maker.Modifiers(Flags.PRIVATE | Flags.FINAL | (isStatic ? Flags.STATIC : 0)), methodNode.toName(lockName), objectType, newObjectArray), ast, context); - injectFieldSuppressWarnings(methodNode.up(), fieldDecl); + injectFieldAndMarkGenerated(methodNode.up(), fieldDecl); } if (method.body == null) return; diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index bf364641..a6bc388a 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -69,7 +69,6 @@ import com.sun.tools.javac.tree.JCTree.JCExpressionStatement; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCIdent; import com.sun.tools.javac.tree.JCTree.JCImport; -import com.sun.tools.javac.tree.JCTree.JCLiteral; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; import com.sun.tools.javac.tree.JCTree.JCModifiers; @@ -818,7 +817,7 @@ public class JavacHandlerUtil { * The field carries the @{@link SuppressWarnings}("all") annotation. * Also takes care of updating the JavacAST. */ - public static void injectFieldSuppressWarnings(JavacNode typeNode, JCVariableDecl field) { + public static void injectFieldAndMarkGenerated(JavacNode typeNode, JCVariableDecl field) { injectField(typeNode, field, true); } @@ -831,10 +830,13 @@ public class JavacHandlerUtil { return injectField(typeNode, field, false); } - private static JavacNode injectField(JavacNode typeNode, JCVariableDecl field, boolean addSuppressWarnings) { + private static JavacNode injectField(JavacNode typeNode, JCVariableDecl field, boolean addGenerated) { JCClassDecl type = (JCClassDecl) typeNode.get(); - if (addSuppressWarnings) addSuppressWarningsAll(field.mods, typeNode, field.pos, getGeneratedBy(field), typeNode.getContext()); + if (addGenerated) { + addSuppressWarningsAll(field.mods, typeNode, field.pos, getGeneratedBy(field), typeNode.getContext()); + addGenerated(field.mods, typeNode, field.pos, getGeneratedBy(field), typeNode.getContext()); + } List insertAfter = null; List insertBefore = type.defs; @@ -950,44 +952,41 @@ public class JavacHandlerUtil { public static void addSuppressWarningsAll(JCModifiers mods, JavacNode node, int pos, JCTree source, Context context) { if (!LombokOptionsFactory.getDelombokOptions(context).getFormatPreferences().generateSuppressWarnings()) return; - for (JCAnnotation ann : mods.annotations) { - JCTree annType = ann.getAnnotationType(); - Name lastPart = null; - if (annType instanceof JCIdent) lastPart = ((JCIdent) annType).name; - else if (annType instanceof JCFieldAccess) lastPart = ((JCFieldAccess) annType).name; - - if (lastPart != null && lastPart.contentEquals("SuppressWarnings")) return; - } - JavacTreeMaker maker = node.getTreeMaker(); - JCExpression suppressWarningsType = genJavaLangTypeRef(node, "SuppressWarnings"); - JCLiteral allLiteral = maker.Literal("all"); - suppressWarningsType.pos = pos; - allLiteral.pos = pos; - JCAnnotation annotation = recursiveSetGeneratedBy(maker.Annotation(suppressWarningsType, List.of(allLiteral)), source, context); - annotation.pos = pos; - mods.annotations = mods.annotations.append(annotation); + addAnnotation(mods, node, pos, source, context, "java.lang.SuppressWarnings", node.getTreeMaker().Literal("all")); } - + public static void addGenerated(JCModifiers mods, JavacNode node, int pos, JCTree source, Context context) { if (!LombokOptionsFactory.getDelombokOptions(context).getFormatPreferences().generateGenerated()) return; + addAnnotation(mods, node, pos, source, context, "javax.annotation.Generated", node.getTreeMaker().Literal("lombok")); + } + + private static void addAnnotation(JCModifiers mods, JavacNode node, int pos, JCTree source, Context context, String annotationTypeFqn, JCExpression arg) { + boolean isJavaLangBased; + String simpleName; { + int idx = annotationTypeFqn.lastIndexOf('.'); + simpleName = idx == -1 ? annotationTypeFqn : annotationTypeFqn.substring(idx + 1); + + isJavaLangBased = idx == 9 && annotationTypeFqn.regionMatches(0, "java.lang.", 0, 10); + } + for (JCAnnotation ann : mods.annotations) { JCTree annType = ann.getAnnotationType(); Name lastPart = null; if (annType instanceof JCIdent) lastPart = ((JCIdent) annType).name; else if (annType instanceof JCFieldAccess) lastPart = ((JCFieldAccess) annType).name; - - if (lastPart != null && lastPart.contentEquals("Generated")) return; + + if (lastPart != null && lastPart.contentEquals(simpleName)) return; } JavacTreeMaker maker = node.getTreeMaker(); - JCExpression generatedType = chainDots(node, "javax", "annotation", "Generated"); - JCExpression lombokLiteral = maker.Literal("lombok"); - generatedType.pos = pos; - lombokLiteral.pos = pos; - JCAnnotation annotation = recursiveSetGeneratedBy(maker.Annotation(generatedType, List.of(lombokLiteral)), source, context); + JCExpression annType = isJavaLangBased ? genJavaLangTypeRef(node, simpleName) : chainDotsString(node, annotationTypeFqn); + annType.pos = pos; + if (arg != null) arg.pos = pos; + List argList = arg != null ? List.of(arg) : List.nil(); + JCAnnotation annotation = recursiveSetGeneratedBy(maker.Annotation(annType, argList), source, context); annotation.pos = pos; mods.annotations = mods.annotations.append(annotation); } - + private static List addAllButOne(List defs, int idx) { ListBuffer out = new ListBuffer(); int i = 0; diff --git a/src/delombok/lombok/delombok/Delombok.java b/src/delombok/lombok/delombok/Delombok.java index 059bb004..514fc2ec 100644 --- a/src/delombok/lombok/delombok/Delombok.java +++ b/src/delombok/lombok/delombok/Delombok.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2010 The Project Lombok Authors. + * Copyright (C) 2009-2015 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 @@ -204,7 +204,7 @@ public class Delombok { System.out.println(indentAndWordbreak(e.getValue(), 4, 70)); } System.out.println("Example: -f indent:4 -f emptyLines:indent"); - System.out.println("The '-f pretty' option is shorthand for '-f suppressWarnings:skip -f danceAroundIdeChecks:skip -f generateDelombokComment:skip -f javaLangAsFQN:skip'"); + System.out.println("The '-f pretty' option is shorthand for '-f suppressWarnings:skip -f generated:skip -f danceAroundIdeChecks:skip -f generateDelombokComment:skip -f javaLangAsFQN:skip'"); System.exit(0); return; } @@ -301,6 +301,7 @@ public class Delombok { if (prettyEnabled) { if (!formatPrefs.containsKey("suppresswarnings")) formatPrefs.put("suppresswarnings", "skip"); + if (!formatPrefs.containsKey("generated")) formatPrefs.put("generated", "skip"); if (!formatPrefs.containsKey("dancearoundidechecks")) formatPrefs.put("dancearoundidechecks", "skip"); if (!formatPrefs.containsKey("generatedelombokcomment")) formatPrefs.put("generatedelombokcomment", "skip"); if (!formatPrefs.containsKey("javalangasfqn")) formatPrefs.put("javalangasfqn", "skip"); diff --git a/src/delombok/lombok/delombok/FormatPreferences.java b/src/delombok/lombok/delombok/FormatPreferences.java index caacc246..1479a740 100644 --- a/src/delombok/lombok/delombok/FormatPreferences.java +++ b/src/delombok/lombok/delombok/FormatPreferences.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 The Project Lombok Authors. + * Copyright (C) 2013-2015 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 @@ -43,11 +43,11 @@ public final class FormatPreferences { keys.put("emptyLines", "Either 'indent' or 'blank'. indent means: Indent an empty line to the right level. Default: 'blank'"); keys.put("finalParams", "Either 'generate' or 'skip'. generate means: All lombok-generated methods set all parameters to final. Default: 'generate'"); keys.put("constructorProperties", "Either 'generate' or 'skip'. generate means: All lombok-generated constructors with 1 or more arguments get an @ConstructorProperties annotation. Default: 'generate'"); - keys.put("suppressWarnings", "Either 'generate' or 'skip'. generate means: All lombok-generated methods get a @SuppressWarnings annotation. Default: 'generate'"); + keys.put("suppressWarnings", "Either 'generate' or 'skip'. generate means: All lombok-generated methods, types, and fields get a @SuppressWarnings annotation. Default: 'generate'"); + keys.put("generated", "Either 'generate' or 'skip'. generate means: All lombok-generated methods, types, and fields get a @Generated(\"lombok\") annotation. Default: 'generate'"); keys.put("danceAroundIdeChecks", "Either 'generate' or 'skip'. generate means: Lombok will intentionally obfuscate some generated code to avoid IDE warnings. Default: 'generate'"); keys.put("generateDelombokComment", "Either 'generate' or 'skip'. generate means: Any file modified by delombok will have a comment stating this at the top. Default: 'generate'"); keys.put("javaLangAsFQN", "Either 'generate' or 'skip'. generate means: Any generated reference to java.lang classes are prefixed with `java.lang.`. Default: 'generate'"); - keys.put("generated", "Either 'generate' or 'skip'. generate means: All lombok-generated methods get a @Generated(\"lombok\") annotation. Default: 'generate'"); KEYS = Collections.unmodifiableMap(keys); } @@ -84,10 +84,10 @@ public final class FormatPreferences { this.generateFinalParams = unrollBoolean(preferences, "finalParams", "generate", "skip", true); this.generateConstructorProperties = unrollBoolean(preferences, "constructorProperties", "generate", "skip", true); this.generateSuppressWarnings = unrollBoolean(preferences, "suppressWarnings", "generate", "skip", true); + this.generateGenerated = unrollBoolean(preferences, "generated", "generate", "skip", true); this.danceAroundIdeChecks = unrollBoolean(preferences, "danceAroundIdeChecks", "generate", "skip", true); this.generateDelombokComment = unrollBoolean(preferences, "generateDelombokComment", "generate", "skip", true); this.javaLangAsFqn = unrollBoolean(preferences, "javaLangAsFQN", "generate", "skip", true); - this.generateGenerated = unrollBoolean(preferences, "generated", "generate", "skip", true); } private static boolean unrollBoolean(Map preferences, String name, String trueStr, String falseStr, boolean defaultVal) { @@ -115,6 +115,10 @@ public final class FormatPreferences { return generateSuppressWarnings; } + public boolean generateGenerated() { + return generateGenerated; + } + public boolean generateFinalParams() { return generateFinalParams; } @@ -134,8 +138,4 @@ public final class FormatPreferences { public boolean generateConstructorProperties() { return generateConstructorProperties; } - - public boolean generateGenerated() { - return generateGenerated; - } } -- cgit