From 0375f1a9e8f606588d4e136fc718a6876ff0ae4f Mon Sep 17 00:00:00 2001
From: Thomas Klambauer
Date: Tue, 17 Jul 2018 13:35:34 +0200
Subject: [PATCH 01/40] lombok config broken: version must be string
otherwise gradle compile will fail.
---
website/templates/setup/gradle.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/website/templates/setup/gradle.html b/website/templates/setup/gradle.html
index 7cb4af0d..41d90dcc 100644
--- a/website/templates/setup/gradle.html
+++ b/website/templates/setup/gradle.html
@@ -15,7 +15,7 @@
Note, to tell the gradle-lombok plugin to use the latest version of lombok, you need to explicitly tell it about the latest version number and the SHA-256. For our current latest version, put this in your build.gradle file:
lombok {
- version = ${version}
+ version = '${version}'
sha256 = ""
}
From a195a47337f592eb117f519f7a1a42f0d8f570d1 Mon Sep 17 00:00:00 2001
From: Reinier Zwitserloot
Date: Tue, 17 Jul 2018 22:32:24 +0200
Subject: [PATCH 02/40] Attempting to fix issues with integration with
mapstruct; issue #1359
---
build.xml | 3 ++-
doc/changelog.markdown | 1 +
src/launch/lombok/launch/ShadowClassLoader.java | 9 +++++++--
3 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/build.xml b/build.xml
index 28c7fd75..c1d13bd7 100644
--- a/build.xml
+++ b/build.xml
@@ -261,7 +261,8 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
-
+
+
diff --git a/doc/changelog.markdown b/doc/changelog.markdown
index 8166f3d1..a77dbb3d 100644
--- a/doc/changelog.markdown
+++ b/doc/changelog.markdown
@@ -2,6 +2,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)
* 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/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;
From ff739d6d5a6a68f8d87480be7b0c0104e08f77e0 Mon Sep 17 00:00:00 2001
From: Roland Praml
Date: Thu, 19 Jul 2018 21:46:39 +0200
Subject: [PATCH 03/40] Add Roland Praml to authors list
---
AUTHORS | 1 +
1 file changed, 1 insertion(+)
diff --git a/AUTHORS b/AUTHORS
index 0e542693..5246fde7 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -23,6 +23,7 @@ Rabea Gransberger
Reinier Zwitserloot
Robbert Jan Grootjans
Roel Spilker
+Roland Praml
Sander Koning
Szymon Pacanowski
Taiki Sugawara
From be1cfd2f59933725726ec5810e0c189a4aca6ad7 Mon Sep 17 00:00:00 2001
From: Roland Praml
Date: Sun, 8 Jul 2018 16:52:14 +0200
Subject: [PATCH 04/40] Replaced StringBuilder by simple char array in
"hotspot" method
---
src/core/lombok/bytecode/ClassFileMetaData.java | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
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);
}
/**
From 111d0a5f16667824d0a73b733624e6deffe19a0e Mon Sep 17 00:00:00 2001
From: Reinier Zwitserloot
Date: Wed, 25 Jul 2018 21:10:20 +0200
Subject: [PATCH 05/40] =?UTF-8?q?Fixes=20issue=20#1789=20-=20picking=20ano?=
=?UTF-8?q?ther=20workspace=20duplicates=20the=20=E2=80=98lombok=20is=20in?=
=?UTF-8?q?stalled=E2=80=99=20text=20in=20the=20eclipse=20about=20dialog.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../lombok/eclipse/agent/PatchFixesShadowLoaded.java | 1 +
1 file changed, 1 insertion(+)
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;
From 5ec61bb62d3dd2d9509ade090e750dd43e36c0f3 Mon Sep 17 00:00:00 2001
From: Reinier Zwitserloot
Date: Wed, 25 Jul 2018 21:41:17 +0200
Subject: [PATCH 06/40] =?UTF-8?q?[fixes=20issue=20#1759]=20We=20removed=20?=
=?UTF-8?q?the=20=E2=80=98flag=20usage=E2=80=99=20check=20on=20builder=20i?=
=?UTF-8?q?nstead=20of=20replacing=20it=20with=20the=20non-experimental=20?=
=?UTF-8?q?check=20about=203=20years=20ago=20when=20builder=20moved=20out?=
=?UTF-8?q?=20of=20experimental.=20The=20check=20has=20now=20been=20restor?=
=?UTF-8?q?ed.?=
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(+)
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.
From 7c3724c9dc03684b9e4ecb9b33296c894138add6 Mon Sep 17 00:00:00 2001
From: Reinier Zwitserloot
Date: Wed, 25 Jul 2018 22:04:52 +0200
Subject: [PATCH 07/40] =?UTF-8?q?[Fixes=20issue=20#1783]=20lombok.var=20/?=
=?UTF-8?q?=20lombok.experimental.var=20import=20would=20be=20removed=20by?=
=?UTF-8?q?=20eclipse=E2=80=99s=20organize=20imports.?=
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(-)
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);
}
From 7e94041dbc177476020969b00d3411020418f903 Mon Sep 17 00:00:00 2001
From: Reinier Zwitserloot
Date: Wed, 25 Jul 2018 23:19:00 +0200
Subject: [PATCH 08/40] =?UTF-8?q?Added=20key=20=E2=80=98dangerousconfig.lo?=
=?UTF-8?q?mbok.disable=E2=80=99.?=
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 ++++++++++-----
.../core/configuration/ConfigurationApp.java | 7 ++++---
.../core/configuration/ConfigurationKey.java | 12 +++++++++++-
.../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(-)
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 extends ConfigurationKey>>)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();
}
});
From dc715da8b79bff32116ac477d0ac04875bd21167 Mon Sep 17 00:00:00 2001
From: Reinier Zwitserloot
Date: Thu, 26 Jul 2018 00:00:24 +0200
Subject: [PATCH 09/40] pre-release version bump
---
doc/changelog.markdown | 3 ++-
src/core/lombok/core/Version.java | 6 +++---
2 files changed, 5 insertions(+), 4 deletions(-)
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
From 61fbd4a7f82180871e635a0ca80248e0cec02cf3 Mon Sep 17 00:00:00 2001
From: Reinier Zwitserloot
Date: Thu, 26 Jul 2018 00:17:09 +0200
Subject: [PATCH 10/40] post-release version bump
---
doc/changelog.markdown | 3 +++
src/core/lombok/core/Version.java | 6 +++---
2 files changed, 6 insertions(+), 3 deletions(-)
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
From 3d432c38d0cfeb36b8e7402eca56faaafcf7bac7 Mon Sep 17 00:00:00 2001
From: Reinier Zwitserloot
Date: Sun, 29 Jul 2018 16:37:21 +0200
Subject: [PATCH 11/40] code impl of FieldNameConstants rewrite + test updates
for it
---
src/core/lombok/ConfigurationKeys.java | 11 +-
.../handlers/HandleFieldNameConstants.java | 150 +++++++++++-------
.../experimental/FieldNameConstants.java | 28 +++-
.../handlers/HandleFieldNameConstants.java | 137 +++++++++-------
.../FieldNameConstantsBasic.java | 8 +-
.../FieldNameConstantsConfigKeys.java | 7 +-
.../FieldNameConstantsEnum.java | 10 ++
.../FieldNameConstantsWeird.java | 6 -
.../after-ecj/FieldNameConstantsBasic.java | 18 ++-
.../FieldNameConstantsConfigKeys.java | 13 +-
.../after-ecj/FieldNameConstantsEnum.java | 23 +++
.../after-ecj/FieldNameConstantsWeird.java | 13 --
.../before/FieldNameConstantsBasic.java | 4 +-
.../before/FieldNameConstantsConfigKeys.java | 3 +-
.../before/FieldNameConstantsEnum.java | 13 ++
.../before/FieldNameConstantsWeird.java | 12 --
.../FieldNameConstantsWeird.java.messages | 1 -
.../FieldNameConstantsWeird.java.messages | 1 -
18 files changed, 277 insertions(+), 181 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
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 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);
}
- generateFieldNameConstantsForType(node, annotationNode, level, prefix, suffix);
- break;
+ injectField(innerNode, fieldConstant);
}
}
-
- private void createFieldNameConstantsForFields(AccessLevel level, String prefix, String suffix, Collection 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");
- 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.");
- 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);
- }
}
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;
+ 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;
+ }
+
+
+ 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;
+ }
+
+ 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());
}
- generateFieldNameConstantsForType(node, annotationNode, level, prefix, suffix);
- break;
+ JCVariableDecl enumField = maker.VarDef(enumValueMods, ((JCVariableDecl) field.get()).name, returnType, init);
+ injectField(innerNode, enumField);
}
}
-
- 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");
- 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.");
- 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);
- }
-}
\ 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.
From eeab3c0021503bca69012cf71cbbfe2505be2293 Mon Sep 17 00:00:00 2001
From: Reinier Zwitserloot
Date: Sun, 29 Jul 2018 16:37:54 +0200
Subject: [PATCH 12/40] A few upgrades for the printers used with
@lombok.core.PrintAST.
---
.../lombok/eclipse/EclipseASTVisitor.java | 105 ++++++++++++++++--
src/core/lombok/javac/JavacASTVisitor.java | 14 ++-
2 files changed, 107 insertions(+), 12 deletions(-)
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++;
}
From b9fb35cb8e81d73b9b9b650022a1564b14761885 Mon Sep 17 00:00:00 2001
From: Reinier Zwitserloot
Date: Sun, 29 Jul 2018 16:38:16 +0200
Subject: [PATCH 13/40] Printing missing gradle integration would print for any
non-javac, non-gradle compiler. Fixed that.
---
src/core/lombok/core/AnnotationProcessor.java | 25 ++++++++++---------
.../javac/handlers/HandleFieldDefaults.java | 2 +-
2 files changed, 14 insertions(+), 13 deletions(-)
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.
From e964f5eec6015564d561ad45dc29964b4fc4481e Mon Sep 17 00:00:00 2001
From: Reinier Zwitserloot
Date: Sun, 29 Jul 2018 16:47:39 +0200
Subject: [PATCH 14/40] =?UTF-8?q?[website]=20=E2=80=99Install=E2=80=99=20-?=
=?UTF-8?q?>=20=E2=80=98How=20to=20use=E2=80=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
website/templates/_scaffold.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/website/templates/_scaffold.html b/website/templates/_scaffold.html
index 7acfb6b6..65b2fb7f 100644
--- a/website/templates/_scaffold.html
+++ b/website/templates/_scaffold.html
@@ -111,7 +111,7 @@ ga('send', 'pageview');
- Install
+ How to use
Install