diff options
9 files changed, 100 insertions, 41 deletions
diff --git a/src/core/lombok/javac/LombokOptions.java b/src/core/lombok/javac/LombokOptions.java index c73edc0f..60d0ce5e 100644 --- a/src/core/lombok/javac/LombokOptions.java +++ b/src/core/lombok/javac/LombokOptions.java @@ -22,9 +22,10 @@ package lombok.javac; import java.util.HashSet; -import java.util.Map; import java.util.Set; +import lombok.delombok.FormatPreferences; + import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Options; @@ -32,17 +33,17 @@ import com.sun.tools.javac.util.Options; public abstract class LombokOptions extends Options { private boolean deleteLombokAnnotations = true; private final Set<JCCompilationUnit> changed = new HashSet<JCCompilationUnit>(); - private Map<String, String> formatPreferences = null; + private FormatPreferences formatPreferences = new FormatPreferences(null); public boolean isChanged(JCCompilationUnit ast) { return changed.contains(ast); } - public void setFormatPreferences(Map<String, String> formatPreferences) { + public void setFormatPreferences(FormatPreferences formatPreferences) { this.formatPreferences = formatPreferences; } - public Map<String, String> getFormatPreferences() { + public FormatPreferences getFormatPreferences() { return this.formatPreferences; } diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java index e48896d9..0caba524 100644 --- a/src/core/lombok/javac/handlers/HandleConstructor.java +++ b/src/core/lombok/javac/handlers/HandleConstructor.java @@ -235,7 +235,8 @@ public class HandleConstructor { Name rawName = field.name; List<JCAnnotation> nonNulls = findAnnotations(fieldNode, TransformationsUtil.NON_NULL_PATTERN); List<JCAnnotation> nullables = findAnnotations(fieldNode, TransformationsUtil.NULLABLE_PATTERN); - JCVariableDecl param = maker.VarDef(maker.Modifiers(Flags.FINAL | Flags.PARAMETER, nonNulls.appendList(nullables)), fieldName, field.vartype, null); + long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext()); + JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, nonNulls.appendList(nullables)), fieldName, field.vartype, null); params.append(param); JCFieldAccess thisX = maker.Select(maker.Ident(fieldNode.toName("this")), rawName); JCAssign assign = maker.Assign(thisX, maker.Ident(fieldName)); @@ -297,7 +298,8 @@ public class HandleConstructor { JCExpression pType = cloneType(maker, field.vartype, source, typeNode.getContext()); List<JCAnnotation> nonNulls = findAnnotations(fieldNode, TransformationsUtil.NON_NULL_PATTERN); List<JCAnnotation> nullables = findAnnotations(fieldNode, TransformationsUtil.NULLABLE_PATTERN); - JCVariableDecl param = maker.VarDef(maker.Modifiers(Flags.FINAL | Flags.PARAMETER, nonNulls.appendList(nullables)), fieldName, pType, null); + long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext()); + JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, nonNulls.appendList(nullables)), fieldName, pType, null); params.append(param); args.append(maker.Ident(fieldName)); } diff --git a/src/core/lombok/javac/handlers/HandleDelegate.java b/src/core/lombok/javac/handlers/HandleDelegate.java index 1073541f..e306460f 100644 --- a/src/core/lombok/javac/handlers/HandleDelegate.java +++ b/src/core/lombok/javac/handlers/HandleDelegate.java @@ -305,7 +305,8 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> { int idx = 0; for (TypeMirror param : sig.type.getParameterTypes()) { - JCModifiers paramMods = maker.Modifiers(Flags.FINAL | Flags.PARAMETER); + long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, annotation.getContext()); + JCModifiers paramMods = maker.Modifiers(flags); String[] paramNames = sig.getParameterNames(); Name name = annotation.toName(paramNames[idx++]); params.append(maker.VarDef(paramMods, name, JavacResolution.typeToJCTree((Type) param, annotation.getAst(), true), null)); diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index 8e8494d0..64aff6d6 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -228,10 +228,11 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas Name primeName = typeNode.toName(PRIME_NAME); Name resultName = typeNode.toName(RESULT_NAME); + long finalFlag = JavacHandlerUtil.addFinalIfNeeded(0L, typeNode.getContext()); + /* final int PRIME = 31; */ { if (!fields.isEmpty() || callSuper) { - statements.append(maker.VarDef(maker.Modifiers(Flags.FINAL), - primeName, maker.TypeIdent(CTC_INT), maker.Literal(31))); + statements.append(maker.VarDef(maker.Modifiers(finalFlag), primeName, maker.TypeIdent(CTC_INT), maker.Literal(31))); } } @@ -258,7 +259,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas break; case LONG: { Name dollarFieldName = dollar.append(((JCVariableDecl)fieldNode.get()).name); - statements.append(maker.VarDef(maker.Modifiers(Flags.FINAL), dollarFieldName, maker.TypeIdent(CTC_LONG), fieldAccessor)); + statements.append(maker.VarDef(maker.Modifiers(finalFlag), dollarFieldName, maker.TypeIdent(CTC_LONG), fieldAccessor)); statements.append(createResultCalculation(typeNode, longToIntForHashCode(maker, maker.Ident(dollarFieldName), maker.Ident(dollarFieldName)))); } break; @@ -276,7 +277,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas List.<JCExpression>nil(), chainDots(typeNode, "java", "lang", "Double", "doubleToLongBits"), List.of(fieldAccessor)); - statements.append(maker.VarDef(maker.Modifiers(Flags.FINAL), dollarFieldName, maker.TypeIdent(CTC_LONG), init)); + statements.append(maker.VarDef(maker.Modifiers(finalFlag), dollarFieldName, maker.TypeIdent(CTC_LONG), init)); statements.append(createResultCalculation(typeNode, longToIntForHashCode(maker, maker.Ident(dollarFieldName), maker.Ident(dollarFieldName)))); } break; @@ -302,7 +303,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas /* $fieldName == null ? 0 : $fieldName.hashCode() */ Name dollarFieldName = dollar.append(((JCVariableDecl)fieldNode.get()).name); - statements.append(maker.VarDef(maker.Modifiers(Flags.FINAL), dollarFieldName, chainDots(typeNode, "java", "lang", "Object"), fieldAccessor)); + statements.append(maker.VarDef(maker.Modifiers(finalFlag), dollarFieldName, chainDots(typeNode, "java", "lang", "Object"), fieldAccessor)); JCExpression hcCall = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(dollarFieldName), typeNode.toName("hashCode")), List.<JCExpression>nil()); @@ -370,8 +371,10 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas JCExpression objectType = chainDots(typeNode, "java", "lang", "Object"); JCExpression returnType = maker.TypeIdent(CTC_BOOLEAN); + long finalFlag = JavacHandlerUtil.addFinalIfNeeded(0L, typeNode.getContext()); + ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); - final List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(Flags.FINAL | Flags.PARAMETER), oName, objectType, null)); + final List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(finalFlag | Flags.PARAMETER), oName, objectType, null)); /* if (o == this) return true; */ { statements.append(maker.If(maker.Binary(CTC_EQUAL, maker.Ident(oName), @@ -403,7 +406,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas } statements.append( - maker.VarDef(maker.Modifiers(Flags.FINAL), otherName, selfType1, maker.TypeCast(selfType2, maker.Ident(oName)))); + maker.VarDef(maker.Modifiers(finalFlag), otherName, selfType1, maker.TypeCast(selfType2, maker.Ident(oName)))); } } @@ -468,8 +471,8 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas Name thisDollarFieldName = thisDollar.append(fieldName); Name otherDollarFieldName = otherDollar.append(fieldName); - statements.append(maker.VarDef(maker.Modifiers(Flags.FINAL), thisDollarFieldName, chainDots(typeNode, "java", "lang", "Object"), thisFieldAccessor)); - statements.append(maker.VarDef(maker.Modifiers(Flags.FINAL), otherDollarFieldName, chainDots(typeNode, "java", "lang", "Object"), otherFieldAccessor)); + statements.append(maker.VarDef(maker.Modifiers(finalFlag), thisDollarFieldName, chainDots(typeNode, "java", "lang", "Object"), thisFieldAccessor)); + statements.append(maker.VarDef(maker.Modifiers(finalFlag), otherDollarFieldName, chainDots(typeNode, "java", "lang", "Object"), otherFieldAccessor)); JCExpression thisEqualsNull = maker.Binary(CTC_EQUAL, maker.Ident(thisDollarFieldName), maker.Literal(CTC_BOT, null)); JCExpression otherNotEqualsNull = maker.Binary(CTC_NOT_EQUAL, maker.Ident(otherDollarFieldName), maker.Literal(CTC_BOT, null)); @@ -501,7 +504,8 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas Name canEqualName = typeNode.toName("canEqual"); JCExpression objectType = chainDots(typeNode, "java", "lang", "Object"); Name otherName = typeNode.toName("other"); - List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(Flags.FINAL | Flags.PARAMETER), otherName, objectType, null)); + long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext()); + List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(flags), otherName, objectType, null)); JCBlock body = maker.Block(0, List.<JCStatement>of( maker.Return(maker.TypeTest(maker.Ident(otherName), createTypeReference(typeNode))))); diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index d14d1458..5dd6ec69 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -211,7 +211,8 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { Name methodName = field.toName(setterName); List<JCAnnotation> annsOnParam = copyAnnotations(onParam).appendList(nonNulls).appendList(nullables); - JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(Flags.FINAL | Flags.PARAMETER, annsOnParam), fieldDecl.name, fieldDecl.vartype, null); + long flags = JavacHandlerUtil.addFinalIfNeeded(0L, field.getContext()); + JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(flags, annsOnParam), fieldDecl.name, fieldDecl.vartype, null); if (nonNulls.isEmpty()) { statements.append(treeMaker.Exec(assign)); diff --git a/src/core/lombok/javac/handlers/HandleWither.java b/src/core/lombok/javac/handlers/HandleWither.java index 53ba39de..f2e51473 100644 --- a/src/core/lombok/javac/handlers/HandleWither.java +++ b/src/core/lombok/javac/handlers/HandleWither.java @@ -214,7 +214,8 @@ public class HandleWither extends JavacAnnotationHandler<Wither> { Name methodName = field.toName(witherName); List<JCAnnotation> annsOnParam = copyAnnotations(onParam).appendList(nonNulls).appendList(nullables); - JCVariableDecl param = maker.VarDef(maker.Modifiers(Flags.FINAL | Flags.PARAMETER, annsOnParam), fieldDecl.name, fieldDecl.vartype, null); + long flags = JavacHandlerUtil.addFinalIfNeeded(0L, field.getContext()); + JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, annsOnParam), fieldDecl.name, fieldDecl.vartype, null); JCExpression selfType = cloneSelfType(field); if (selfType == null) return null; diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index d61174ae..8a125fb6 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -43,6 +43,7 @@ import lombok.core.AnnotationValues; import lombok.core.AnnotationValues.AnnotationValue; import lombok.core.TransformationsUtil; import lombok.core.TypeResolver; +import lombok.delombok.LombokOptionsFactory; import lombok.experimental.Accessors; import lombok.javac.Javac; import lombok.javac.JavacNode; @@ -892,7 +893,15 @@ public class JavacHandlerUtil { return typeNode.add(type, Kind.TYPE); } + public static long addFinalIfNeeded(long flags, Context context) { + boolean addFinal = LombokOptionsFactory.getDelombokOptions(context).getFormatPreferences().generateFinalParams(); + + if (addFinal) flags |= Flags.FINAL; + return flags; + } + private static void addSuppressWarningsAll(JCModifiers mods, JavacNode node, int pos, JCTree source, Context context) { + if (!LombokOptionsFactory.getDelombokOptions(context).getFormatPreferences().generateSuppressWarnings()) return; JavacTreeMaker maker = node.getTreeMaker(); JCExpression suppressWarningsType = chainDots(node, "java", "lang", "SuppressWarnings"); JCLiteral allLiteral = maker.Literal("all"); diff --git a/src/delombok/lombok/delombok/Delombok.java b/src/delombok/lombok/delombok/Delombok.java index 23400771..ef2d2f38 100644 --- a/src/delombok/lombok/delombok/Delombok.java +++ b/src/delombok/lombok/delombok/Delombok.java @@ -58,6 +58,7 @@ import com.sun.tools.javac.util.Context; import com.zwitserloot.cmdreader.CmdReader; import com.zwitserloot.cmdreader.Description; import com.zwitserloot.cmdreader.Excludes; +import com.zwitserloot.cmdreader.FullName; import com.zwitserloot.cmdreader.InvalidCommandLineException; import com.zwitserloot.cmdreader.Mandatory; import com.zwitserloot.cmdreader.Sequential; @@ -91,9 +92,12 @@ public class Delombok { private boolean verbose; @Shorthand("f") - @Description("Sets formatting rules. Use 'help' or 'list' to list all available rules. Unset format rules are inferred by scanning the source for usages.") + @Description("Sets formatting rules. Use --format-help to list all available rules. Unset format rules are inferred by scanning the source for usages.") private List<String> format = new ArrayList<String>(); + @FullName("format-help") + private boolean formatHelp; + @Shorthand("q") @Description("No warnings or errors will be emitted to standard error") @Excludes("verbose") @@ -109,7 +113,7 @@ public class Delombok { @Shorthand("d") @Description("Directory to save delomboked files to") - @Mandatory(onlyIfNot={"print", "help"}) + @Mandatory(onlyIfNot={"print", "help", "format-help"}) private String target; @Shorthand("c") @@ -176,7 +180,7 @@ public class Delombok { return; } - if (args.help || args.input.isEmpty()) { + if (args.help || (args.input.isEmpty() && !args.formatHelp)) { if (!args.help) System.err.println("ERROR: no files or directories to delombok specified."); System.err.println(reader.generateCommandLineHelp("delombok")); System.exit(args.help ? 0 : 1); @@ -193,20 +197,20 @@ public class Delombok { Map<String, String> formatPrefs = new HashMap<String, String>(); - for (String format : args.format) { - if ("help".equalsIgnoreCase(format) || "list".equalsIgnoreCase(format)) { - System.out.println("Available format keys (to use, -f key:value -f key2:value2 -f ... ):"); - for (Map.Entry<String, String> e : FormatPreferences.getKeysAndDescriptions().entrySet()) { - System.out.print(" "); - System.out.print(e.getKey()); - System.out.println(":"); - System.out.println(indentAndWordbreak(e.getValue(), 4, 70)); - } - System.out.println("Example: -f indent:4 -f emptyLines:indent"); - System.exit(0); - return; + if (args.formatHelp) { + System.out.println("Available format keys (to use, -f key:value -f key2:value2 -f ... ):"); + for (Map.Entry<String, String> e : FormatPreferences.getKeysAndDescriptions().entrySet()) { + System.out.print(" "); + System.out.print(e.getKey()); + System.out.println(":"); + System.out.println(indentAndWordbreak(e.getValue(), 4, 70)); } - + System.out.println("Example: -f indent:4 -f emptyLines:indent"); + System.exit(0); + return; + } + + for (String format : args.format) { int idx = format.indexOf(':'); if (idx == -1) { System.err.println("Format keys need to be 2 values separated with a colon. Try -f help."); @@ -438,7 +442,7 @@ public class Delombok { if (classpath != null) options.putJavacOption("CLASSPATH", classpath); if (sourcepath != null) options.putJavacOption("SOURCEPATH", sourcepath); if (bootclasspath != null) options.putJavacOption("BOOTCLASSPATH", bootclasspath); - options.setFormatPreferences(formatPrefs); + options.setFormatPreferences(new FormatPreferences(formatPrefs)); options.put("compilePolicy", "check"); CommentCatcher catcher = CommentCatcher.create(context); diff --git a/src/delombok/lombok/delombok/FormatPreferences.java b/src/delombok/lombok/delombok/FormatPreferences.java index e733151d..2df0ac60 100644 --- a/src/delombok/lombok/delombok/FormatPreferences.java +++ b/src/delombok/lombok/delombok/FormatPreferences.java @@ -28,17 +28,25 @@ import java.util.Map; public final class FormatPreferences { private final String indent; - private final boolean filledEmpties; + private final Boolean filledEmpties; + private final boolean generateSuppressWarnings; + private final boolean generateFinalParams; static final Map<String, String> KEYS; static { Map<String, String> keys = new LinkedHashMap<String, String>(); keys.put("indent", "The indent to use. 'tab' can be used to represent 1 tab. A number means that many spaces. Default: 'tab'"); keys.put("emptyLines", "Either 'indent' or 'blank'. indent means: Indent an empty line to the right level. Default: 'blank'"); + keys.put("suppressWarnings", "Either 'generate' or 'skip'. generate means: All lombok-generated methods get a @SuppressWarnings annotation. Default: 'generate'"); + keys.put("finalParams", "Either 'generate' or 'skip'. generate means: All lombok-generated methods set all parameters to final. Default: 'generate'"); KEYS = Collections.unmodifiableMap(keys); } - public FormatPreferences(Map<String, String> preferences, String indent, boolean filledEmpties) { + public FormatPreferences(Map<String, String> preferences) { + this(preferences, null, null); + } + + public FormatPreferences(Map<String, String> preferences, String indent, Boolean filledEmpties) { if (preferences == null) preferences = Collections.emptyMap(); String indent_ = preferences.get("indent"); @@ -57,21 +65,49 @@ public final class FormatPreferences { if ("indent".equalsIgnoreCase(empties_)) filledEmpties = true; else if ("blank".equalsIgnoreCase(empties_)) filledEmpties = false; else if (empties_ != null && !"scan".equalsIgnoreCase(empties_)) { - throw new IllegalArgumentException("Legal values for 'emptyLines' is scan, indent, or blank."); + throw new IllegalArgumentException("Legal values for 'emptyLines' are 'scan', 'indent', or 'blank'."); } + this.indent = indent; this.filledEmpties = filledEmpties; + + String generateFinalParams_ = preferences.get("finalParams"); + if (generateFinalParams_ == null || "generate".equalsIgnoreCase(generateFinalParams_)) { + this.generateFinalParams = true; + } else if ("skip".equalsIgnoreCase(generateFinalParams_)) { + this.generateFinalParams = false; + } else { + throw new IllegalArgumentException("Legal values for 'finalParams' are 'generate', or 'skip'."); + } + + String generateSuppressWarnings_ = preferences.get("suppressWarnings"); + if (generateSuppressWarnings_ == null || "generate".equalsIgnoreCase(generateSuppressWarnings_)) { + this.generateSuppressWarnings = true; + } else if ("skip".equalsIgnoreCase(generateSuppressWarnings_)) { + this.generateSuppressWarnings = false; + } else { + throw new IllegalArgumentException("Legal values for 'suppressWarnings' are 'generate', or 'skip'."); + } } + public static Map<String, String> getKeysAndDescriptions() { return KEYS; } /** If true, empty lines should still be appropriately indented. If false, empty lines should be completely blank. */ public boolean fillEmpties() { - return filledEmpties; + return filledEmpties == null ? false : filledEmpties; } public String indent() { - return indent; + return indent == null ? "\t" : indent; + } + + public boolean generateSuppressWarnings() { + return generateSuppressWarnings; + } + + public boolean generateFinalParams() { + return generateFinalParams; } } |