From a195a47337f592eb117f519f7a1a42f0d8f570d1 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Tue, 17 Jul 2018 22:32:24 +0200 Subject: Attempting to fix issues with integration with mapstruct; issue #1359 --- src/launch/lombok/launch/ShadowClassLoader.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/launch/lombok/launch/ShadowClassLoader.java b/src/launch/lombok/launch/ShadowClassLoader.java index 36dd289c..32363469 100644 --- a/src/launch/lombok/launch/ShadowClassLoader.java +++ b/src/launch/lombok/launch/ShadowClassLoader.java @@ -526,9 +526,14 @@ class ShadowClassLoader extends ClassLoader { String fileNameOfClass = name.replace(".", "/") + ".class"; URL res = getResource_(fileNameOfClass, true); if (res == null) { - if (!exclusionListMatch(fileNameOfClass)) return super.loadClass(name, resolve); - throw new ClassNotFoundException(name); + if (!exclusionListMatch(fileNameOfClass)) try { + return super.loadClass(name, resolve); + } catch (ClassNotFoundException cnfe) { + res = getResource_("secondaryLoading.SCL." + sclSuffix + "/" + name.replace(".", "/") + ".SCL." + sclSuffix, true); + if (res == null) throw cnfe; + } } + if (res == null) throw new ClassNotFoundException(name); byte[] b; int p = 0; -- cgit From be1cfd2f59933725726ec5810e0c189a4aca6ad7 Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Sun, 8 Jul 2018 16:52:14 +0200 Subject: Replaced StringBuilder by simple char array in "hotspot" method --- src/core/lombok/bytecode/ClassFileMetaData.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/core/lombok/bytecode/ClassFileMetaData.java b/src/core/lombok/bytecode/ClassFileMetaData.java index 0dc6a6c8..826eed83 100644 --- a/src/core/lombok/bytecode/ClassFileMetaData.java +++ b/src/core/lombok/bytecode/ClassFileMetaData.java @@ -116,23 +116,24 @@ public class ClassFileMetaData { int end = pos + size; // the resulting string might be smaller - StringBuilder result = new StringBuilder(size); + char[] result = new char[size]; + int length = 0; while (pos < end) { int first = (byteCode[pos++] & 0xFF); if (first < 0x80) { - result.append((char)first); + result[length++] = (char)first; } else if ((first & 0xE0) == 0xC0) { int x = (first & 0x1F) << 6; int y = (byteCode[pos++] & 0x3F); - result.append((char)(x | y)); + result[length++] = (char)(x | y); } else { int x = (first & 0x0F) << 12; int y = (byteCode[pos++] & 0x3F) << 6; int z = (byteCode[pos++] & 0x3F); - result.append((char)(x | y | z)); + result[length++] = (char)(x | y | z); } } - return result.toString(); + return new String(result, 0, length); } /** -- cgit From 111d0a5f16667824d0a73b733624e6deffe19a0e Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 25 Jul 2018 21:10:20 +0200 Subject: Fixes issue #1789 - picking another workspace duplicates the ‘lombok is installed’ text in the eclipse about dialog. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/eclipseAgent/lombok/eclipse/agent/PatchFixesShadowLoaded.java | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchFixesShadowLoaded.java b/src/eclipseAgent/lombok/eclipse/agent/PatchFixesShadowLoaded.java index 52f63765..c0a2c6fe 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchFixesShadowLoaded.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchFixesShadowLoaded.java @@ -32,6 +32,7 @@ import lombok.core.Version; public class PatchFixesShadowLoaded { public static String addLombokNotesToEclipseAboutDialog(String origReturnValue, String key) { if ("aboutText".equals(key)) { + if (origReturnValue.contains(" is installed. https://projectlombok.org")) return origReturnValue; return origReturnValue + "\n\nLombok " + Version.getFullVersion() + " is installed. https://projectlombok.org/"; } return origReturnValue; -- cgit From 5ec61bb62d3dd2d9509ade090e750dd43e36c0f3 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 25 Jul 2018 21:41:17 +0200 Subject: [fixes issue #1759] We removed the ‘flag usage’ check on builder instead of replacing it with the non-experimental check about 3 years ago when builder moved out of experimental. The check has now been restored. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/lombok/javac/handlers/HandleBuilder.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index bb495fbc..f04ea8b1 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -99,6 +99,8 @@ public class HandleBuilder extends JavacAnnotationHandler { } @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { + handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder"); + Builder builderInstance = annotation.getInstance(); // These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them. -- cgit From 7c3724c9dc03684b9e4ecb9b33296c894138add6 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 25 Jul 2018 22:04:52 +0200 Subject: [Fixes issue #1783] lombok.var / lombok.experimental.var import would be removed by eclipse’s organize imports. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/changelog.markdown | 1 + .../lombok/eclipse/agent/PatchVal.java | 16 ++--- .../lombok/eclipse/agent/PatchValEclipse.java | 84 ++++++++++++++++------ 3 files changed, 70 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/doc/changelog.markdown b/doc/changelog.markdown index a77dbb3d..e6392c53 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -4,6 +4,7 @@ Lombok Changelog ### v1.18.1 "Edgy Guinea Pig" * BUGFIX: mapstruct + lombok in eclipse should hopefully work again. [Issue #1359](https://github.com/rzwitserloot/lombok/issues/1359) and [mapstruct issue #1159](https://github.com/mapstruct/mapstruct/issues/1159) * BUGFIX: Equals and hashCode again exclude transient fields by default. [Issue #1724](https://github.com/rzwitserloot/lombok/issues/1724) +* BUGFIX: Eclipse 'organize imports' feature (either explicitly, or if automatically triggered on saving via 'save actions') would remove the import for `lombok.var`. [Issue #1783](https://github.com/rzwitserloot/lombok/issues/1783) * FEATURE: You can now make builders for type hierarchies, using the new (experimental) `@SuperBuilder` annotation. Thanks for the contribution, Jan Rieke. [`@SuperBuilder` documentation](https://projectlombok.org/features/experimental/SuperBuilder) * FEATURE: `@NoArgsConstructor`, including forcing one with `lombok.config: lombok.noArgsConstructor.extraPrivate=true` now take any defaults set with `@Builder.Default` into account. [Issue #1347](https://github.com/rzwitserloot/lombok/issues/1347) diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java index c2a362bd..fee104d3 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java @@ -210,16 +210,16 @@ public class PatchVal { if (local == null || !LocalDeclaration.class.equals(local.getClass())) return false; boolean decomponent = false; - boolean val = isVal(local, scope); - boolean var = isVar(local, scope); - if (!(val || var)) return false; + boolean val = isVal(local, scope); + boolean var = isVar(local, scope); + if (!(val || var)) return false; StackTraceElement[] st = new Throwable().getStackTrace(); for (int i = 0; i < st.length - 2 && i < 10; i++) { if (st[i].getClassName().equals("lombok.launch.PatchFixesHider$Val")) { boolean valInForStatement = val && - st[i + 1].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.LocalDeclaration") && - st[i + 2].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.ForStatement"); + st[i + 1].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.LocalDeclaration") && + st[i + 2].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.ForStatement"); if (valInForStatement) return false; break; } @@ -269,7 +269,7 @@ public class PatchVal { } } - if(val) local.modifiers |= ClassFileConstants.AccFinal; + if (val) local.modifiers |= ClassFileConstants.AccFinal; local.annotations = addValAnnotation(local.annotations, local.type, scope); local.type = replacement != null ? replacement : new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, poss(local.type, 3)); @@ -298,7 +298,7 @@ public class PatchVal { if (val) forEach.elementVariable.modifiers |= ClassFileConstants.AccFinal; forEach.elementVariable.annotations = addValAnnotation(forEach.elementVariable.annotations, forEach.elementVariable.type, scope); forEach.elementVariable.type = replacement != null ? replacement : - new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, poss(forEach.elementVariable.type, 3)); + new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, poss(forEach.elementVariable.type, 3)); return false; } @@ -326,7 +326,7 @@ public class PatchVal { resolved = ((ArrayBinding) resolved).elementsType(); return resolved; } else if (resolved instanceof ReferenceBinding) { - ReferenceBinding iterableType = ((ReferenceBinding)resolved).findSuperTypeOriginatingFrom(TypeIds.T_JavaLangIterable, false); + ReferenceBinding iterableType = ((ReferenceBinding) resolved).findSuperTypeOriginatingFrom(TypeIds.T_JavaLangIterable, false); TypeBinding[] arguments = null; if (iterableType != null) switch (iterableType.kind()) { diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchValEclipse.java b/src/eclipseAgent/lombok/eclipse/agent/PatchValEclipse.java index d59b6a2e..99447bae 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchValEclipse.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchValEclipse.java @@ -47,9 +47,9 @@ import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.ForeachStatement; import org.eclipse.jdt.internal.compiler.ast.ImportReference; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; +import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.TypeReference; -import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.parser.Parser; public class PatchValEclipse { @@ -103,6 +103,10 @@ public class PatchValEclipse { } } + private static boolean couldBeVal(ImportReference[] imports, TypeReference type) { + return PatchVal.couldBe(imports, "lombok.val", type); + } + private static boolean couldBeVar(ImportReference[] imports, TypeReference type) { return PatchVal.couldBe(imports, "lombok.experimental.var", type) || PatchVal.couldBe(imports, "lombok.var", type); } @@ -118,17 +122,18 @@ public class PatchValEclipse { } public static void addFinalAndValAnnotationToModifierList(Object converter, List modifiers, AST ast, LocalDeclaration in) { - // First check that 'in' has the final flag on, and a @val / @lombok.val annotation. - if ((in.modifiers & ClassFileConstants.AccFinal) == 0) return; + // First check that 'in' has the final flag on, and a @val / @lombok.val / @var / @lombok.var annotation. if (in.annotations == null) return; boolean found = false; - Annotation valAnnotation = null; - + Annotation valAnnotation = null, varAnnotation = null; for (Annotation ann : in.annotations) { if (couldBeVal(null, ann.type)) { found = true; valAnnotation = ann; - break; + } + if (couldBeVar(null, ann.type)) { + found = true; + varAnnotation = ann; } } @@ -139,10 +144,11 @@ public class PatchValEclipse { if (modifiers == null) return; // This is null only if the project is 1.4 or less. Lombok doesn't work in that. boolean finalIsPresent = false; boolean valIsPresent = false; + boolean varIsPresent = false; for (Object present : modifiers) { if (present instanceof Modifier) { - ModifierKeyword keyword = ((Modifier)present).getKeyword(); + ModifierKeyword keyword = ((Modifier) present).getKeyword(); if (keyword == null) continue; if (keyword.toFlagValue() == Modifier.FINAL) finalIsPresent = true; } @@ -151,20 +157,18 @@ public class PatchValEclipse { Name typeName = ((org.eclipse.jdt.core.dom.Annotation) present).getTypeName(); if (typeName != null) { String fullyQualifiedName = typeName.getFullyQualifiedName(); - if ("val".equals(fullyQualifiedName) || "lombok.val".equals(fullyQualifiedName)) { - valIsPresent = true; - } + if ("val".equals(fullyQualifiedName) || "lombok.val".equals(fullyQualifiedName)) valIsPresent = true; + if ("var".equals(fullyQualifiedName) || "lombok.var".equals(fullyQualifiedName) || "lombok.experimental.var".equals(fullyQualifiedName)) varIsPresent = true; } } } - if (!finalIsPresent) { - modifiers.add( - createModifier(ast, ModifierKeyword.FINAL_KEYWORD, valAnnotation.sourceStart, valAnnotation.sourceEnd)); + if (!finalIsPresent && valAnnotation != null) { + modifiers.add(createModifier(ast, ModifierKeyword.FINAL_KEYWORD, valAnnotation.sourceStart, valAnnotation.sourceEnd)); } - if (!valIsPresent) { - MarkerAnnotation newAnnotation = createValAnnotation(ast, valAnnotation, valAnnotation.sourceStart, valAnnotation.sourceEnd); + if (!valIsPresent && valAnnotation != null) { + MarkerAnnotation newAnnotation = createValVarAnnotation(ast, valAnnotation, valAnnotation.sourceStart, valAnnotation.sourceEnd); try { Reflection.astConverterRecordNodes.invoke(converter, newAnnotation, valAnnotation); Reflection.astConverterRecordNodes.invoke(converter, newAnnotation.getTypeName(), valAnnotation.type); @@ -175,10 +179,19 @@ public class PatchValEclipse { } modifiers.add(newAnnotation); } - } - - private static boolean couldBeVal(ImportReference[] imports, TypeReference type) { - return PatchVal.couldBe(imports, "lombok.val", type); + + if (!varIsPresent && varAnnotation != null) { + MarkerAnnotation newAnnotation = createValVarAnnotation(ast, varAnnotation, varAnnotation.sourceStart, varAnnotation.sourceEnd); + try { + Reflection.astConverterRecordNodes.invoke(converter, newAnnotation, varAnnotation); + Reflection.astConverterRecordNodes.invoke(converter, newAnnotation.getTypeName(), varAnnotation.type); + } catch (IllegalAccessException e) { + throw Lombok.sneakyThrow(e); + } catch (InvocationTargetException e) { + throw Lombok.sneakyThrow(e.getCause()); + } + modifiers.add(newAnnotation); + } } public static Modifier createModifier(AST ast, ModifierKeyword keyword, int start, int end) { @@ -200,7 +213,7 @@ public class PatchValEclipse { return modifier; } - public static MarkerAnnotation createValAnnotation(AST ast, Annotation original, int start, int end) { + public static MarkerAnnotation createValVarAnnotation(AST ast, Annotation original, int start, int end) { MarkerAnnotation out = null; try { out = Reflection.markerAnnotationConstructor.newInstance(ast); @@ -212,13 +225,23 @@ public class PatchValEclipse { throw Lombok.sneakyThrow(e); } + char[][] tokens; + if (original.type instanceof SingleTypeReference) { + tokens = new char[1][]; + tokens[0] = ((SingleTypeReference) original.type).token; + } else if (original.type instanceof QualifiedTypeReference) { + tokens = ((QualifiedTypeReference) original.type).tokens; + } else { + return null; + } + if (out != null) { - SimpleName valName = ast.newSimpleName("val"); + SimpleName valName = ast.newSimpleName(new String(tokens[tokens.length - 1])); valName.setSourceRange(start, end - start + 1); - if (original.type instanceof SingleTypeReference) { + if (tokens.length == 1) { out.setTypeName(valName); setIndex(valName, 1); - } else { + } else if (tokens.length == 2) { SimpleName lombokName = ast.newSimpleName("lombok"); lombokName.setSourceRange(start, end - start + 1); setIndex(lombokName, 1); @@ -227,6 +250,21 @@ public class PatchValEclipse { setIndex(fullName, 1); fullName.setSourceRange(start, end - start + 1); out.setTypeName(fullName); + } else { + SimpleName lombokName = ast.newSimpleName("lombok"); + lombokName.setSourceRange(start, end - start + 1); + SimpleName experimentalName = ast.newSimpleName("experimental"); + lombokName.setSourceRange(start, end - start + 1); + setIndex(lombokName, 1); + setIndex(experimentalName, 2); + setIndex(valName, 3); + QualifiedName lombokExperimentalName = ast.newQualifiedName(lombokName, experimentalName); + lombokExperimentalName.setSourceRange(start, end - start + 1); + setIndex(lombokExperimentalName, 1); + QualifiedName fullName = ast.newQualifiedName(lombokExperimentalName, valName); + setIndex(fullName, 1); + fullName.setSourceRange(start, end - start + 1); + out.setTypeName(fullName); } out.setSourceRange(start, end - start + 1); } -- cgit From 7e94041dbc177476020969b00d3411020418f903 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 25 Jul 2018 23:19:00 +0200 Subject: Added key ‘dangerousconfig.lombok.disable’. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/lombok/ConfigurationKeys.java | 9 ++++++++- src/core/lombok/core/LombokConfiguration.java | 15 ++++++++++----- src/core/lombok/core/configuration/ConfigurationApp.java | 7 ++++--- src/core/lombok/core/configuration/ConfigurationKey.java | 12 +++++++++++- .../core/configuration/ConfigurationResolverFactory.java | 6 +++--- src/core/lombok/eclipse/EclipseAST.java | 12 ++++++++---- src/core/lombok/eclipse/TransformEclipseAST.java | 6 +++++- src/core/lombok/javac/JavacAST.java | 7 +++++-- src/core/lombok/javac/JavacTransformer.java | 11 +++++++++-- test/core/src/lombok/AbstractRunTests.java | 6 +++--- 10 files changed, 66 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index f5134bbd..1a28c0fa 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2017 The Project Lombok Authors. + * Copyright (C) 2013-2018 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 @@ -38,6 +38,13 @@ public class ConfigurationKeys { // ----- global ----- + /** + * lombok configuration: {@code dangerousconfig.lombok.disable} = {@code true} | {@code false}. + * + * If {@code true}, lombok is disabled entirely. + */ + public static final ConfigurationKey LOMBOK_DISABLE = new ConfigurationKey("dangerousconfig.lombok.disable", "Disables lombok transformers. It does not flag any lombok mentions (so, @Cleanup silently does nothing), and does not disable patched operations in eclipse either. Don't use this unless you know what you're doing. (default: false).", true) {}; + /** * lombok configuration: {@code lombok.addGeneratedAnnotation} = {@code true} | {@code false}. * diff --git a/src/core/lombok/core/LombokConfiguration.java b/src/core/lombok/core/LombokConfiguration.java index eb7b3d75..4a79c797 100644 --- a/src/core/lombok/core/LombokConfiguration.java +++ b/src/core/lombok/core/LombokConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 The Project Lombok Authors. + * Copyright (C) 2013-2018 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,7 @@ */ package lombok.core; +import java.net.URI; import java.util.Collections; import lombok.core.configuration.BubblingConfigurationResolver; @@ -44,7 +45,7 @@ public class LombokConfiguration { static { if (System.getProperty("lombok.disableConfig") != null) { configurationResolverFactory = new ConfigurationResolverFactory() { - @Override public ConfigurationResolver createResolver(AST ast) { + @Override public ConfigurationResolver createResolver(URI sourceLocation) { return NULL_RESOLVER; } }; @@ -63,13 +64,17 @@ public class LombokConfiguration { } static T read(ConfigurationKey key, AST ast) { - return configurationResolverFactory.createResolver(ast).resolve(key); + return configurationResolverFactory.createResolver(ast.getAbsoluteFileLocation()).resolve(key); + } + + public static T read(ConfigurationKey key, URI sourceLocation) { + return configurationResolverFactory.createResolver(sourceLocation).resolve(key); } private static ConfigurationResolverFactory createFileSystemBubblingResolverFactory() { return new ConfigurationResolverFactory() { - @Override public ConfigurationResolver createResolver(AST ast) { - return new BubblingConfigurationResolver(cache.sourcesForJavaFile(ast.getAbsoluteFileLocation(), ConfigurationProblemReporter.CONSOLE)); + @Override public ConfigurationResolver createResolver(URI sourceLocation) { + return new BubblingConfigurationResolver(cache.sourcesForJavaFile(sourceLocation, ConfigurationProblemReporter.CONSOLE)); } }; } diff --git a/src/core/lombok/core/configuration/ConfigurationApp.java b/src/core/lombok/core/configuration/ConfigurationApp.java index efe57e38..9cfec2e7 100644 --- a/src/core/lombok/core/configuration/ConfigurationApp.java +++ b/src/core/lombok/core/configuration/ConfigurationApp.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Project Lombok Authors. + * Copyright (C) 2014-2018 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 ConfigurationApp extends LombokApp { boolean verbose = args.verbose; if (args.generate) { - return generate(keys, verbose); + return generate(keys, verbose, !args.key.isEmpty()); } return display(keys, verbose, args.paths, !args.key.isEmpty()); @@ -130,8 +130,9 @@ public class ConfigurationApp extends LombokApp { return this; } - public int generate(Collection> keys, boolean verbose) { + public int generate(Collection> keys, boolean verbose, boolean explicit) { for (ConfigurationKey key : keys) { + if (!explicit && key.isHidden()) continue; String keyName = key.getKeyName(); ConfigurationDataType type = key.getType(); String description = key.getDescription(); diff --git a/src/core/lombok/core/configuration/ConfigurationKey.java b/src/core/lombok/core/configuration/ConfigurationKey.java index d46a70b0..18075190 100644 --- a/src/core/lombok/core/configuration/ConfigurationKey.java +++ b/src/core/lombok/core/configuration/ConfigurationKey.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 The Project Lombok Authors. + * Copyright (C) 2013-2018 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,13 +43,19 @@ public abstract class ConfigurationKey { private final String keyName; private final String description; private final ConfigurationDataType type; + private final boolean hidden; public ConfigurationKey(String keyName, String description) { + this(keyName, description, false); + } + + public ConfigurationKey(String keyName, String description, boolean hidden) { this.keyName = checkName(keyName); @SuppressWarnings("unchecked") ConfigurationDataType type = ConfigurationDataType.toDataType((Class>)getClass()); this.type = type; this.description = description; + this.hidden = hidden; registerKey(keyName, this); } @@ -65,6 +71,10 @@ public abstract class ConfigurationKey { return type; } + public final boolean isHidden() { + return hidden; + } + @Override public String toString() { return keyName + " (" + type + "): " + description; } diff --git a/src/core/lombok/core/configuration/ConfigurationResolverFactory.java b/src/core/lombok/core/configuration/ConfigurationResolverFactory.java index 83b58c2f..b640b271 100644 --- a/src/core/lombok/core/configuration/ConfigurationResolverFactory.java +++ b/src/core/lombok/core/configuration/ConfigurationResolverFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Project Lombok Authors. + * Copyright (C) 2014-2018 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.core.configuration; -import lombok.core.AST; +import java.net.URI; public interface ConfigurationResolverFactory { - ConfigurationResolver createResolver(AST ast); + ConfigurationResolver createResolver(URI sourceLocation); } diff --git a/src/core/lombok/eclipse/EclipseAST.java b/src/core/lombok/eclipse/EclipseAST.java index dc2c9843..7cd2e400 100644 --- a/src/core/lombok/eclipse/EclipseAST.java +++ b/src/core/lombok/eclipse/EclipseAST.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2013 The Project Lombok Authors. + * Copyright (C) 2009-2018 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 @@ -73,16 +73,20 @@ public class EclipseAST extends AST { private static final URI NOT_CALCULATED_MARKER = URI.create("https://projectlombok.org/not/calculated"); private URI memoizedAbsoluteFileLocation = NOT_CALCULATED_MARKER; + public static URI getAbsoluteFileLocation(CompilationUnitDeclaration ast) { + return getAbsoluteFileLocation0(ast); + } + public URI getAbsoluteFileLocation() { if (memoizedAbsoluteFileLocation != NOT_CALCULATED_MARKER) return memoizedAbsoluteFileLocation; - memoizedAbsoluteFileLocation = getAbsoluteFileLocation0(); + memoizedAbsoluteFileLocation = getAbsoluteFileLocation0(this.compilationUnitDeclaration); return memoizedAbsoluteFileLocation; } /** This is the call, but we wrapped it to memoize this. */ - private URI getAbsoluteFileLocation0() { - String fileName = getFileName(); + private static URI getAbsoluteFileLocation0(CompilationUnitDeclaration ast) { + String fileName = toFileName(ast); if (fileName != null && (fileName.startsWith("file:") || fileName.startsWith("sourcecontrol:"))) { // Some exotic build systems get real fancy with filenames. Known culprits: // The 'jazz' source control system _probably_ (not confirmed yet) uses sourcecontrol://jazz: urls. diff --git a/src/core/lombok/eclipse/TransformEclipseAST.java b/src/core/lombok/eclipse/TransformEclipseAST.java index 683465c9..541924ad 100644 --- a/src/core/lombok/eclipse/TransformEclipseAST.java +++ b/src/core/lombok/eclipse/TransformEclipseAST.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2012 The Project Lombok Authors. + * Copyright (C) 2009-2018 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,6 +25,8 @@ import static lombok.eclipse.handlers.EclipseHandlerUtil.*; import java.lang.reflect.Field; +import lombok.ConfigurationKeys; +import lombok.core.LombokConfiguration; import lombok.core.debug.DebugSnapshotStore; import lombok.core.debug.HistogramTracker; import lombok.patcher.Symbols; @@ -143,6 +145,8 @@ public class TransformEclipseAST { // Do NOT abort if (ast.bits & ASTNode.HasAllMethodBodies) != 0 - that doesn't work. + if (Boolean.TRUE.equals(LombokConfiguration.read(ConfigurationKeys.LOMBOK_DISABLE, EclipseAST.getAbsoluteFileLocation(ast)))) return; + try { DebugSnapshotStore.INSTANCE.snapshot(ast, "transform entry"); long histoToken = lombokTracker == null ? 0L : lombokTracker.start(); diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java index 4ca2c050..091612cc 100644 --- a/src/core/lombok/javac/JavacAST.java +++ b/src/core/lombok/javac/JavacAST.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2017 The Project Lombok Authors. + * Copyright (C) 2009-2018 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 @@ -93,8 +93,11 @@ public class JavacAST extends AST { } @Override public URI getAbsoluteFileLocation() { + return getAbsoluteFileLocation((JCCompilationUnit) top().get()); + } + + public static URI getAbsoluteFileLocation(JCCompilationUnit cu) { try { - JCCompilationUnit cu = (JCCompilationUnit) top().get(); return cu.sourcefile.toUri(); } catch (Exception e) { return null; diff --git a/src/core/lombok/javac/JavacTransformer.java b/src/core/lombok/javac/JavacTransformer.java index 54977a59..2e37b32b 100644 --- a/src/core/lombok/javac/JavacTransformer.java +++ b/src/core/lombok/javac/JavacTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2017 The Project Lombok Authors. + * Copyright (C) 2009-2018 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 @@ -35,6 +35,9 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.List; +import lombok.ConfigurationKeys; +import lombok.core.LombokConfiguration; + public class JavacTransformer { private final HandlerLibrary handlers; private final Messager messager; @@ -65,7 +68,11 @@ public class JavacTransformer { java.util.List asts = new ArrayList(); - for (JCCompilationUnit unit : compilationUnits) asts.add(new JavacAST(messager, context, unit)); + for (JCCompilationUnit unit : compilationUnits) { + if (!Boolean.TRUE.equals(LombokConfiguration.read(ConfigurationKeys.LOMBOK_DISABLE, JavacAST.getAbsoluteFileLocation(unit)))) { + asts.add(new JavacAST(messager, context, unit)); + } + } for (JavacAST ast : asts) { ast.traverse(new AnnotationVisitor(priority)); diff --git a/test/core/src/lombok/AbstractRunTests.java b/test/core/src/lombok/AbstractRunTests.java index 3d672bc4..f93fbe27 100644 --- a/test/core/src/lombok/AbstractRunTests.java +++ b/test/core/src/lombok/AbstractRunTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2014 The Project Lombok Authors. + * Copyright (C) 2009-2018 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 @@ -30,6 +30,7 @@ import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.StringWriter; +import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; @@ -40,7 +41,6 @@ import java.util.Map; import org.junit.Assert; import lombok.DirectoryRunner.FileTester; -import lombok.core.AST; import lombok.core.LombokConfiguration; import lombok.core.LombokImmutableList; import lombok.core.configuration.ConfigurationKeysLoader; @@ -84,7 +84,7 @@ public abstract class AbstractRunTests { StringWriter writer = new StringWriter(); LombokConfiguration.overrideConfigurationResolverFactory(new ConfigurationResolverFactory() { - @Override public ConfigurationResolver createResolver(AST ast) { + @Override public ConfigurationResolver createResolver(URI sourceLocation) { return sourceDirectives_.getConfiguration(); } }); -- cgit From dc715da8b79bff32116ac477d0ac04875bd21167 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Thu, 26 Jul 2018 00:00:24 +0200 Subject: pre-release version bump --- doc/changelog.markdown | 3 ++- src/core/lombok/core/Version.java | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/doc/changelog.markdown b/doc/changelog.markdown index e6392c53..29bd1cce 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -1,10 +1,11 @@ Lombok Changelog ---------------- -### v1.18.1 "Edgy Guinea Pig" +### v1.18.2 (July 26th, 2018) * BUGFIX: mapstruct + lombok in eclipse should hopefully work again. [Issue #1359](https://github.com/rzwitserloot/lombok/issues/1359) and [mapstruct issue #1159](https://github.com/mapstruct/mapstruct/issues/1159) * BUGFIX: Equals and hashCode again exclude transient fields by default. [Issue #1724](https://github.com/rzwitserloot/lombok/issues/1724) * BUGFIX: Eclipse 'organize imports' feature (either explicitly, or if automatically triggered on saving via 'save actions') would remove the import for `lombok.var`. [Issue #1783](https://github.com/rzwitserloot/lombok/issues/1783) +* BUGFIX: Lombok and gradle v4.9 didn't work together; that's been fixed. [Issue #1716](https://github.com/rzwitserloot/lombok/issues/1716) and [gradle-apt-plugin issue #87](https://github.com/tbroyer/gradle-apt-plugin/issues/87) * FEATURE: You can now make builders for type hierarchies, using the new (experimental) `@SuperBuilder` annotation. Thanks for the contribution, Jan Rieke. [`@SuperBuilder` documentation](https://projectlombok.org/features/experimental/SuperBuilder) * FEATURE: `@NoArgsConstructor`, including forcing one with `lombok.config: lombok.noArgsConstructor.extraPrivate=true` now take any defaults set with `@Builder.Default` into account. [Issue #1347](https://github.com/rzwitserloot/lombok/issues/1347) diff --git a/src/core/lombok/core/Version.java b/src/core/lombok/core/Version.java index 70af48e0..7b19d00e 100644 --- a/src/core/lombok/core/Version.java +++ b/src/core/lombok/core/Version.java @@ -30,9 +30,9 @@ public class Version { // ** CAREFUL ** - this class must always compile with 0 dependencies (it must not refer to any other sources or libraries). // Note: In 'X.Y.Z', if Z is odd, its a snapshot build built from the repository, so many different 0.10.3 versions can exist, for example. // Official builds always end in an even number. (Since 0.10.2). - private static final String VERSION = "1.18.1"; - private static final String RELEASE_NAME = "Edgy Guinea Pig"; -// private static final String RELEASE_NAME = "Envious Ferret"; + private static final String VERSION = "1.18.2"; +// private static final String RELEASE_NAME = "Edgy Guinea Pig"; + private static final String RELEASE_NAME = "Envious Ferret"; // Named version history: // Angry Butterfly -- cgit From 61fbd4a7f82180871e635a0ca80248e0cec02cf3 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Thu, 26 Jul 2018 00:17:09 +0200 Subject: post-release version bump --- doc/changelog.markdown | 3 +++ src/core/lombok/core/Version.java | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 29bd1cce..0a12cb2d 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -1,6 +1,9 @@ Lombok Changelog ---------------- +### v1.18.3 "Edgy Guinea Pig" +* No changes yet. + ### v1.18.2 (July 26th, 2018) * BUGFIX: mapstruct + lombok in eclipse should hopefully work again. [Issue #1359](https://github.com/rzwitserloot/lombok/issues/1359) and [mapstruct issue #1159](https://github.com/mapstruct/mapstruct/issues/1159) * BUGFIX: Equals and hashCode again exclude transient fields by default. [Issue #1724](https://github.com/rzwitserloot/lombok/issues/1724) diff --git a/src/core/lombok/core/Version.java b/src/core/lombok/core/Version.java index 7b19d00e..4b119873 100644 --- a/src/core/lombok/core/Version.java +++ b/src/core/lombok/core/Version.java @@ -30,9 +30,9 @@ public class Version { // ** CAREFUL ** - this class must always compile with 0 dependencies (it must not refer to any other sources or libraries). // Note: In 'X.Y.Z', if Z is odd, its a snapshot build built from the repository, so many different 0.10.3 versions can exist, for example. // Official builds always end in an even number. (Since 0.10.2). - private static final String VERSION = "1.18.2"; -// private static final String RELEASE_NAME = "Edgy Guinea Pig"; - private static final String RELEASE_NAME = "Envious Ferret"; + private static final String VERSION = "1.18.3"; + private static final String RELEASE_NAME = "Edgy Guinea Pig"; +// private static final String RELEASE_NAME = "Envious Ferret"; // Named version history: // Angry Butterfly -- cgit From 3d432c38d0cfeb36b8e7402eca56faaafcf7bac7 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Sun, 29 Jul 2018 16:37:21 +0200 Subject: code impl of FieldNameConstants rewrite + test updates for it --- src/core/lombok/ConfigurationKeys.java | 11 +- .../eclipse/handlers/HandleFieldNameConstants.java | 144 +++++++++++++-------- .../lombok/experimental/FieldNameConstants.java | 28 +++- .../javac/handlers/HandleFieldNameConstants.java | 129 ++++++++++-------- .../after-delombok/FieldNameConstantsBasic.java | 8 +- .../FieldNameConstantsConfigKeys.java | 7 +- .../after-delombok/FieldNameConstantsEnum.java | 10 ++ .../after-delombok/FieldNameConstantsWeird.java | 6 - .../after-ecj/FieldNameConstantsBasic.java | 18 ++- .../after-ecj/FieldNameConstantsConfigKeys.java | 13 +- .../resource/after-ecj/FieldNameConstantsEnum.java | 23 ++++ .../after-ecj/FieldNameConstantsWeird.java | 13 -- .../resource/before/FieldNameConstantsBasic.java | 4 +- .../before/FieldNameConstantsConfigKeys.java | 3 +- .../resource/before/FieldNameConstantsEnum.java | 13 ++ .../resource/before/FieldNameConstantsWeird.java | 12 -- .../FieldNameConstantsWeird.java.messages | 1 - .../FieldNameConstantsWeird.java.messages | 1 - 18 files changed, 270 insertions(+), 174 deletions(-) create mode 100644 test/transform/resource/after-delombok/FieldNameConstantsEnum.java delete mode 100644 test/transform/resource/after-delombok/FieldNameConstantsWeird.java create mode 100644 test/transform/resource/after-ecj/FieldNameConstantsEnum.java delete mode 100644 test/transform/resource/after-ecj/FieldNameConstantsWeird.java create mode 100644 test/transform/resource/before/FieldNameConstantsEnum.java delete mode 100644 test/transform/resource/before/FieldNameConstantsWeird.java delete mode 100644 test/transform/resource/messages-delombok/FieldNameConstantsWeird.java.messages delete mode 100644 test/transform/resource/messages-ecj/FieldNameConstantsWeird.java.messages (limited to 'src') diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index 1a28c0fa..184ded27 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -529,18 +529,11 @@ public class ConfigurationKeys { public static final ConfigurationKey FIELD_NAME_CONSTANTS_FLAG_USAGE = new ConfigurationKey("lombok.fieldNameConstants.flagUsage", "Emit a warning or error if @FieldNameConstants is used.") {}; /** - * lombok configuration: {@code lombok.fieldNameConstants.prefix} = <String: aJavaIdentifierPrefix> (Default: {@code PREFIX_}). + * lombok configuration: {@code lombok.fieldNameConstants.innerTypeName} = <String: AValidJavaTypeName> (Default: {@code Fields}). * * The names of the constants generated by {@code @FieldNameConstants} will be prefixed with this value. */ - public static final ConfigurationKey FIELD_NAME_CONSTANTS_PREFIX = new ConfigurationKey("lombok.fieldNameConstants.prefix", "names of constants generated by @FieldNameConstants will be prefixed with this value. (default: 'PREFIX_').") {}; - - /** - * lombok configuration: {@code lombok.fieldNameConstants.suffix} = <String: aJavaIdentifierPrefix> (Default: nothing). - * - * The names of the constants generated by {@code @FieldNameConstants} will be suffixed with this value. - */ - public static final ConfigurationKey FIELD_NAME_CONSTANTS_SUFFIX = new ConfigurationKey("lombok.fieldNameConstants.suffix", "names of constants generated by @FieldNameConstants will be suffixed with this value. (default: nothing).") {}; + public static final ConfigurationKey FIELD_NAME_CONSTANTS_INNER_TYPE_NAME = new ConfigurationKey("lombok.fieldNameConstants.innerTypeName", "The default name of the inner type generated by @FieldNameConstants. (default: 'Fields').") {}; // ----- Wither ----- diff --git a/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java b/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java index c3a28f7f..15650490 100644 --- a/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java +++ b/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java @@ -24,32 +24,37 @@ package lombok.eclipse.handlers; import static lombok.core.handlers.HandlerUtil.handleExperimentalFlagUsage; import static lombok.eclipse.handlers.EclipseHandlerUtil.*; -import java.lang.reflect.Modifier; -import java.util.Collection; +import java.util.ArrayList; +import java.util.List; import lombok.AccessLevel; import lombok.ConfigurationKeys; import lombok.core.AST.Kind; import lombok.core.AnnotationValues; -import lombok.core.handlers.HandlerUtil; import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; import lombok.experimental.FieldNameConstants; import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.Annotation; +import org.eclipse.jdt.internal.compiler.ast.Clinit; +import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; +import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.StringLiteral; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.mangosdk.spi.ProviderFor; @ProviderFor(EclipseAnnotationHandler.class) public class HandleFieldNameConstants extends EclipseAnnotationHandler { - public void generateFieldNameConstantsForType(EclipseNode typeNode, EclipseNode errorNode, AccessLevel level, String prefix, String suffix) { + public void generateFieldNameConstantsForType(EclipseNode typeNode, EclipseNode errorNode, AccessLevel level, boolean asEnum, String innerTypeName, boolean onlyExplicit) { TypeDeclaration typeDecl = null; if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); @@ -57,22 +62,29 @@ public class HandleFieldNameConstants extends EclipseAnnotationHandler qualified = new ArrayList(); + for (EclipseNode field : typeNode.down()) { - if (fieldQualifiesForFieldNameConstantsGeneration(field)) generateFieldNameConstantsForField(field, errorNode.get(), level, prefix, suffix); + if (fieldQualifiesForFieldNameConstantsGeneration(field, onlyExplicit)) qualified.add(field); + } + + if (qualified.isEmpty()) { + errorNode.addWarning("No fields qualify for @FieldNameConstants, therefore this annotation does nothing"); + } else { + createInnerTypeFieldNameConstants(typeNode, errorNode.get(), level, qualified, asEnum, innerTypeName); } } - private void generateFieldNameConstantsForField(EclipseNode fieldNode, ASTNode pos, AccessLevel level, String prefix, String suffix) { - if (hasAnnotation(FieldNameConstants.class, fieldNode)) return; - createFieldNameConstantsForField(level, prefix, suffix, fieldNode, fieldNode, pos, false); - } - - private boolean fieldQualifiesForFieldNameConstantsGeneration(EclipseNode field) { + private boolean fieldQualifiesForFieldNameConstantsGeneration(EclipseNode field, boolean onlyExplicit) { if (field.getKind() != Kind.FIELD) return false; + if (hasAnnotation(FieldNameConstants.Exclude.class, field)) return false; + if (hasAnnotation(FieldNameConstants.Include.class, field)) return true; + if (onlyExplicit) return false; + FieldDeclaration fieldDecl = (FieldDeclaration) field.get(); return filterField(fieldDecl); } @@ -81,55 +93,75 @@ public class HandleFieldNameConstants extends EclipseAnnotationHandler fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists) { - for (EclipseNode fieldNode : fieldNodes) createFieldNameConstantsForField(level, prefix, suffix, fieldNode, errorNode, source, whineIfExists); - } - - private void createFieldNameConstantsForField(AccessLevel level, String prefix, String suffix, EclipseNode fieldNode, EclipseNode errorNode, ASTNode source, boolean whineIfExists) { - if (fieldNode.getKind() != Kind.FIELD) { - errorNode.addError("@FieldNameConstants is only supported on a class, an enum, or a field"); + FieldNameConstants annotationInstance = annotation.getInstance(); + AccessLevel level = annotationInstance.level(); + boolean asEnum = annotationInstance.asEnum(); + boolean usingLombokv1_18_2 = annotation.isExplicit("prefix") || annotation.isExplicit("suffix") || node.getKind() == Kind.FIELD; + + if (usingLombokv1_18_2) { + annotationNode.addError("@FieldNameConstants has been redesigned in lombok v1.18.4; please upgrade your project dependency on lombok. See https://projectlombok.org/features/experimental/FieldNameConstants for more information."); return; } - FieldDeclaration field = (FieldDeclaration) fieldNode.get(); - String fieldName = new String(field.name); - String constantName = prefix + HandlerUtil.camelCaseToConstant(fieldName) + suffix; - if (constantName.equals(fieldName)) { - fieldNode.addWarning("Not generating constant for this field: The name of the constant would be equal to the name of this field."); + if (level == AccessLevel.NONE) { + annotationNode.addWarning("AccessLevel.NONE is not compatible with @FieldNameConstants. If you don't want the inner type, simply remove FieldNameConstants."); return; } - int pS = source.sourceStart, pE = source.sourceEnd; - long p = (long) pS << 32 | pE; - FieldDeclaration fieldConstant = new FieldDeclaration(constantName.toCharArray(), pS,pE); - fieldConstant.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; - fieldConstant.modifiers = toEclipseModifier(level) | Modifier.STATIC | Modifier.FINAL; - fieldConstant.type = new QualifiedTypeReference(TypeConstants.JAVA_LANG_STRING, new long[] {p,p,p}); - fieldConstant.initialization = new StringLiteral(field.name, pS, pE, 0); - injectField(fieldNode.up(), fieldConstant); + String innerTypeName = annotationInstance.innerTypeName(); + if (innerTypeName.isEmpty()) innerTypeName = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_INNER_TYPE_NAME); + if (innerTypeName == null || innerTypeName.isEmpty()) innerTypeName = "Fields"; + + generateFieldNameConstantsForType(node, annotationNode, level, asEnum, innerTypeName, annotationInstance.onlyExplicitlyIncluded()); + } + + private void createInnerTypeFieldNameConstants(EclipseNode typeNode, ASTNode source, AccessLevel level, List fields, boolean asEnum, String innerTypeName) { + if (fields.isEmpty()) return; + + TypeDeclaration parent = (TypeDeclaration) typeNode.get(); + TypeDeclaration innerType = new TypeDeclaration(parent.compilationResult); + innerType.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; + innerType.modifiers = toEclipseModifier(level) | (asEnum ? ClassFileConstants.AccEnum : ClassFileConstants.AccStatic | ClassFileConstants.AccFinal); + char[] name = innerTypeName.toCharArray(); + innerType.name = name; + innerType.traverse(new SetGeneratedByVisitor(source), (ClassScope) null); + EclipseNode innerNode = injectType(typeNode, innerType); + + ConstructorDeclaration constructor = new ConstructorDeclaration(parent.compilationResult); + constructor.selector = name; + constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart; + constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd; + constructor.modifiers = ClassFileConstants.AccPrivate; + ExplicitConstructorCall superCall = new ExplicitConstructorCall(0); + superCall.sourceStart = source.sourceStart; + superCall.sourceEnd = source.sourceEnd; + superCall.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; + constructor.constructorCall = superCall; + if (!asEnum) constructor.statements = new Statement[0]; + + injectMethod(innerNode, constructor); + + if (asEnum) injectMethod(innerNode, new Clinit(parent.compilationResult)); + + for (EclipseNode fieldNode : fields) { + FieldDeclaration field = (FieldDeclaration) fieldNode.get(); + char[] fName = field.name; + int pS = source.sourceStart, pE = source.sourceEnd; + long p = (long) pS << 32 | pE; + FieldDeclaration fieldConstant = new FieldDeclaration(fName, pS, pE); + fieldConstant.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; + fieldConstant.modifiers = asEnum ? 0 : ClassFileConstants.AccPublic | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal; + fieldConstant.type = asEnum ? null : new QualifiedTypeReference(TypeConstants.JAVA_LANG_STRING, new long[] {p, p, p}); + if (asEnum) { + AllocationExpression ac = new AllocationExpression(); + ac.enumConstant = fieldConstant; + ac.sourceStart = source.sourceStart; + ac.sourceEnd = source.sourceEnd; + fieldConstant.initialization = ac; + } else { + fieldConstant.initialization = new StringLiteral(field.name, pS, pE, 0); + } + injectField(innerNode, fieldConstant); + } } } diff --git a/src/core/lombok/experimental/FieldNameConstants.java b/src/core/lombok/experimental/FieldNameConstants.java index 31c2970c..d6886890 100644 --- a/src/core/lombok/experimental/FieldNameConstants.java +++ b/src/core/lombok/experimental/FieldNameConstants.java @@ -29,12 +29,32 @@ import java.lang.annotation.Target; import lombok.AccessLevel; /** - * Generates String constants containing the field name for each field. + * Generates an inner type, containing String constants containing the field name for each field. Alternatively, generates an inner enum with enum values matching each field name. */ -@Target({ElementType.TYPE, ElementType.FIELD}) +@Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) public @interface FieldNameConstants { lombok.AccessLevel level() default AccessLevel.PUBLIC; - String prefix() default " CONFIG DEFAULT "; - String suffix() default " CONFIG DEFAULT "; + boolean asEnum() default false; + String innerTypeName() default ""; + + /** + * Only include fields and methods explicitly marked with {@code @FieldNameConstants.Include}. + * Normally, all (non-static) fields are included by default. + */ + boolean onlyExplicitlyIncluded() default false; + + /** + * If present, do not include this field in the generated fieldnames inner type. + */ + @Target(ElementType.FIELD) + @Retention(RetentionPolicy.SOURCE) + public @interface Exclude {} + + /** + * If present, include this field in the generated fieldnames inner type (default). + */ + @Target(ElementType.FIELD) + @Retention(RetentionPolicy.SOURCE) + public @interface Include {} } diff --git a/src/core/lombok/javac/handlers/HandleFieldNameConstants.java b/src/core/lombok/javac/handlers/HandleFieldNameConstants.java index 8ff136fc..5b120948 100644 --- a/src/core/lombok/javac/handlers/HandleFieldNameConstants.java +++ b/src/core/lombok/javac/handlers/HandleFieldNameConstants.java @@ -24,13 +24,11 @@ package lombok.javac.handlers; import static lombok.core.handlers.HandlerUtil.handleExperimentalFlagUsage; import static lombok.javac.handlers.JavacHandlerUtil.*; -import java.lang.reflect.Modifier; -import java.util.Collection; +import java.util.ArrayList; import lombok.AccessLevel; import lombok.ConfigurationKeys; import lombok.core.AST.Kind; -import lombok.core.handlers.HandlerUtil; import lombok.core.AnnotationValues; import lombok.experimental.FieldNameConstants; import lombok.javac.JavacAnnotationHandler; @@ -40,16 +38,23 @@ import lombok.javac.JavacTreeMaker; 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.JCTree.JCAnnotation; +import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCExpression; +import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCModifiers; +import com.sun.tools.javac.tree.JCTree.JCStatement; +import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; +import com.sun.tools.javac.util.List; +import com.sun.tools.javac.util.Name; @ProviderFor(JavacAnnotationHandler.class) public class HandleFieldNameConstants extends JavacAnnotationHandler { - public void generateFieldNameConstantsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, String prefix, String suffix) { + public void generateFieldNameConstantsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean asEnum, String innerTypeName, boolean onlyExplicit) { JCClassDecl typeDecl = null; if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get(); @@ -57,22 +62,31 @@ public class HandleFieldNameConstants extends JavacAnnotationHandler qualified = new ArrayList(); + for (JavacNode field : typeNode.down()) { - if (fieldQualifiesForFieldNameConstantsGeneration(field)) generateFieldNameConstantsForField(field, errorNode.get(), level, prefix, suffix); + if (fieldQualifiesForFieldNameConstantsGeneration(field, onlyExplicit)) qualified.add(field); + } + + if (qualified.isEmpty()) { + errorNode.addWarning("No fields qualify for @FieldNameConstants, therefore this annotation does nothing"); + } else { + createInnerTypeFieldNameConstants(typeNode, errorNode.get(), level, qualified, asEnum, innerTypeName); } } - private void generateFieldNameConstantsForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level, String prefix, String suffix) { - if (hasAnnotation(FieldNameConstants.class, fieldNode)) return; - createFieldNameConstantsForField(level, prefix, suffix, fieldNode, fieldNode, false); - } - - private boolean fieldQualifiesForFieldNameConstantsGeneration(JavacNode field) { + private boolean fieldQualifiesForFieldNameConstantsGeneration(JavacNode field, boolean onlyExplicit) { if (field.getKind() != Kind.FIELD) return false; + boolean exclAnn = JavacHandlerUtil.hasAnnotationAndDeleteIfNeccessary(FieldNameConstants.Exclude.class, field); + boolean inclAnn = JavacHandlerUtil.hasAnnotationAndDeleteIfNeccessary(FieldNameConstants.Include.class, field); + if (exclAnn) return false; + if (inclAnn) return true; + if (onlyExplicit) return false; + JCVariableDecl fieldDecl = (JCVariableDecl) field.get(); if (fieldDecl.name.toString().startsWith("$")) return false; if ((fieldDecl.mods.flags & Flags.STATIC) != 0) return false; @@ -82,56 +96,61 @@ public class HandleFieldNameConstants extends JavacAnnotationHandler annotation, JCAnnotation ast, JavacNode annotationNode) { handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.FIELD_NAME_CONSTANTS_FLAG_USAGE, "@FieldNameConstants"); - Collection fields = annotationNode.upFromAnnotationToFields(); deleteAnnotationIfNeccessary(annotationNode, FieldNameConstants.class); deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); JavacNode node = annotationNode.up(); - FieldNameConstants annotatationInstance = annotation.getInstance(); - AccessLevel level = annotatationInstance.level(); - String prefix = annotatationInstance.prefix(); - String suffix = annotatationInstance.suffix(); - if (prefix.equals(" CONFIG DEFAULT ")) prefix = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_PREFIX); - if (suffix.equals(" CONFIG DEFAULT ")) suffix = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_SUFFIX); - if (prefix == null) prefix = "FIELD_"; - if (suffix == null) suffix = ""; - if (node == null) return; - switch (node.getKind()) { - case FIELD: - if (level != AccessLevel.NONE) createFieldNameConstantsForFields(level, prefix, suffix, fields, annotationNode, annotationNode, true); - break; - case TYPE: - if (level == AccessLevel.NONE) { - annotationNode.addWarning("type-level '@FieldNameConstants' does not work with AccessLevel.NONE."); - return; - } - generateFieldNameConstantsForType(node, annotationNode, level, prefix, suffix); - break; - } - } - - private void createFieldNameConstantsForFields(AccessLevel level, String prefix, String suffix, Collection fieldNodes, JavacNode annotationNode, JavacNode errorNode, boolean whineIfExists) { - for (JavacNode fieldNode : fieldNodes) createFieldNameConstantsForField(level, prefix, suffix, fieldNode, errorNode, whineIfExists); - } - - private void createFieldNameConstantsForField(AccessLevel level, String prefix, String suffix, JavacNode fieldNode, JavacNode source, boolean whineIfExists) { - if (fieldNode.getKind() != Kind.FIELD) { - source.addError("@FieldNameConstants is only supported on a class, an enum, or a field"); + FieldNameConstants annotationInstance = annotation.getInstance(); + AccessLevel level = annotationInstance.level(); + boolean asEnum = annotationInstance.asEnum(); + boolean usingLombokv1_18_2 = annotation.isExplicit("prefix") || annotation.isExplicit("suffix") || node.getKind() == Kind.FIELD; + + if (usingLombokv1_18_2) { + annotationNode.addError("@FieldNameConstants has been redesigned in lombok v1.18.4; please upgrade your project dependency on lombok. See https://projectlombok.org/features/experimental/FieldNameConstants for more information."); return; } - JCVariableDecl field = (JCVariableDecl) fieldNode.get(); - String fieldName = field.name.toString(); - String constantName = prefix + HandlerUtil.camelCaseToConstant(fieldName) + suffix; - if (constantName.equals(fieldName)) { - fieldNode.addWarning("Not generating constant for this field: The name of the constant would be equal to the name of this field."); + + if (level == AccessLevel.NONE) { + annotationNode.addWarning("AccessLevel.NONE is not compatible with @FieldNameConstants. If you don't want the inner type, simply remove @FieldNameConstants."); return; } - JavacTreeMaker treeMaker = fieldNode.getTreeMaker(); - JCModifiers modifiers = treeMaker.Modifiers(toJavacModifier(level) | Modifier.STATIC | Modifier.FINAL); - JCExpression returnType = chainDots(fieldNode, "java", "lang", "String"); - JCExpression init = treeMaker.Literal(fieldNode.getName()); - JCVariableDecl fieldConstant = treeMaker.VarDef(modifiers, fieldNode.toName(constantName), returnType, init); - injectField(fieldNode.up(), fieldConstant); + String innerTypeName = annotationInstance.innerTypeName(); + if (innerTypeName.isEmpty()) innerTypeName = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_INNER_TYPE_NAME); + if (innerTypeName == null || innerTypeName.isEmpty()) innerTypeName = "Fields"; + + generateFieldNameConstantsForType(node, annotationNode, level, asEnum, innerTypeName, annotationInstance.onlyExplicitlyIncluded()); + } + + private void createInnerTypeFieldNameConstants(JavacNode typeNode, DiagnosticPosition pos, AccessLevel level, java.util.List fields, boolean asEnum, String innerTypeName) { + if (fields.isEmpty()) return; + + JavacTreeMaker maker = typeNode.getTreeMaker(); + JCModifiers mods = maker.Modifiers(toJavacModifier(level) | (asEnum ? Flags.ENUM : Flags.STATIC | Flags.FINAL)); + + Name fieldsName = typeNode.toName(innerTypeName); + JCClassDecl innerType = maker.ClassDef(mods, fieldsName, List.nil(), null, List.nil(), List.nil()); + JavacNode innerNode = injectType(typeNode, innerType); + + JCModifiers genConstrMods = maker.Modifiers(Flags.GENERATEDCONSTR | (asEnum ? 0L : Flags.PRIVATE)); + JCBlock genConstrBody = maker.Block(0L, List.of(maker.Exec(maker.Apply(List.nil(), maker.Ident(typeNode.toName("super")), List.nil())))); + JCMethodDecl genConstr = maker.MethodDef(genConstrMods, typeNode.toName(""), null, List.nil(), List.nil(), List.nil(), genConstrBody, null); + + injectMethod(innerNode, genConstr); + + for (JavacNode field : fields) { + JCModifiers enumValueMods = maker.Modifiers(Flags.PUBLIC | Flags.STATIC | Flags.FINAL | (asEnum ? Flags.ENUM : 0L)); + JCExpression returnType; + JCExpression init; + if (asEnum) { + returnType = maker.Ident(fieldsName); + init = maker.NewClass(null, List.nil(), maker.Ident(fieldsName), List.nil(), null); + } else { + returnType = chainDots(field, "java", "lang", "String"); + init = maker.Literal(field.getName()); + } + JCVariableDecl enumField = maker.VarDef(enumValueMods, ((JCVariableDecl) field.get()).name, returnType, init); + injectField(innerNode, enumField); + } } -} \ No newline at end of file +} diff --git a/test/transform/resource/after-delombok/FieldNameConstantsBasic.java b/test/transform/resource/after-delombok/FieldNameConstantsBasic.java index 4e547aa5..8be45d2b 100644 --- a/test/transform/resource/after-delombok/FieldNameConstantsBasic.java +++ b/test/transform/resource/after-delombok/FieldNameConstantsBasic.java @@ -1,8 +1,12 @@ public class FieldNameConstantsBasic { - protected static final java.lang.String FIELD_I_AM_A_DVD_PLAYER = "iAmADvdPlayer"; - public static final java.lang.String FIELD_BUT_PRINT_ME_PLEASE = "butPrintMePlease"; String iAmADvdPlayer; int $skipMe; static double skipMeToo; + int andMe; String butPrintMePlease; + @java.lang.SuppressWarnings("all") + static final class Fields { + public static final java.lang.String butPrintMePlease = "butPrintMePlease"; + public static final java.lang.String iAmADvdPlayer = "iAmADvdPlayer"; + } } diff --git a/test/transform/resource/after-delombok/FieldNameConstantsConfigKeys.java b/test/transform/resource/after-delombok/FieldNameConstantsConfigKeys.java index c71b9264..4c2a53e3 100644 --- a/test/transform/resource/after-delombok/FieldNameConstantsConfigKeys.java +++ b/test/transform/resource/after-delombok/FieldNameConstantsConfigKeys.java @@ -1,4 +1,7 @@ public class FieldNameConstantsConfigKeys { - public static final java.lang.String I_AM_A_DVD_PLAYER_SFX = "iAmADvdPlayer"; String iAmADvdPlayer; -} + @java.lang.SuppressWarnings("all") + public static final class Foobar { + public static final java.lang.String iAmADvdPlayer = "iAmADvdPlayer"; + } +} \ No newline at end of file diff --git a/test/transform/resource/after-delombok/FieldNameConstantsEnum.java b/test/transform/resource/after-delombok/FieldNameConstantsEnum.java new file mode 100644 index 00000000..c3fbf0c2 --- /dev/null +++ b/test/transform/resource/after-delombok/FieldNameConstantsEnum.java @@ -0,0 +1,10 @@ +public class FieldNameConstantsEnum { + String iAmADvdPlayer; + int $dontSkipMe; + static double alsoDontSkipMe; + int butSkipMe; + @java.lang.SuppressWarnings("all") + public enum TypeTest { + iAmADvdPlayer, $dontSkipMe, alsoDontSkipMe; + } +} diff --git a/test/transform/resource/after-delombok/FieldNameConstantsWeird.java b/test/transform/resource/after-delombok/FieldNameConstantsWeird.java deleted file mode 100644 index 6940f628..00000000 --- a/test/transform/resource/after-delombok/FieldNameConstantsWeird.java +++ /dev/null @@ -1,6 +0,0 @@ -public class FieldNameConstantsWeird { - public static final java.lang.String FIELD_AZ = "A"; - String iAmADvdPlayer; - String X; - String A; -} diff --git a/test/transform/resource/after-ecj/FieldNameConstantsBasic.java b/test/transform/resource/after-ecj/FieldNameConstantsBasic.java index f77203ba..674dd602 100644 --- a/test/transform/resource/after-ecj/FieldNameConstantsBasic.java +++ b/test/transform/resource/after-ecj/FieldNameConstantsBasic.java @@ -1,15 +1,23 @@ import lombok.experimental.FieldNameConstants; import lombok.AccessLevel; -public @FieldNameConstants class FieldNameConstantsBasic { - public static final java.lang.String FIELD_BUT_PRINT_ME_PLEASE = "butPrintMePlease"; - protected static final java.lang.String FIELD_I_AM_A_DVD_PLAYER = "iAmADvdPlayer"; - @FieldNameConstants(level = AccessLevel.PROTECTED) String iAmADvdPlayer; +public @FieldNameConstants(level = AccessLevel.PACKAGE) class FieldNameConstantsBasic { + static final @java.lang.SuppressWarnings("all") class Fields { + public static final java.lang.String butPrintMePlease = "butPrintMePlease"; + public static final java.lang.String iAmADvdPlayer = "iAmADvdPlayer"; + () { + } + private @java.lang.SuppressWarnings("all") Fields() { + super(); + } + } + String iAmADvdPlayer; int $skipMe; static double skipMeToo; + @FieldNameConstants.Exclude int andMe; String butPrintMePlease; () { } public FieldNameConstantsBasic() { super(); } -} +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/FieldNameConstantsConfigKeys.java b/test/transform/resource/after-ecj/FieldNameConstantsConfigKeys.java index 44629ee5..7eb97364 100644 --- a/test/transform/resource/after-ecj/FieldNameConstantsConfigKeys.java +++ b/test/transform/resource/after-ecj/FieldNameConstantsConfigKeys.java @@ -1,9 +1,14 @@ public @lombok.experimental.FieldNameConstants class FieldNameConstantsConfigKeys { - public static final java.lang.String I_AM_A_DVD_PLAYER_SFX = "iAmADvdPlayer"; - String iAmADvdPlayer; - () { + public static final @java.lang.SuppressWarnings("all") class Foobar { + public static final java.lang.String iAmADvdPlayer = "iAmADvdPlayer"; + () { + } + private @java.lang.SuppressWarnings("all") Foobar() { + super(); + } } + String iAmADvdPlayer; public FieldNameConstantsConfigKeys() { super(); } -} +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/FieldNameConstantsEnum.java b/test/transform/resource/after-ecj/FieldNameConstantsEnum.java new file mode 100644 index 00000000..053a6e7a --- /dev/null +++ b/test/transform/resource/after-ecj/FieldNameConstantsEnum.java @@ -0,0 +1,23 @@ +import lombok.experimental.FieldNameConstants; +import lombok.AccessLevel; +public @FieldNameConstants(onlyExplicitlyIncluded = true,asEnum = true,innerTypeName = "TypeTest") class FieldNameConstantsEnum { + public @java.lang.SuppressWarnings("all") enum TypeTest { + iAmADvdPlayer(), + $dontSkipMe(), + alsoDontSkipMe(), + private @java.lang.SuppressWarnings("all") TypeTest() { + super(); + } + () { + } + } + @FieldNameConstants.Include String iAmADvdPlayer; + @FieldNameConstants.Include int $dontSkipMe; + static @FieldNameConstants.Include double alsoDontSkipMe; + int butSkipMe; + () { + } + public FieldNameConstantsEnum() { + super(); + } +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/FieldNameConstantsWeird.java b/test/transform/resource/after-ecj/FieldNameConstantsWeird.java deleted file mode 100644 index 9958f664..00000000 --- a/test/transform/resource/after-ecj/FieldNameConstantsWeird.java +++ /dev/null @@ -1,13 +0,0 @@ -import lombok.experimental.FieldNameConstants; -import lombok.AccessLevel; -public @FieldNameConstants class FieldNameConstantsWeird { - public static final java.lang.String FIELD_AZ = "A"; - @FieldNameConstants(level = AccessLevel.NONE) String iAmADvdPlayer; - @FieldNameConstants(prefix = "") String X; - @FieldNameConstants(suffix = "Z") String A; - () { - } - public FieldNameConstantsWeird() { - super(); - } -} diff --git a/test/transform/resource/before/FieldNameConstantsBasic.java b/test/transform/resource/before/FieldNameConstantsBasic.java index 1bc15d84..2842dea3 100644 --- a/test/transform/resource/before/FieldNameConstantsBasic.java +++ b/test/transform/resource/before/FieldNameConstantsBasic.java @@ -1,11 +1,11 @@ import lombok.experimental.FieldNameConstants; import lombok.AccessLevel; -@FieldNameConstants +@FieldNameConstants(level = AccessLevel.PACKAGE) public class FieldNameConstantsBasic { - @FieldNameConstants(level = AccessLevel.PROTECTED) String iAmADvdPlayer; int $skipMe; static double skipMeToo; + @FieldNameConstants.Exclude int andMe; String butPrintMePlease; } diff --git a/test/transform/resource/before/FieldNameConstantsConfigKeys.java b/test/transform/resource/before/FieldNameConstantsConfigKeys.java index ab8e3091..5595222c 100644 --- a/test/transform/resource/before/FieldNameConstantsConfigKeys.java +++ b/test/transform/resource/before/FieldNameConstantsConfigKeys.java @@ -1,5 +1,4 @@ -//CONF: lombok.fieldNameConstants.prefix = -//CONF: lombok.fieldNameConstants.suffix = _SFX +//CONF: lombok.fieldNameConstants.innerTypeName = Foobar @lombok.experimental.FieldNameConstants public class FieldNameConstantsConfigKeys { diff --git a/test/transform/resource/before/FieldNameConstantsEnum.java b/test/transform/resource/before/FieldNameConstantsEnum.java new file mode 100644 index 00000000..d56bb280 --- /dev/null +++ b/test/transform/resource/before/FieldNameConstantsEnum.java @@ -0,0 +1,13 @@ +import lombok.experimental.FieldNameConstants; +import lombok.AccessLevel; + +@FieldNameConstants(onlyExplicitlyIncluded = true, asEnum = true, innerTypeName = "TypeTest") +public class FieldNameConstantsEnum { + @FieldNameConstants.Include + String iAmADvdPlayer; + @FieldNameConstants.Include + int $dontSkipMe; + @FieldNameConstants.Include + static double alsoDontSkipMe; + int butSkipMe; +} diff --git a/test/transform/resource/before/FieldNameConstantsWeird.java b/test/transform/resource/before/FieldNameConstantsWeird.java deleted file mode 100644 index 74ec299a..00000000 --- a/test/transform/resource/before/FieldNameConstantsWeird.java +++ /dev/null @@ -1,12 +0,0 @@ -import lombok.experimental.FieldNameConstants; -import lombok.AccessLevel; - -@FieldNameConstants -public class FieldNameConstantsWeird { - @FieldNameConstants(level = AccessLevel.NONE) - String iAmADvdPlayer; - @FieldNameConstants(prefix = "") - String X; - @FieldNameConstants(suffix = "Z") - String A; -} diff --git a/test/transform/resource/messages-delombok/FieldNameConstantsWeird.java.messages b/test/transform/resource/messages-delombok/FieldNameConstantsWeird.java.messages deleted file mode 100644 index 02a38d58..00000000 --- a/test/transform/resource/messages-delombok/FieldNameConstantsWeird.java.messages +++ /dev/null @@ -1 +0,0 @@ -9 Not generating constant for this field: The name of the constant would be equal to the name of this field. diff --git a/test/transform/resource/messages-ecj/FieldNameConstantsWeird.java.messages b/test/transform/resource/messages-ecj/FieldNameConstantsWeird.java.messages deleted file mode 100644 index 02a38d58..00000000 --- a/test/transform/resource/messages-ecj/FieldNameConstantsWeird.java.messages +++ /dev/null @@ -1 +0,0 @@ -9 Not generating constant for this field: The name of the constant would be equal to the name of this field. -- cgit From eeab3c0021503bca69012cf71cbbfe2505be2293 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Sun, 29 Jul 2018 16:37:54 +0200 Subject: A few upgrades for the printers used with @lombok.core.PrintAST. --- src/core/lombok/eclipse/EclipseASTVisitor.java | 105 +++++++++++++++++++++++-- src/core/lombok/javac/JavacASTVisitor.java | 14 ++-- 2 files changed, 107 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/core/lombok/eclipse/EclipseASTVisitor.java b/src/core/lombok/eclipse/EclipseASTVisitor.java index f5b49cbb..63557f41 100644 --- a/src/core/lombok/eclipse/EclipseASTVisitor.java +++ b/src/core/lombok/eclipse/EclipseASTVisitor.java @@ -26,7 +26,9 @@ import static lombok.eclipse.handlers.EclipseHandlerUtil.*; import java.io.PrintStream; import java.lang.reflect.Modifier; +import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.Block; @@ -38,6 +40,7 @@ import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeReference; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; /** * Implement so you can ask any EclipseAST.Node to traverse depth-first through all children, @@ -199,8 +202,82 @@ public interface EclipseASTVisitor { print(""); } + private String printFlags(int flags, ASTNode node) { + StringBuilder out = new StringBuilder(); + if ((flags & ClassFileConstants.AccPublic) != 0) { + flags &= ~ClassFileConstants.AccPublic; + out.append("public "); + } + if ((flags & ClassFileConstants.AccPrivate) != 0) { + flags &= ~ClassFileConstants.AccPrivate; + out.append("private "); + } + if ((flags & ClassFileConstants.AccProtected) != 0) { + flags &= ~ClassFileConstants.AccProtected; + out.append("protected "); + } + if ((flags & ClassFileConstants.AccStatic) != 0) { + flags &= ~ClassFileConstants.AccStatic; + out.append("static "); + } + if ((flags & ClassFileConstants.AccFinal) != 0) { + flags &= ~ClassFileConstants.AccFinal; + out.append("final "); + } + if ((flags & ClassFileConstants.AccSynchronized) != 0) { + flags &= ~ClassFileConstants.AccSynchronized; + out.append("synchronized "); + } + if ((flags & ClassFileConstants.AccNative) != 0) { + flags &= ~ClassFileConstants.AccNative; + out.append("native "); + } + if ((flags & ClassFileConstants.AccInterface) != 0) { + flags &= ~ClassFileConstants.AccInterface; + out.append("interface "); + } + if ((flags & ClassFileConstants.AccAbstract) != 0) { + flags &= ~ClassFileConstants.AccAbstract; + out.append("abstract "); + } + if ((flags & ClassFileConstants.AccStrictfp) != 0) { + flags &= ~ClassFileConstants.AccStrictfp; + out.append("strictfp "); + } + if ((flags & ClassFileConstants.AccSynthetic) != 0) { + flags &= ~ClassFileConstants.AccSynthetic; + out.append("synthetic "); + } + if ((flags & ClassFileConstants.AccAnnotation) != 0) { + flags &= ~ClassFileConstants.AccAnnotation; + out.append("annotation "); + } + if ((flags & ClassFileConstants.AccEnum) != 0) { + flags &= ~ClassFileConstants.AccEnum; + out.append("enum "); + } + + if ((flags & ClassFileConstants.AccVolatile) != 0) { + flags &= ~ClassFileConstants.AccVolatile; + if (node instanceof FieldDeclaration) out.append("volatile "); + else out.append("volatile/bridge "); + } + if ((flags & ClassFileConstants.AccTransient) != 0) { + flags &= ~ClassFileConstants.AccTransient; + if (node instanceof Argument) out.append("varargs "); + else if (node instanceof FieldDeclaration) out.append("transient "); + else out.append("transient/varargs "); + } + + if (flags != 0) { + out.append(String.format(" 0x%08X ", flags)); + } + + return out.toString().trim(); + } + public void visitType(EclipseNode node, TypeDeclaration type) { - print("", str(type.name), isGenerated(type) ? " (GENERATED)" : "", position(node)); + print(" %s", str(type.name), isGenerated(type) ? " (GENERATED)" : "", position(node), printFlags(type.modifiers, type)); indent++; if (printContent) { print("%s", type); @@ -239,8 +316,8 @@ public interface EclipseASTVisitor { } public void visitField(EclipseNode node, FieldDeclaration field) { - print("", isGenerated(field) ? " (GENERATED)" : "", - str(field.type), str(field.name), field.initialization, position(node)); + print(" %s", isGenerated(field) ? " (GENERATED)" : "", + str(field.type), str(field.name), field.initialization, position(node), printFlags(field.modifiers, field)); indent++; if (printContent) { if (field.initialization != null) print("%s", field.initialization); @@ -260,9 +337,13 @@ public interface EclipseASTVisitor { public void visitMethod(EclipseNode node, AbstractMethodDeclaration method) { String type = method instanceof ConstructorDeclaration ? "CONSTRUCTOR" : "METHOD"; - print("<%s %s: %s%s%s>", type, str(method.selector), method.statements != null ? "filled" : "blank", - isGenerated(method) ? " (GENERATED)" : "", position(node)); + print("<%s %s: %s%s%s> %s", type, str(method.selector), method.statements != null ? ("filled(" + method.statements.length + ")") : "blank", + isGenerated(method) ? " (GENERATED)" : "", position(node), printFlags(method.modifiers, method)); indent++; + if (method instanceof ConstructorDeclaration) { + ConstructorDeclaration cd = (ConstructorDeclaration) method; + print("--> constructorCall: %s", cd.constructorCall == null ? "-NONE-" : cd.constructorCall); + } if (printContent) { if (method.statements != null) print("%s", method); disablePrinting++; @@ -281,7 +362,8 @@ public interface EclipseASTVisitor { } public void visitMethodArgument(EclipseNode node, Argument arg, AbstractMethodDeclaration method) { - print("", isGenerated(arg) ? " (GENERATED)" : "", str(arg.type), str(arg.name), arg.initialization, position(node)); + print(" %s", isGenerated(arg) ? " (GENERATED)" : "", + str(arg.type), str(arg.name), arg.initialization, position(node), printFlags(arg.modifiers, arg)); indent++; } @@ -295,7 +377,8 @@ public interface EclipseASTVisitor { } public void visitLocal(EclipseNode node, LocalDeclaration local) { - print("", isGenerated(local) ? " (GENERATED)" : "", str(local.type), str(local.name), local.initialization, position(node)); + print(" %s", isGenerated(local) ? " (GENERATED)" : "", + str(local.type), str(local.name), local.initialization, position(node), printFlags(local.modifiers, local)); indent++; } @@ -310,6 +393,14 @@ public interface EclipseASTVisitor { public void visitStatement(EclipseNode node, Statement statement) { print("<%s%s%s>", statement.getClass(), isGenerated(statement) ? " (GENERATED)" : "", position(node)); + if (statement instanceof AllocationExpression) { + AllocationExpression alloc = (AllocationExpression) statement; + print(" --> arguments: %s", alloc.arguments == null ? "NULL" : alloc.arguments.length); + print(" --> genericTypeArguments: %s", alloc.genericTypeArguments == null ? "NULL" : alloc.genericTypeArguments.length); + print(" --> typeArguments: %s", alloc.typeArguments == null ? "NULL" : alloc.typeArguments.length); + print(" --> enumConstant: %s", alloc.enumConstant); + print(" --> inferredReturnType: %s", alloc.inferredReturnType); + } indent++; print("%s", statement); } diff --git a/src/core/lombok/javac/JavacASTVisitor.java b/src/core/lombok/javac/JavacASTVisitor.java index 565980f9..d4f8f731 100644 --- a/src/core/lombok/javac/JavacASTVisitor.java +++ b/src/core/lombok/javac/JavacASTVisitor.java @@ -149,8 +149,12 @@ public interface JavacASTVisitor { print(""); } + private String printFlags(long f) { + return Flags.toString(f); + } + @Override public void visitType(JavacNode node, JCClassDecl type) { - print("", type.name); + print(" %s", type.name, printFlags(type.mods.flags)); indent++; if (printContent) { print("%s", type); @@ -185,7 +189,7 @@ public interface JavacASTVisitor { } @Override public void visitField(JavacNode node, JCVariableDecl field) { - print("", field.vartype, field.name); + print(" %s", field.vartype, field.name, printFlags(field.mods.flags)); indent++; if (printContent) { if (field.init != null) print("%s", field.init); @@ -210,7 +214,7 @@ public interface JavacASTVisitor { type = "DEFAULTCONSTRUCTOR"; } else type = "CONSTRUCTOR"; } else type = "METHOD"; - print("<%s %s> returns: %s", type, method.name, method.restype); + print("<%s %s> %s returns: %s", type, method.name, printFlags(method.mods.flags), method.restype); indent++; if (printContent) { if (method.body == null) print("(ABSTRACT)"); @@ -230,7 +234,7 @@ public interface JavacASTVisitor { } @Override public void visitMethodArgument(JavacNode node, JCVariableDecl arg, JCMethodDecl method) { - print("", arg.vartype, arg.name); + print(" %s", arg.vartype, arg.name, printFlags(arg.mods.flags)); indent++; } @@ -244,7 +248,7 @@ public interface JavacASTVisitor { } @Override public void visitLocal(JavacNode node, JCVariableDecl local) { - print("", local.vartype, local.name); + print(" %s", local.vartype, local.name, printFlags(local.mods.flags)); indent++; } -- cgit From b9fb35cb8e81d73b9b9b650022a1564b14761885 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Sun, 29 Jul 2018 16:38:16 +0200 Subject: Printing missing gradle integration would print for any non-javac, non-gradle compiler. Fixed that. --- src/core/lombok/core/AnnotationProcessor.java | 25 +++++++++++----------- .../lombok/javac/handlers/HandleFieldDefaults.java | 2 +- 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/core/lombok/core/AnnotationProcessor.java b/src/core/lombok/core/AnnotationProcessor.java index 04448ecb..89dfa555 100644 --- a/src/core/lombok/core/AnnotationProcessor.java +++ b/src/core/lombok/core/AnnotationProcessor.java @@ -49,7 +49,7 @@ import lombok.patcher.ClassRootFinder; @SupportedAnnotationTypes("*") public class AnnotationProcessor extends AbstractProcessor { - + private static String trace(Throwable t) { StringWriter w = new StringWriter(); t.printStackTrace(new PrintWriter(w, true)); @@ -65,7 +65,7 @@ public class AnnotationProcessor extends AbstractProcessor { private final List registered = Arrays.asList(new JavacDescriptor(), new EcjDescriptor()); private final List active = new ArrayList(); private final List delayedWarnings = new ArrayList(); - + /** * This method is a simplified version of {@link lombok.javac.apt.LombokProcessor.getJavacProcessingEnvironment} * It simply returns the processing environment, but in case of gradle incremental compilation, @@ -73,34 +73,35 @@ public class AnnotationProcessor extends AbstractProcessor { */ public static ProcessingEnvironment getJavacProcessingEnvironment(ProcessingEnvironment procEnv, List delayedWarnings) { ProcessingEnvironment javacProcEnv = tryRecursivelyObtainJavacProcessingEnvironment(procEnv); - + if (javacProcEnv == null) { - delayedWarnings.add("Can't get the delegate of the gradle IncrementalProcessingEnvironment."); + if (!procEnv.getClass().getName().startsWith("org.eclipse.jdt.")) { + delayedWarnings.add("Can't get the delegate of the gradle IncrementalProcessingEnvironment."); + } } - + return javacProcEnv; } - + private static ProcessingEnvironment tryRecursivelyObtainJavacProcessingEnvironment(ProcessingEnvironment procEnv) { if (procEnv.getClass().getName().equals("com.sun.tools.javac.processing.JavacProcessingEnvironment")) { return procEnv; } - + for (Class procEnvClass = procEnv.getClass(); procEnvClass != null; procEnvClass = procEnvClass.getSuperclass()) { try { Field field = procEnvClass.getDeclaredField("delegate"); field.setAccessible(true); Object delegate = field.get(procEnv); - + return tryRecursivelyObtainJavacProcessingEnvironment((ProcessingEnvironment) delegate); } catch (final Exception e) { // no valid delegate, try superclass } } - + return null; } - static class JavacDescriptor extends ProcessorDescriptor { private Processor processor; @@ -111,9 +112,9 @@ public class AnnotationProcessor extends AbstractProcessor { @Override boolean want(ProcessingEnvironment procEnv, List delayedWarnings) { ProcessingEnvironment javacProcEnv = getJavacProcessingEnvironment(procEnv, delayedWarnings); - + if (javacProcEnv == null) return false; - + try { ClassLoader classLoader = findAndPatchClassLoader(javacProcEnv); processor = (Processor) Class.forName("lombok.javac.apt.LombokProcessor", false, classLoader).newInstance(); diff --git a/src/core/lombok/javac/handlers/HandleFieldDefaults.java b/src/core/lombok/javac/handlers/HandleFieldDefaults.java index 52f6c39c..aa381c0d 100644 --- a/src/core/lombok/javac/handlers/HandleFieldDefaults.java +++ b/src/core/lombok/javac/handlers/HandleFieldDefaults.java @@ -44,7 +44,7 @@ import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; /** - * Handles the {@code lombok.FieldDefaults} annotation for eclipse. + * Handles the {@code lombok.FieldDefaults} annotation for javac. */ @ProviderFor(JavacASTVisitor.class) @HandlerPriority(-2048) //-2^11; to ensure @Value picks up on messing with the fields' 'final' state, run earlier. -- cgit From 100cff228d0f4d68219460aefe89b70877b726dc Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Mon, 9 Jul 2018 20:29:21 +0200 Subject: reduced calls of traverse invocations --- src/core/lombok/eclipse/HandlerLibrary.java | 18 ++++++++++----- src/core/lombok/eclipse/TransformEclipseAST.java | 28 +++++++++++++++++++----- 2 files changed, 34 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/core/lombok/eclipse/HandlerLibrary.java b/src/core/lombok/eclipse/HandlerLibrary.java index 07c6f97b..75a22f03 100644 --- a/src/core/lombok/eclipse/HandlerLibrary.java +++ b/src/core/lombok/eclipse/HandlerLibrary.java @@ -32,6 +32,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; @@ -212,21 +213,25 @@ public class HandlerLibrary { * @param ast The Compilation Unit that contains the Annotation AST Node. * @param annotationNode The Lombok AST Node representing the Annotation AST Node. * @param annotation 'node.get()' - convenience parameter. + * @param priority current prioritiy + * @return the priority we want to run - MAX_VALUE means never */ - public void handleAnnotation(CompilationUnitDeclaration ast, EclipseNode annotationNode, org.eclipse.jdt.internal.compiler.ast.Annotation annotation, long priority) { + public long handleAnnotation(CompilationUnitDeclaration ast, EclipseNode annotationNode, org.eclipse.jdt.internal.compiler.ast.Annotation annotation, long priority) { TypeResolver resolver = new TypeResolver(annotationNode.getImportList()); TypeReference rawType = annotation.type; - if (rawType == null) return; + if (rawType == null) return Long.MAX_VALUE; String fqn = resolver.typeRefToFullyQualifiedName(annotationNode, typeLibrary, toQualifiedName(annotation.type.getTypeName())); - if (fqn == null) return; + if (fqn == null) return Long.MAX_VALUE; AnnotationHandlerContainer container = annotationHandlers.get(fqn); - if (container == null) return; - if (priority != container.getPriority()) return; + if (container == null) return Long.MAX_VALUE; + + if (priority < container.getPriority()) return container.getPriority(); // we want to run at this priority + if (priority > container.getPriority()) return Long.MAX_VALUE; // it's over- we do not want to run again if (!annotationNode.isCompleteParse() && container.deferUntilPostDiet()) { if (needsHandling(annotation)) container.preHandle(annotation, annotationNode); - return; + return Long.MAX_VALUE; } try { @@ -236,6 +241,7 @@ public class HandlerLibrary { } catch (Throwable t) { error(ast, String.format("Lombok annotation handler %s failed", container.handler.getClass()), t); } + return Long.MAX_VALUE; } /** diff --git a/src/core/lombok/eclipse/TransformEclipseAST.java b/src/core/lombok/eclipse/TransformEclipseAST.java index 541924ad..24e24495 100644 --- a/src/core/lombok/eclipse/TransformEclipseAST.java +++ b/src/core/lombok/eclipse/TransformEclipseAST.java @@ -24,6 +24,8 @@ package lombok.eclipse; import static lombok.eclipse.handlers.EclipseHandlerUtil.*; import java.lang.reflect.Field; +import java.util.HashSet; +import java.util.Set; import lombok.ConfigurationKeys; import lombok.core.LombokConfiguration; @@ -186,42 +188,56 @@ public class TransformEclipseAST { * then handles any PrintASTs. */ public void go() { + long nextPriority = Long.MIN_VALUE; for (Long d : handlers.getPriorities()) { - ast.traverse(new AnnotationVisitor(d)); + if (nextPriority > d) { + continue; + } + AnnotationVisitor visitor = new AnnotationVisitor(d); + ast.traverse(visitor); + // if no visitor interested for this AST, nextPriority would be MAX_VALUE and we bail out immediatetly + nextPriority = visitor.getNextPriority(); handlers.callASTVisitors(ast, d, ast.isCompleteParse()); } } private static class AnnotationVisitor extends EclipseASTAdapter { private final long priority; + // this is the next priority we continue to visit. + // Long.MAX_VALUE means never. Each visit method will potentially reduce the next priority + private long nextPriority = Long.MAX_VALUE; public AnnotationVisitor(long priority) { this.priority = priority; } + public long getNextPriority() { + return nextPriority; + } + @Override public void visitAnnotationOnField(FieldDeclaration field, EclipseNode annotationNode, Annotation annotation) { CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get(); - handlers.handleAnnotation(top, annotationNode, annotation, priority); + nextPriority = Math.min(nextPriority, handlers.handleAnnotation(top, annotationNode, annotation, priority)); } @Override public void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, EclipseNode annotationNode, Annotation annotation) { CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get(); - handlers.handleAnnotation(top, annotationNode, annotation, priority); + nextPriority = Math.min(nextPriority, handlers.handleAnnotation(top, annotationNode, annotation, priority)); } @Override public void visitAnnotationOnLocal(LocalDeclaration local, EclipseNode annotationNode, Annotation annotation) { CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get(); - handlers.handleAnnotation(top, annotationNode, annotation, priority); + nextPriority = Math.min(nextPriority, handlers.handleAnnotation(top, annotationNode, annotation, priority)); } @Override public void visitAnnotationOnMethod(AbstractMethodDeclaration method, EclipseNode annotationNode, Annotation annotation) { CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get(); - handlers.handleAnnotation(top, annotationNode, annotation, priority); + nextPriority = Math.min(nextPriority, handlers.handleAnnotation(top, annotationNode, annotation, priority)); } @Override public void visitAnnotationOnType(TypeDeclaration type, EclipseNode annotationNode, Annotation annotation) { CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get(); - handlers.handleAnnotation(top, annotationNode, annotation, priority); + nextPriority = Math.min(nextPriority, handlers.handleAnnotation(top, annotationNode, annotation, priority)); } } } -- cgit From 40570f7950dc05f90bea05396c9d23d426fe99ba Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Sun, 8 Jul 2018 21:46:12 +0200 Subject: optimized the to/fromQualifiedName method --- src/utils/lombok/eclipse/Eclipse.java | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/utils/lombok/eclipse/Eclipse.java b/src/utils/lombok/eclipse/Eclipse.java index 5ef33086..943a7a7a 100644 --- a/src/utils/lombok/eclipse/Eclipse.java +++ b/src/utils/lombok/eclipse/Eclipse.java @@ -56,6 +56,8 @@ public class Eclipse { */ public static final int ECLIPSE_DO_NOT_TOUCH_FLAG = ASTNode.Bit24; + private static final Pattern SPLIT_AT_DOT = Pattern.compile("\\."); + private Eclipse() { //Prevent instantiation } @@ -65,19 +67,25 @@ public class Eclipse { * but we need to deal with it. This turns [[java][lang][String]] into "java.lang.String". */ public static String toQualifiedName(char[][] typeName) { - int len = typeName.length - 1; + int len = typeName.length - 1; // number of dots + if (len == 0) return new String(typeName[0]); + for (char[] c : typeName) len += c.length; - StringBuilder sb = new StringBuilder(len); - boolean first = true; - for (char[] c : typeName) { - sb.append(first ? "" : ".").append(c); - first = false; + char[] ret = new char[len]; + char[] part = typeName[0]; + System.arraycopy(part, 0, ret, 0, part.length); + int pos = part.length; + for (int i = 1; i < typeName.length; i++) { + ret[pos++] = '.'; + part = typeName[i]; + System.arraycopy(part, 0, ret, pos, part.length); + pos += part.length; } - return sb.toString(); + return new String(ret); } public static char[][] fromQualifiedName(String typeName) { - String[] split = typeName.split("\\."); + String[] split = SPLIT_AT_DOT.split(typeName); char[][] result = new char[split.length][]; for (int i = 0; i < split.length; i++) { result[i] = split[i].toCharArray(); -- cgit From 46377b1be44c564ea7e37f30ddd7d81faf19d45e Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Mon, 9 Jul 2018 01:06:44 +0200 Subject: do not scan classes from java or sun package for extensions --- src/launch/lombok/launch/ShadowClassLoader.java | 28 ++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/launch/lombok/launch/ShadowClassLoader.java b/src/launch/lombok/launch/ShadowClassLoader.java index 32363469..5489f3ea 100644 --- a/src/launch/lombok/launch/ShadowClassLoader.java +++ b/src/launch/lombok/launch/ShadowClassLoader.java @@ -296,17 +296,18 @@ class ShadowClassLoader extends ClassLoader { return null; } - private boolean partOfShadow(URL item, String name) { - return inOwnBase(item, name) || isPartOfShadowSuffix(item, name, sclSuffix); + private boolean partOfShadow(String item, String name) { + return !name.startsWith("java/") + && !name.startsWith("sun/") + && (inOwnBase(item, name) || isPartOfShadowSuffix(item, name, sclSuffix)); } /** * Checks if the stated item is located inside the same classpath root as the jar that hosts ShadowClassLoader.class. {@code item} and {@code name} refer to the same thing. */ - private boolean inOwnBase(URL item, String name) { + private boolean inOwnBase(String item, String name) { if (item == null) return false; - String itemString = item.toString(); - return (itemString.length() == SELF_BASE_LENGTH + name.length()) && SELF_BASE.regionMatches(0, itemString, 0, SELF_BASE_LENGTH); + return (item.length() == SELF_BASE_LENGTH + name.length()) && SELF_BASE.regionMatches(0, item, 0, SELF_BASE_LENGTH); } private static boolean sclFileContainsSuffix(InputStream in, String suffix) throws IOException { @@ -386,12 +387,11 @@ class ShadowClassLoader extends ClassLoader { } } - private boolean isPartOfShadowSuffix(URL item, String name, String suffix) { + private boolean isPartOfShadowSuffix(String url, String name, String suffix) { // Instead of throwing an exception or logging, weird, unexpected cases just return false. // This is better than throwing an exception, because exceptions would make your build tools unusable. // Such cases are marked with the comment: // *unexpected* - if (item == null) return false; - String url = item.toString(); + if (url == null) return false; if (url.startsWith("file:/")) { url = urlDecode(url.substring(5)); if (url.length() <= name.length() || !url.endsWith(name) || url.charAt(url.length() - name.length() - 1) != '/') { @@ -436,14 +436,14 @@ class ShadowClassLoader extends ClassLoader { Enumeration sec = super.getResources(name); while (sec.hasMoreElements()) { URL item = sec.nextElement(); - if (!partOfShadow(item, name)) vector.add(item); + if (!partOfShadow(item.toString(), name)) vector.add(item); } if (altName != null) { Enumeration tern = super.getResources(altName); while (tern.hasMoreElements()) { URL item = tern.nextElement(); - if (!partOfShadow(item, altName)) vector.add(item); + if (!partOfShadow(item.toString(), altName)) vector.add(item); } } @@ -483,11 +483,11 @@ class ShadowClassLoader extends ClassLoader { if (altName != null) { URL res = super.getResource(altName); - if (res != null && (!noSuper || partOfShadow(res, altName))) return res; + if (res != null && (!noSuper || partOfShadow(res.toString(), altName))) return res; } URL res = super.getResource(name); - if (res != null && (!noSuper || partOfShadow(res, name))) return res; + if (res != null && (!noSuper || partOfShadow(res.toString(), name))) return res; return null; } @@ -501,12 +501,12 @@ class ShadowClassLoader extends ClassLoader { private URL getResourceSkippingSelf(String name) throws IOException { URL candidate = super.getResource(name); if (candidate == null) return null; - if (!partOfShadow(candidate, name)) return candidate; + if (!partOfShadow(candidate.toString(), name)) return candidate; Enumeration en = super.getResources(name); while (en.hasMoreElements()) { candidate = en.nextElement(); - if (!partOfShadow(candidate, name)) return candidate; + if (!partOfShadow(candidate.toString(), name)) return candidate; } return null; -- cgit From fe2117e7796e8f85b5710944bfd3efb499c87865 Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Sun, 8 Jul 2018 16:57:00 +0200 Subject: using map.get instead of searching for entry --- src/core/lombok/core/LombokInternalAliasing.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/core/lombok/core/LombokInternalAliasing.java b/src/core/lombok/core/LombokInternalAliasing.java index 3dc1bfa2..c1089580 100644 --- a/src/core/lombok/core/LombokInternalAliasing.java +++ b/src/core/lombok/core/LombokInternalAliasing.java @@ -36,10 +36,8 @@ public class LombokInternalAliasing { */ public static String processAliases(String in) { if (in == null) return null; - for (Map.Entry e : ALIASES.entrySet()) { - if (in.equals(e.getKey())) return e.getValue(); - } - return in; + String ret = ALIASES.get(in); + return ret == null ? in : ret; } static { -- cgit From 763b384a169d3303ff82a044ec7be68be92691b1 Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Sun, 8 Jul 2018 17:18:54 +0200 Subject: Do not use reflection to check if annotation is present --- src/core/lombok/eclipse/EclipseASTAdapter.java | 7 +++++++ src/core/lombok/eclipse/EclipseASTVisitor.java | 6 ++++++ src/core/lombok/eclipse/EclipseNode.java | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/lombok/eclipse/EclipseASTAdapter.java b/src/core/lombok/eclipse/EclipseASTAdapter.java index 2a78c270..61807fff 100644 --- a/src/core/lombok/eclipse/EclipseASTAdapter.java +++ b/src/core/lombok/eclipse/EclipseASTAdapter.java @@ -36,6 +36,9 @@ import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; * has been implemented with an empty body. Override whichever methods you need. */ public abstract class EclipseASTAdapter implements EclipseASTVisitor { + + private final boolean deferUntilPostDiet = getClass().isAnnotationPresent(DeferUntilPostDiet.class); + /** {@inheritDoc} */ public void visitCompilationUnit(EclipseNode top, CompilationUnitDeclaration unit) {} @@ -98,4 +101,8 @@ public abstract class EclipseASTAdapter implements EclipseASTVisitor { /** {@inheritDoc} */ public void endVisitStatement(EclipseNode statementNode, Statement statement) {} + + public boolean isDeferUntilPostDiet() { + return deferUntilPostDiet ; + } } diff --git a/src/core/lombok/eclipse/EclipseASTVisitor.java b/src/core/lombok/eclipse/EclipseASTVisitor.java index 63557f41..b2fd4b2f 100644 --- a/src/core/lombok/eclipse/EclipseASTVisitor.java +++ b/src/core/lombok/eclipse/EclipseASTVisitor.java @@ -416,5 +416,11 @@ public interface EclipseASTVisitor { int end = node.get().sourceEnd(); return String.format(" [%d, %d]", start, end); } + + public boolean isDeferUntilPostDiet() { + return false; + } } + + boolean isDeferUntilPostDiet(); } diff --git a/src/core/lombok/eclipse/EclipseNode.java b/src/core/lombok/eclipse/EclipseNode.java index 4db1d38d..4e05fb30 100644 --- a/src/core/lombok/eclipse/EclipseNode.java +++ b/src/core/lombok/eclipse/EclipseNode.java @@ -53,7 +53,7 @@ public class EclipseNode extends lombok.core.LombokNode Date: Mon, 9 Jul 2018 01:03:47 +0200 Subject: Share the same class loader --- src/eclipseAgent/lombok/launch/PatchFixesHider.java | 2 +- src/launch/lombok/launch/Agent.java | 2 +- src/launch/lombok/launch/AnnotationProcessor.java | 2 +- src/launch/lombok/launch/Main.java | 12 +++++++++--- 4 files changed, 12 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/eclipseAgent/lombok/launch/PatchFixesHider.java b/src/eclipseAgent/lombok/launch/PatchFixesHider.java index 317b06a4..3c70d81d 100644 --- a/src/eclipseAgent/lombok/launch/PatchFixesHider.java +++ b/src/eclipseAgent/lombok/launch/PatchFixesHider.java @@ -92,7 +92,7 @@ final class PatchFixesHider { shadowLoader = Util.class.getClassLoader(); } catch (ClassNotFoundException e) { // If we get here, it isn't, and we should use the shadowloader. - shadowLoader = Main.createShadowClassLoader(); + shadowLoader = Main.getShadowClassLoader(); } } diff --git a/src/launch/lombok/launch/Agent.java b/src/launch/lombok/launch/Agent.java index 7989e51f..357a8e48 100644 --- a/src/launch/lombok/launch/Agent.java +++ b/src/launch/lombok/launch/Agent.java @@ -35,7 +35,7 @@ final class Agent { } private static void runLauncher(String agentArgs, Instrumentation instrumentation, boolean injected) throws Throwable { - ClassLoader cl = Main.createShadowClassLoader(); + ClassLoader cl = Main.getShadowClassLoader(); try { Class c = cl.loadClass("lombok.core.AgentLauncher"); Method m = c.getDeclaredMethod("runAgents", String.class, Instrumentation.class, boolean.class, Class.class); diff --git a/src/launch/lombok/launch/AnnotationProcessor.java b/src/launch/lombok/launch/AnnotationProcessor.java index c4f922b9..b03dec76 100644 --- a/src/launch/lombok/launch/AnnotationProcessor.java +++ b/src/launch/lombok/launch/AnnotationProcessor.java @@ -104,7 +104,7 @@ class AnnotationProcessorHider { } private static AbstractProcessor createWrappedInstance() { - ClassLoader cl = Main.createShadowClassLoader(); + ClassLoader cl = Main.getShadowClassLoader(); try { Class mc = cl.loadClass("lombok.core.AnnotationProcessor"); return (AbstractProcessor) mc.getDeclaredConstructor().newInstance(); diff --git a/src/launch/lombok/launch/Main.java b/src/launch/lombok/launch/Main.java index b81b6268..82913f8e 100644 --- a/src/launch/lombok/launch/Main.java +++ b/src/launch/lombok/launch/Main.java @@ -25,12 +25,18 @@ import java.lang.reflect.InvocationTargetException; import java.util.Arrays; class Main { - static ClassLoader createShadowClassLoader() { - return new ShadowClassLoader(Main.class.getClassLoader(), "lombok", null, Arrays.asList(), Arrays.asList("lombok.patcher.Symbols")); + + private static ShadowClassLoader classLoader; + + static synchronized ClassLoader getShadowClassLoader() { + if (classLoader == null) { + classLoader = new ShadowClassLoader(Main.class.getClassLoader(), "lombok", null, Arrays.asList(), Arrays.asList("lombok.patcher.Symbols")); + } + return classLoader; } public static void main(String[] args) throws Throwable { - ClassLoader cl = createShadowClassLoader(); + ClassLoader cl = getShadowClassLoader(); Class mc = cl.loadClass("lombok.core.Main"); try { mc.getMethod("main", String[].class).invoke(null, new Object[] {args}); -- cgit From 8151e710fc9add7232f2828bc069077d6eb1c457 Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Mon, 9 Jul 2018 01:05:35 +0200 Subject: FIX: omit warning "Can't get the delegate of the gradle IncrementalProcessingEnvironment." in eclipse build. --- src/core/lombok/core/AnnotationProcessor.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/lombok/core/AnnotationProcessor.java b/src/core/lombok/core/AnnotationProcessor.java index 89dfa555..d2efa87c 100644 --- a/src/core/lombok/core/AnnotationProcessor.java +++ b/src/core/lombok/core/AnnotationProcessor.java @@ -111,6 +111,9 @@ public class AnnotationProcessor extends AbstractProcessor { } @Override boolean want(ProcessingEnvironment procEnv, List delayedWarnings) { + // do not run on ECJ as it may print warnings + if (procEnv.getClass().getName().startsWith("org.eclipse.jdt.")) return false; + ProcessingEnvironment javacProcEnv = getJavacProcessingEnvironment(procEnv, delayedWarnings); if (javacProcEnv == null) return false; @@ -210,7 +213,7 @@ public class AnnotationProcessor extends AbstractProcessor { for (TypeElement elem : annotations) { zeroElems = false; Name n = elem.getQualifiedName(); - if (n.length() > 7 && n.subSequence(0, 7).toString().equals("lombok.")) continue; + if (n.toString().startsWith("lombok.")) continue; onlyLombok = false; } -- cgit From d2ec0e7bdd8faea3ad5553a276299573fb52ff78 Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Sun, 8 Jul 2018 16:54:20 +0200 Subject: replace Collection by FieldAccess[] array (saves iterator instance) --- src/core/lombok/core/AST.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/core/lombok/core/AST.java b/src/core/lombok/core/AST.java index 1142018f..fe7a4330 100644 --- a/src/core/lombok/core/AST.java +++ b/src/core/lombok/core/AST.java @@ -216,19 +216,19 @@ public abstract class AST, L extends LombokNode, } } - private static final ConcurrentMap, Collection> fieldsOfASTClasses = new ConcurrentHashMap, Collection>(); + private static final ConcurrentMap, FieldAccess[]> fieldsOfASTClasses = new ConcurrentHashMap, FieldAccess[]>(); /** Returns FieldAccess objects for the stated class. Each field that contains objects of the kind returned by * {@link #getStatementTypes()}, either directly or inside of an array or java.util.collection (or array-of-arrays, * or collection-of-collections, et cetera), is returned. */ - protected Collection fieldsOf(Class c) { - Collection fields = fieldsOfASTClasses.get(c); + protected FieldAccess[] fieldsOf(Class c) { + FieldAccess[] fields = fieldsOfASTClasses.get(c); if (fields != null) return fields; - fields = new ArrayList(); - getFields(c, fields); - fieldsOfASTClasses.putIfAbsent(c, fields); + List fieldList = new ArrayList(); + getFields(c, fieldList); + fieldsOfASTClasses.putIfAbsent(c, fieldList.toArray(new FieldAccess[fieldList.size()])); return fieldsOfASTClasses.get(c); } -- cgit From 0904b1fd3a831ca5e056921bb37f51c759e2e074 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Thu, 16 Aug 2018 11:47:25 +0200 Subject: [fixes #1759] ‘flag usage’ check on builder for eclipse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/lombok/eclipse/handlers/HandleBuilder.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index e1b1af26..4301e51a 100644 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -146,6 +146,8 @@ public class HandleBuilder extends EclipseAnnotationHandler { } @Override public void handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) { + handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder"); + long p = (long) ast.sourceStart << 32 | ast.sourceEnd; Builder builderInstance = annotation.getInstance(); -- cgit From 13c1fde7a0102fc951a8a488943681f1c57ea27e Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Mon, 20 Aug 2018 21:37:14 +0200 Subject: [fixes #1813] erroneous message on eclipse that lombok ‘can’t get the delegate of the gradle IncrementalProcessingEnvironment’. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/lombok/core/AnnotationProcessor.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'src') diff --git a/src/core/lombok/core/AnnotationProcessor.java b/src/core/lombok/core/AnnotationProcessor.java index d2efa87c..293bfef6 100644 --- a/src/core/lombok/core/AnnotationProcessor.java +++ b/src/core/lombok/core/AnnotationProcessor.java @@ -72,15 +72,7 @@ public class AnnotationProcessor extends AbstractProcessor { * the delegate ProcessingEnvironment of the gradle wrapper is returned. */ public static ProcessingEnvironment getJavacProcessingEnvironment(ProcessingEnvironment procEnv, List delayedWarnings) { - ProcessingEnvironment javacProcEnv = tryRecursivelyObtainJavacProcessingEnvironment(procEnv); - - if (javacProcEnv == null) { - if (!procEnv.getClass().getName().startsWith("org.eclipse.jdt.")) { - delayedWarnings.add("Can't get the delegate of the gradle IncrementalProcessingEnvironment."); - } - } - - return javacProcEnv; + return tryRecursivelyObtainJavacProcessingEnvironment(procEnv); } private static ProcessingEnvironment tryRecursivelyObtainJavacProcessingEnvironment(ProcessingEnvironment procEnv) { -- cgit From a31e9ffdac96737f5a441efa6c80a2394bba63d1 Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Sun, 8 Jul 2018 17:01:26 +0200 Subject: use delared ast Type instead of generic one saves a lot of "checkcasts" in the byte code --- src/core/lombok/core/LombokNode.java | 38 ++++++++++++++------------------ src/core/lombok/eclipse/EclipseNode.java | 8 ++++++- src/core/lombok/javac/JavacNode.java | 9 +++++++- 3 files changed, 32 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/core/lombok/core/LombokNode.java b/src/core/lombok/core/LombokNode.java index d6708956..5a0842bc 100644 --- a/src/core/lombok/core/LombokNode.java +++ b/src/core/lombok/core/LombokNode.java @@ -40,7 +40,6 @@ import lombok.core.AST.Kind; * For example, JCTree for javac, and ASTNode for Eclipse. */ public abstract class LombokNode, L extends LombokNode, N> implements DiagnosticsReceiver { - protected final A ast; protected final Kind kind; protected final N node; protected LombokImmutableList children; @@ -59,8 +58,7 @@ public abstract class LombokNode, L extends LombokNode children, Kind kind) { - this.ast = ast; + protected LombokNode(N node, List children, Kind kind) { this.kind = kind; this.node = node; this.children = children != null ? LombokImmutableList.copyOf(children) : LombokImmutableList.of(); @@ -72,9 +70,7 @@ public abstract class LombokNode, L extends LombokNode, L extends LombokNode, L extends LombokNode, L extends LombokNode, L extends LombokNode, L extends LombokNode, L extends LombokNode, L extends LombokNode, L extends LombokNode, L extends LombokNode oldNodes = new IdentityHashMap(); gatherAndRemoveChildren(oldNodes); - L newNode = ast.buildTree(get(), kind); + L newNode = getAst().buildTree(get(), kind); - ast.setChanged(); + getAst().setChanged(); - ast.replaceNewWithExistingOld(oldNodes, newNode); + getAst().replaceNewWithExistingOld(oldNodes, newNode); } @SuppressWarnings({"unchecked", "rawtypes"}) private void gatherAndRemoveChildren(Map map) { for (LombokNode child : children) child.gatherAndRemoveChildren(map); - ast.identityDetector.remove(get()); + getAst().identityDetector.remove(get()); map.put(get(), (L) this); children = LombokImmutableList.of(); - ast.getNodeMap().remove(get()); + getAst().getNodeMap().remove(get()); } /** @@ -264,7 +260,7 @@ public abstract class LombokNode, L extends LombokNode { + private EclipseAST ast; /** {@inheritDoc} */ EclipseNode(EclipseAST ast, ASTNode node, List children, Kind kind) { - super(ast, node, children, kind); + super(node, children, kind); + this.ast = ast; } + @Override + public EclipseAST getAst() { + return ast; + } /** * Visits this node and all child nodes depth-first, calling the provided visitor's visit methods. */ diff --git a/src/core/lombok/javac/JavacNode.java b/src/core/lombok/javac/JavacNode.java index 2bce6e3a..3963c892 100644 --- a/src/core/lombok/javac/JavacNode.java +++ b/src/core/lombok/javac/JavacNode.java @@ -50,11 +50,18 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; * Javac specific version of the LombokNode class. */ public class JavacNode extends lombok.core.LombokNode { + private JavacAST ast; /** * Passes through to the parent constructor. */ public JavacNode(JavacAST ast, JCTree node, List children, Kind kind) { - super(ast, node, children, kind); + super(node, children, kind); + this.ast = ast; + } + + @Override + public JavacAST getAst() { + return ast; } public Element getElement() { -- cgit From 35fe755b87f194621b5f328e4773f1f406f8ccc9 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Mon, 20 Aug 2018 23:44:31 +0200 Subject: bugfix for the new ‘find the next priority’ system committed earlier; it should also find next priority for the astvisitors (only the annotation visitors were being considered). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/lombok/core/configuration/StringConfigurationSource.java | 1 - src/core/lombok/eclipse/HandlerLibrary.java | 8 +++++--- src/core/lombok/eclipse/TransformEclipseAST.java | 8 ++------ src/core/lombok/javac/apt/LombokProcessor.java | 6 +++--- test/core/src/lombok/RunTestsViaEcj.java | 2 +- 5 files changed, 11 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/core/lombok/core/configuration/StringConfigurationSource.java b/src/core/lombok/core/configuration/StringConfigurationSource.java index dd2f0319..abf6eea0 100644 --- a/src/core/lombok/core/configuration/StringConfigurationSource.java +++ b/src/core/lombok/core/configuration/StringConfigurationSource.java @@ -67,7 +67,6 @@ public class StringConfigurationSource implements ConfigurationSource { list.add(new ListModification(value, add)); } }); - return new StringConfigurationSource(values); } diff --git a/src/core/lombok/eclipse/HandlerLibrary.java b/src/core/lombok/eclipse/HandlerLibrary.java index 75a22f03..0e72fb38 100644 --- a/src/core/lombok/eclipse/HandlerLibrary.java +++ b/src/core/lombok/eclipse/HandlerLibrary.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2014 The Project Lombok Authors. + * Copyright (C) 2009-2018 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 @@ -32,7 +32,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; @@ -247,8 +246,10 @@ public class HandlerLibrary { /** * Will call all registered {@link EclipseASTVisitor} instances. */ - public void callASTVisitors(EclipseAST ast, long priority, boolean isCompleteParse) { + public long callASTVisitors(EclipseAST ast, long priority, boolean isCompleteParse) { + long nearestPriority = Long.MAX_VALUE; for (VisitorContainer container : visitorHandlers) { + if (priority < container.getPriority()) nearestPriority = Math.min(container.getPriority(), nearestPriority); if (!isCompleteParse && container.deferUntilPostDiet()) continue; if (priority != container.getPriority()) continue; try { @@ -258,5 +259,6 @@ public class HandlerLibrary { String.format("Lombok visitor handler %s failed", container.visitor.getClass()), t); } } + return nearestPriority; } } diff --git a/src/core/lombok/eclipse/TransformEclipseAST.java b/src/core/lombok/eclipse/TransformEclipseAST.java index 24e24495..323fc171 100644 --- a/src/core/lombok/eclipse/TransformEclipseAST.java +++ b/src/core/lombok/eclipse/TransformEclipseAST.java @@ -24,8 +24,6 @@ package lombok.eclipse; import static lombok.eclipse.handlers.EclipseHandlerUtil.*; import java.lang.reflect.Field; -import java.util.HashSet; -import java.util.Set; import lombok.ConfigurationKeys; import lombok.core.LombokConfiguration; @@ -190,14 +188,12 @@ public class TransformEclipseAST { public void go() { long nextPriority = Long.MIN_VALUE; for (Long d : handlers.getPriorities()) { - if (nextPriority > d) { - continue; - } + if (nextPriority > d) continue; AnnotationVisitor visitor = new AnnotationVisitor(d); ast.traverse(visitor); // if no visitor interested for this AST, nextPriority would be MAX_VALUE and we bail out immediatetly nextPriority = visitor.getNextPriority(); - handlers.callASTVisitors(ast, d, ast.isCompleteParse()); + nextPriority = Math.min(nextPriority, handlers.callASTVisitors(ast, d, ast.isCompleteParse())); } } diff --git a/src/core/lombok/javac/apt/LombokProcessor.java b/src/core/lombok/javac/apt/LombokProcessor.java index 04b494bf..89608546 100644 --- a/src/core/lombok/javac/apt/LombokProcessor.java +++ b/src/core/lombok/javac/apt/LombokProcessor.java @@ -166,13 +166,13 @@ public class LombokProcessor extends AbstractProcessor { if (!(originalFiler instanceof InterceptingJavaFileManager)) { final Messager messager = processingEnv.getMessager(); DiagnosticsReceiver receiver = new MessagerDiagnosticsReceiver(messager); - + JavaFileManager newFilerManager = new InterceptingJavaFileManager(originalFiler, receiver); ht.put(key, newFilerManager); Field filerFileManagerField = JavacFiler.class.getDeclaredField("fileManager"); filerFileManagerField.setAccessible(true); filerFileManagerField.set(javacFiler, newFilerManager); - + replaceFileManagerJdk9(context, newFilerManager); } } catch (Exception e) { @@ -429,7 +429,7 @@ public class LombokProcessor extends AbstractProcessor { } /** - * This class returns the given filer as a JavacFiler. In case the case that the filer is no + * This class returns the given filer as a JavacFiler. In case the filer is no * JavacFiler (e.g. the Gradle IncrementalFiler), its "delegate" field is used to get the JavacFiler * (directly or through a delegate field again) */ diff --git a/test/core/src/lombok/RunTestsViaEcj.java b/test/core/src/lombok/RunTestsViaEcj.java index 4e6a6a55..3efe38f5 100644 --- a/test/core/src/lombok/RunTestsViaEcj.java +++ b/test/core/src/lombok/RunTestsViaEcj.java @@ -122,7 +122,7 @@ public class RunTestsViaEcj extends AbstractRunTests { CompilationUnitDeclaration cud = compilationUnit_.get(); - if (cud == null) result.append("---- NO CompilationUnit provided by ecj ----"); + if (cud == null) result.append("---- No CompilationUnit provided by ecj ----"); else result.append(cud.toString()); return true; -- cgit From ca35539f7cd7967bfd8518d0ad0b0015bdd40cfc Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Tue, 21 Aug 2018 00:01:40 +0200 Subject: [fixes #1812] `@Singular` marked collections which nevertheless somehow ended up null would cause an NPE during `toBuilder()` invocations. --- .../eclipse/handlers/EclipseHandlerUtil.java | 26 +++++++++ .../lombok/eclipse/handlers/HandleBuilder.java | 34 +++++++++--- .../eclipse/handlers/HandleEqualsAndHashCode.java | 26 --------- src/core/lombok/javac/handlers/HandleBuilder.java | 28 +++++++--- .../BuilderSingularToBuilderWithNull.java | 63 ++++++++++++++++++++++ .../after-delombok/BuilderWithToBuilder.java | 2 +- .../BuilderSingularToBuilderWithNull.java | 57 ++++++++++++++++++++ .../resource/after-ecj/BuilderWithToBuilder.java | 2 +- .../before/BuilderSingularToBuilderWithNull.java | 10 ++++ 9 files changed, 206 insertions(+), 42 deletions(-) create mode 100644 test/transform/resource/after-delombok/BuilderSingularToBuilderWithNull.java create mode 100644 test/transform/resource/after-ecj/BuilderSingularToBuilderWithNull.java create mode 100644 test/transform/resource/before/BuilderSingularToBuilderWithNull.java (limited to 'src') diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 2dce285c..87df6d1b 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -24,6 +24,7 @@ package lombok.eclipse.handlers; import static lombok.core.handlers.HandlerUtil.*; import static lombok.eclipse.Eclipse.*; import static lombok.eclipse.EclipseAugments.*; +import static lombok.eclipse.handlers.EclipseHandlerUtil.setGeneratedBy; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -1862,4 +1863,29 @@ public class EclipseHandlerUtil { String p = typeDecl.superclass.toString(); return p.equals("Object") || p.equals("java.lang.Object"); } + + public static NameReference generateQualifiedNameRef(ASTNode source, char[]... varNames) { + int pS = source.sourceStart, pE = source.sourceEnd; + long p = (long)pS << 32 | pE; + + NameReference ref; + + if (varNames.length > 1) ref = new QualifiedNameReference(varNames, new long[varNames.length], pS, pE); + else ref = new SingleNameReference(varNames[0], p); + setGeneratedBy(ref, source); + return ref; + } + + public static TypeReference generateQualifiedTypeRef(ASTNode source, char[]... varNames) { + int pS = source.sourceStart, pE = source.sourceEnd; + long p = (long)pS << 32 | pE; + + TypeReference ref; + + long[] poss = Eclipse.poss(source, varNames.length); + if (varNames.length > 1) ref = new QualifiedTypeReference(varNames, poss); + else ref = new SingleTypeReference(varNames[0], p); + setGeneratedBy(ref, source); + return ref; + } } diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 4301e51a..9a069c58 100644 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -40,6 +40,7 @@ import org.eclipse.jdt.internal.compiler.ast.Assignment; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression; import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; +import org.eclipse.jdt.internal.compiler.ast.EqualExpression; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FalseLiteral; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; @@ -47,6 +48,7 @@ import org.eclipse.jdt.internal.compiler.ast.FieldReference; import org.eclipse.jdt.internal.compiler.ast.IfStatement; import org.eclipse.jdt.internal.compiler.ast.MessageSend; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.NullLiteral; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference; @@ -492,6 +494,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { } } + private static final char[] EMPTY_LIST = "emptyList".toCharArray(); private MethodDeclaration generateToBuilderMethod(String methodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, List builderFields, boolean fluent, ASTNode source) { // return new ThingieBuilder().setA(this.a).setB(this.b); @@ -511,19 +514,34 @@ public class HandleBuilder extends EclipseAnnotationHandler { for (BuilderFieldData bfd : builderFields) { char[] setterName = fluent ? bfd.name : HandlerUtil.buildAccessorName("set", new String(bfd.name)).toCharArray(); MessageSend ms = new MessageSend(); + Expression[] tgt = new Expression[bfd.singularData == null ? 1 : 2]; + if (bfd.obtainVia == null || !bfd.obtainVia.field().isEmpty()) { char[] fieldName = bfd.obtainVia == null ? bfd.rawName : bfd.obtainVia.field().toCharArray(); - FieldReference fr = new FieldReference(fieldName, 0); - fr.receiver = new ThisReference(0, 0); - ms.arguments = new Expression[] {fr}; + for (int i = 0; i < tgt.length; i++) { + FieldReference fr = new FieldReference(fieldName, 0); + fr.receiver = new ThisReference(0, 0); + tgt[i] = fr; + } } else { String obtainName = bfd.obtainVia.method(); boolean obtainIsStatic = bfd.obtainVia.isStatic(); - MessageSend obtainExpr = new MessageSend(); - obtainExpr.receiver = obtainIsStatic ? new SingleNameReference(type.getName().toCharArray(), 0) : new ThisReference(0, 0); - obtainExpr.selector = obtainName.toCharArray(); - if (obtainIsStatic) obtainExpr.arguments = new Expression[] {new ThisReference(0, 0)}; - ms.arguments = new Expression[] {obtainExpr}; + for (int i = 0; i < tgt.length; i++) { + MessageSend obtainExpr = new MessageSend(); + obtainExpr.receiver = obtainIsStatic ? new SingleNameReference(type.getName().toCharArray(), 0) : new ThisReference(0, 0); + obtainExpr.selector = obtainName.toCharArray(); + if (obtainIsStatic) obtainExpr.arguments = new Expression[] {new ThisReference(0, 0)}; + tgt[i] = obtainExpr; + } + } + if (bfd.singularData == null) { + ms.arguments = tgt; + } else { + Expression ifNull = new EqualExpression(tgt[0], new NullLiteral(0, 0), OperatorIds.EQUAL_EQUAL); + MessageSend emptyList = new MessageSend(); + emptyList.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA, TypeConstants.UTIL, "Collections".toCharArray()); + emptyList.selector = EMPTY_LIST; + ms.arguments = new Expression[] {new ConditionalExpression(ifNull, emptyList, tgt[1])}; } ms.receiver = receiver; ms.selector = setterName; diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java index c99b9b5f..6945e5d9 100644 --- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java @@ -69,7 +69,6 @@ import org.eclipse.jdt.internal.compiler.ast.NullLiteral; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference; -import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; @@ -819,29 +818,4 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler 1) ref = new QualifiedNameReference(varNames, new long[varNames.length], pS, pE); - else ref = new SingleNameReference(varNames[0], p); - setGeneratedBy(ref, source); - return ref; - } - - public TypeReference generateQualifiedTypeRef(ASTNode source, char[]... varNames) { - int pS = source.sourceStart, pE = source.sourceEnd; - long p = (long)pS << 32 | pE; - - TypeReference ref; - - long[] poss = Eclipse.poss(source, varNames.length); - if (varNames.length > 1) ref = new QualifiedTypeReference(varNames, poss); - else ref = new SingleTypeReference(varNames[0], p); - setGeneratedBy(ref, source); - return ref; - } } diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index f04ea8b1..edf6f2ae 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -492,18 +492,34 @@ public class HandleBuilder extends JavacAnnotationHandler { JCExpression invoke = call; for (BuilderFieldData bfd : builderFields) { Name setterName = fluent ? bfd.name : type.toName(HandlerUtil.buildAccessorName("set", bfd.name.toString())); - JCExpression arg; + JCExpression[] tgt = new JCExpression[bfd.singularData == null ? 1 : 2]; if (bfd.obtainVia == null || !bfd.obtainVia.field().isEmpty()) { - arg = maker.Select(maker.Ident(type.toName("this")), bfd.obtainVia == null ? bfd.rawName : type.toName(bfd.obtainVia.field())); + for (int i = 0; i < tgt.length; i++) { + tgt[i] = maker.Select(maker.Ident(type.toName("this")), bfd.obtainVia == null ? bfd.rawName : type.toName(bfd.obtainVia.field())); + } } else { if (bfd.obtainVia.isStatic()) { - JCExpression c = maker.Select(maker.Ident(type.toName(type.getName())), type.toName(bfd.obtainVia.method())); - arg = maker.Apply(List.nil(), c, List.of(maker.Ident(type.toName("this")))); + for (int i = 0; i < tgt.length; i++) { + JCExpression c = maker.Select(maker.Ident(type.toName(type.getName())), type.toName(bfd.obtainVia.method())); + tgt[i] = maker.Apply(List.nil(), c, List.of(maker.Ident(type.toName("this")))); + } } else { - JCExpression c = maker.Select(maker.Ident(type.toName("this")), type.toName(bfd.obtainVia.method())); - arg = maker.Apply(List.nil(), c, List.nil()); + for (int i = 0; i < tgt.length; i++) { + JCExpression c = maker.Select(maker.Ident(type.toName("this")), type.toName(bfd.obtainVia.method())); + tgt[i] = maker.Apply(List.nil(), c, List.nil()); + } } } + + JCExpression arg; + if (bfd.singularData == null) { + arg = tgt[0]; + } else { + JCExpression eqNull = maker.Binary(CTC_EQUAL, tgt[0], maker.Literal(CTC_BOT, null)); + JCExpression emptyList = maker.Apply(List.nil(), chainDots(type, "java", "util", "Collections", "emptyList"), List.nil()); + arg = maker.Conditional(eqNull, emptyList, tgt[1]); + } + invoke = maker.Apply(List.nil(), maker.Select(invoke, setterName), List.of(arg)); } JCStatement statement = maker.Return(invoke); diff --git a/test/transform/resource/after-delombok/BuilderSingularToBuilderWithNull.java b/test/transform/resource/after-delombok/BuilderSingularToBuilderWithNull.java new file mode 100644 index 00000000..1f472438 --- /dev/null +++ b/test/transform/resource/after-delombok/BuilderSingularToBuilderWithNull.java @@ -0,0 +1,63 @@ +class BuilderSingularToBuilderWithNull { + private java.util.List elems; + public static void test() { + new BuilderSingularToBuilderWithNull(null).toBuilder(); + } + @java.lang.SuppressWarnings("all") + BuilderSingularToBuilderWithNull(final java.util.List elems) { + this.elems = elems; + } + @java.lang.SuppressWarnings("all") + public static class BuilderSingularToBuilderWithNullBuilder { + @java.lang.SuppressWarnings("all") + private java.util.ArrayList elems; + @java.lang.SuppressWarnings("all") + BuilderSingularToBuilderWithNullBuilder() { + } + @java.lang.SuppressWarnings("all") + public BuilderSingularToBuilderWithNullBuilder elem(final String elem) { + if (this.elems == null) this.elems = new java.util.ArrayList(); + this.elems.add(elem); + return this; + } + @java.lang.SuppressWarnings("all") + public BuilderSingularToBuilderWithNullBuilder elems(final java.util.Collection elems) { + if (this.elems == null) this.elems = new java.util.ArrayList(); + this.elems.addAll(elems); + return this; + } + @java.lang.SuppressWarnings("all") + public BuilderSingularToBuilderWithNullBuilder clearElems() { + if (this.elems != null) this.elems.clear(); + return this; + } + @java.lang.SuppressWarnings("all") + public BuilderSingularToBuilderWithNull build() { + java.util.List elems; + switch (this.elems == null ? 0 : this.elems.size()) { + case 0: + elems = java.util.Collections.emptyList(); + break; + case 1: + elems = java.util.Collections.singletonList(this.elems.get(0)); + break; + default: + elems = java.util.Collections.unmodifiableList(new java.util.ArrayList(this.elems)); + } + return new BuilderSingularToBuilderWithNull(elems); + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "BuilderSingularToBuilderWithNull.BuilderSingularToBuilderWithNullBuilder(elems=" + this.elems + ")"; + } + } + @java.lang.SuppressWarnings("all") + public static BuilderSingularToBuilderWithNullBuilder builder() { + return new BuilderSingularToBuilderWithNullBuilder(); + } + @java.lang.SuppressWarnings("all") + public BuilderSingularToBuilderWithNullBuilder toBuilder() { + return new BuilderSingularToBuilderWithNullBuilder().elems(this.elems == null ? java.util.Collections.emptyList() : this.elems); + } +} diff --git a/test/transform/resource/after-delombok/BuilderWithToBuilder.java b/test/transform/resource/after-delombok/BuilderWithToBuilder.java index 46387f0f..b644a16f 100644 --- a/test/transform/resource/after-delombok/BuilderWithToBuilder.java +++ b/test/transform/resource/after-delombok/BuilderWithToBuilder.java @@ -86,7 +86,7 @@ class BuilderWithToBuilder { } @java.lang.SuppressWarnings("all") public BuilderWithToBuilderBuilder toBuilder() { - return new BuilderWithToBuilderBuilder().one(this.mOne).two(this.mTwo).foo(BuilderWithToBuilder.rrr(this)).bars(this.bars); + return new BuilderWithToBuilderBuilder().one(this.mOne).two(this.mTwo).foo(BuilderWithToBuilder.rrr(this)).bars(this.bars == null ? java.util.Collections.emptyList() : this.bars); } } class ConstructorWithToBuilder { diff --git a/test/transform/resource/after-ecj/BuilderSingularToBuilderWithNull.java b/test/transform/resource/after-ecj/BuilderSingularToBuilderWithNull.java new file mode 100644 index 00000000..7265e17a --- /dev/null +++ b/test/transform/resource/after-ecj/BuilderSingularToBuilderWithNull.java @@ -0,0 +1,57 @@ +import lombok.Singular; +@lombok.Builder(toBuilder = true) class BuilderSingularToBuilderWithNull { + public static @java.lang.SuppressWarnings("all") class BuilderSingularToBuilderWithNullBuilder { + private @java.lang.SuppressWarnings("all") java.util.ArrayList elems; + @java.lang.SuppressWarnings("all") BuilderSingularToBuilderWithNullBuilder() { + super(); + } + public @java.lang.SuppressWarnings("all") BuilderSingularToBuilderWithNullBuilder elem(String elem) { + if ((this.elems == null)) + this.elems = new java.util.ArrayList(); + this.elems.add(elem); + return this; + } + public @java.lang.SuppressWarnings("all") BuilderSingularToBuilderWithNullBuilder elems(java.util.Collection elems) { + if ((this.elems == null)) + this.elems = new java.util.ArrayList(); + this.elems.addAll(elems); + return this; + } + public @java.lang.SuppressWarnings("all") BuilderSingularToBuilderWithNullBuilder clearElems() { + if ((this.elems != null)) + this.elems.clear(); + return this; + } + public @java.lang.SuppressWarnings("all") BuilderSingularToBuilderWithNull build() { + java.util.List elems; + switch (((this.elems == null) ? 0 : this.elems.size())) { + case 0 : + elems = java.util.Collections.emptyList(); + break; + case 1 : + elems = java.util.Collections.singletonList(this.elems.get(0)); + break; + default : + elems = java.util.Collections.unmodifiableList(new java.util.ArrayList(this.elems)); + } + return new BuilderSingularToBuilderWithNull(elems); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return (("BuilderSingularToBuilderWithNull.BuilderSingularToBuilderWithNullBuilder(elems=" + this.elems) + ")"); + } + } + private @Singular java.util.List elems; + public static void test() { + new BuilderSingularToBuilderWithNull(null).toBuilder(); + } + @java.lang.SuppressWarnings("all") BuilderSingularToBuilderWithNull(final java.util.List elems) { + super(); + this.elems = elems; + } + public static @java.lang.SuppressWarnings("all") BuilderSingularToBuilderWithNullBuilder builder() { + return new BuilderSingularToBuilderWithNullBuilder(); + } + public @java.lang.SuppressWarnings("all") BuilderSingularToBuilderWithNullBuilder toBuilder() { + return new BuilderSingularToBuilderWithNullBuilder().elems(((this.elems == null) ? java.util.Collections.emptyList() : this.elems)); + } +} diff --git a/test/transform/resource/after-ecj/BuilderWithToBuilder.java b/test/transform/resource/after-ecj/BuilderWithToBuilder.java index d304293c..b9cc27dd 100644 --- a/test/transform/resource/after-ecj/BuilderWithToBuilder.java +++ b/test/transform/resource/after-ecj/BuilderWithToBuilder.java @@ -74,7 +74,7 @@ import lombok.Builder; return new BuilderWithToBuilderBuilder(); } public @java.lang.SuppressWarnings("all") BuilderWithToBuilderBuilder toBuilder() { - return new BuilderWithToBuilderBuilder().one(this.mOne).two(this.mTwo).foo(BuilderWithToBuilder.rrr(this)).bars(this.bars); + return new BuilderWithToBuilderBuilder().one(this.mOne).two(this.mTwo).foo(BuilderWithToBuilder.rrr(this)).bars(((this.bars == null) ? java.util.Collections.emptyList() : this.bars)); } } @lombok.experimental.Accessors(prefix = "m") class ConstructorWithToBuilder { diff --git a/test/transform/resource/before/BuilderSingularToBuilderWithNull.java b/test/transform/resource/before/BuilderSingularToBuilderWithNull.java new file mode 100644 index 00000000..92a102cb --- /dev/null +++ b/test/transform/resource/before/BuilderSingularToBuilderWithNull.java @@ -0,0 +1,10 @@ +import lombok.Singular; + +@lombok.Builder(toBuilder = true) +class BuilderSingularToBuilderWithNull { + @Singular private java.util.List elems; + + public static void test() { + new BuilderSingularToBuilderWithNull(null).toBuilder(); + } +} -- cgit From f83488af9c3a1e1d1906601aec60a55579dd4d90 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Tue, 21 Aug 2018 00:13:03 +0200 Subject: [#1808] Probable fix: Using module names with dots in them was causing issues, as we only use the simple name. Actually getting the full module name is a little tricky, but this should do the job. --- doc/changelog.markdown | 3 ++- src/core/lombok/javac/apt/LombokProcessor.java | 15 +++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 238b4a38..21e385be 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -2,7 +2,8 @@ Lombok Changelog ---------------- ### v1.18.3 "Edgy Guinea Pig" -* FEATURE: THe `@FieldNameConstants` feature has been completely redesigned. [Issue #1774](https://github.com/rzwitserloot/lombok/issues/1774) [FieldNameConstants documentation](https://projectlombok.org/features/experimental/FieldNameConstants) +* FEATURE: The `@FieldNameConstants` feature has been completely redesigned. [Issue #1774](https://github.com/rzwitserloot/lombok/issues/1774) [FieldNameConstants documentation](https://projectlombok.org/features/experimental/FieldNameConstants) +* BUGFIX: When using lombok to compile modularized (`module-info.java`-style) code, if the module name has dots in it, it wouldn't work. [Issue #1808](https://github.com/rzwitserloot/lombok/issues/1808) ### v1.18.2 (July 26th, 2018) * BUGFIX: mapstruct + lombok in eclipse should hopefully work again. [Issue #1359](https://github.com/rzwitserloot/lombok/issues/1359) and [mapstruct issue #1159](https://github.com/mapstruct/mapstruct/issues/1159) diff --git a/src/core/lombok/javac/apt/LombokProcessor.java b/src/core/lombok/javac/apt/LombokProcessor.java index 89608546..26e16d32 100644 --- a/src/core/lombok/javac/apt/LombokProcessor.java +++ b/src/core/lombok/javac/apt/LombokProcessor.java @@ -43,6 +43,7 @@ import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; +import javax.lang.model.element.QualifiedNameable; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic.Kind; import javax.tools.JavaFileManager; @@ -380,10 +381,7 @@ public class LombokProcessor extends AbstractProcessor { private String getModuleNameFor(Element element) { while (element != null) { - if (element.getKind().name().equals("MODULE")) { - String n = element.getSimpleName().toString().trim(); - return n.isEmpty() ? null : n; - } + if (element.getKind().name().equals("MODULE")) return ModuleNameOracle.getModuleName(element); Element n = element.getEnclosingElement(); if (n == element) return null; element = n; @@ -391,6 +389,15 @@ public class LombokProcessor extends AbstractProcessor { return null; } + // QualifiedNameable is a java7 thing, so to remain compatible with java6, shove this into an inner class to avoid the ClassNotFoundError. + private static class ModuleNameOracle { + static String getModuleName(Element element) { + if (!(element instanceof QualifiedNameable)) return null; + String name = ((QualifiedNameable) element).getQualifiedName().toString().trim(); + return name.isEmpty() ? null : name; + } + } + private JCCompilationUnit toUnit(Element element) { TreePath path = trees == null ? null : trees.getPath(element); if (path == null) return null; -- cgit From 769185e123dfd4a073161eafb58ce50bb79d6201 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Tue, 21 Aug 2018 00:41:56 +0200 Subject: [#1806] Potential fix for java 11 in regards to module system. --- build.xml | 11 +++++++---- buildScripts/ivy.xml | 3 +++ doc/changelog.markdown | 1 + src/core9/module-info.java | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/build.xml b/build.xml index c9411d7e..c50bf644 100644 --- a/build.xml +++ b/build.xml @@ -112,7 +112,7 @@ the common tasks and can be called on to run the main aspects of all the sub-scr - + @@ -246,15 +246,18 @@ the common tasks and can be called on to run the main aspects of all the sub-scr - + + + + - + - + diff --git a/buildScripts/ivy.xml b/buildScripts/ivy.xml index c1ddc6fd..4eed2fa6 100644 --- a/buildScripts/ivy.xml +++ b/buildScripts/ivy.xml @@ -5,6 +5,7 @@ + @@ -64,5 +65,7 @@ + + diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 21e385be..6ba673ad 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -4,6 +4,7 @@ Lombok Changelog ### v1.18.3 "Edgy Guinea Pig" * FEATURE: The `@FieldNameConstants` feature has been completely redesigned. [Issue #1774](https://github.com/rzwitserloot/lombok/issues/1774) [FieldNameConstants documentation](https://projectlombok.org/features/experimental/FieldNameConstants) * BUGFIX: When using lombok to compile modularized (`module-info.java`-style) code, if the module name has dots in it, it wouldn't work. [Issue #1808](https://github.com/rzwitserloot/lombok/issues/1808) +* BUGFIX: Errors about lombok not reading a module providing `org.mapstruct.ap.spi` when trying to use lombok in jigsaw-mode on JDK 11. [Issue #1806](https://github.com/rzwitserloot/lombok/issues/1806) ### v1.18.2 (July 26th, 2018) * BUGFIX: mapstruct + lombok in eclipse should hopefully work again. [Issue #1359](https://github.com/rzwitserloot/lombok/issues/1359) and [mapstruct issue #1159](https://github.com/mapstruct/mapstruct/issues/1159) diff --git a/src/core9/module-info.java b/src/core9/module-info.java index f4d5815f..56e54270 100644 --- a/src/core9/module-info.java +++ b/src/core9/module-info.java @@ -23,6 +23,7 @@ module lombok { requires java.compiler; requires java.instrument; requires jdk.unsupported; + requires static org.mapstruct.processor; exports lombok; exports lombok.experimental; @@ -36,4 +37,3 @@ module lombok { provides javax.annotation.processing.Processor with lombok.launch.AnnotationProcessorHider.AnnotationProcessor; provides org.mapstruct.ap.spi.AstModifyingAnnotationProcessor with lombok.launch.AnnotationProcessorHider.AstModificationNotifier; } - -- cgit