aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xAUTHORS1
-rw-r--r--buildScripts/info.ant.xml5
-rw-r--r--buildScripts/ivy.xml2
-rw-r--r--buildScripts/tests.ant.xml1
-rw-r--r--buildScripts/website.ant.xml13
-rw-r--r--doc/changelog.markdown1
-rw-r--r--src/core/lombok/ConfigurationKeys.java2
-rw-r--r--src/core/lombok/core/PostCompiler.java10
-rw-r--r--src/core/lombok/core/handlers/HandlerUtil.java19
-rw-r--r--src/core/lombok/eclipse/EclipseAST.java2
-rw-r--r--src/core/lombok/eclipse/TransformEclipseAST.java36
-rw-r--r--src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java8
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java55
-rw-r--r--src/delombok/lombok/delombok/PrettyPrinter.java26
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchVal.java25
-rw-r--r--src/stubs/com/sun/tools/javac/code/Symbol.java8
-rw-r--r--src/stubs/com/sun/tools/javac/code/Symtab.java2
-rw-r--r--src/support/lombok/website/RunSite.java103
-rw-r--r--test/configuration/src/lombok/core/configuration/TestConfiguration.java4
-rw-r--r--test/core/src/lombok/AbstractRunTests.java2
-rw-r--r--test/core/src/lombok/RunTestsViaEcj.java81
-rw-r--r--test/transform/resource/after-delombok/DelegateWithVarargs2.java12
-rw-r--r--test/transform/resource/after-delombok/GetterSetterJavadoc.java2
-rw-r--r--test/transform/resource/after-ecj/DelegateWithVarargs2.java17
-rw-r--r--test/transform/resource/before/DelegateWithVarargs2.java9
-rw-r--r--website/resources/img/eclipse-p2-step1.pngbin0 -> 645640 bytes
-rw-r--r--website/resources/img/eclipse-p2-step2.pngbin0 -> 56195 bytes
-rw-r--r--website/templates/features/Builder.html2
-rw-r--r--website/templates/setup/eclipse.html12
-rw-r--r--website/templates/setup/kobalt.html2
30 files changed, 402 insertions, 60 deletions
diff --git a/AUTHORS b/AUTHORS
index 8a2902ad..9adf2005 100755
--- a/AUTHORS
+++ b/AUTHORS
@@ -35,6 +35,7 @@ Robbert Jan Grootjans <grootjans@gmail.com>
Robert Wertman <robert.wertman@gmail.com>
Roel Spilker <r.spilker@gmail.com>
Roland Praml <pram@gmx.de>
+Rostislav Krasny <45571812+rosti-il@users.noreply.github.com>
Samuel Pereira <samuel.p.araujo@gmail.com>
Sander Koning <askoning@gmail.com>
Szymon Pacanowski <spacanowski@gmail.com>
diff --git a/buildScripts/info.ant.xml b/buildScripts/info.ant.xml
index 55fea8af..fe6e0ee3 100644
--- a/buildScripts/info.ant.xml
+++ b/buildScripts/info.ant.xml
@@ -258,6 +258,11 @@ build/website.
'pack' bzips this up, ready to ship to the server.
'publish' sends this to the server and runs a script to deploy.
+ &gt; ant website.open
+
+ First builds the website, then hosts it locally and opens it in your browser so
+ you can see the website in its full, template-applied form.
+
&gt; ant latest-changes.build
Makes a changelog variant that lists only the newest changes; it is included
diff --git a/buildScripts/ivy.xml b/buildScripts/ivy.xml
index 14530f06..3dfbde7e 100644
--- a/buildScripts/ivy.xml
+++ b/buildScripts/ivy.xml
@@ -58,6 +58,7 @@
<dependency org="projectlombok.org" name="markdownj" rev="1.02b4" conf="buildtools->build" />
<dependency org="de.java2html" name="java2html" rev="5.0" conf="buildtools->default" />
<dependency org="org.freemarker" name="freemarker" rev="2.3.28" conf="buildtools->default" />
+ <dependency org="com.sparkjava" name="spark-core" rev="2.9.2" conf="buildtools->default" />
<dependency org="org.eclipse.jgit" name="org.eclipse.jgit.ant" rev="5.2.0.201812061821-r" conf="supporters->default" />
<dependency org="org.eclipse.jgit" name="org.eclipse.jgit" rev="5.2.0.201812061821-r" conf="supporters->default" />
@@ -93,6 +94,7 @@
<dependency org="org.eclipse.jdt" name="org.eclipse.jdt.core" rev="3.22.0" conf="eclipse-202006->default" transitive="false" />
<dependency org="org.eclipse.jdt" name="org.eclipse.jdt.ui" rev="3.21.100" conf="eclipse-202006->default" transitive="false" />
<dependency org="org.eclipse.platform" name="org.eclipse.equinox.common" rev="3.12.0" conf="eclipse-202006->default" transitive="false" />
+ <dependency org="org.eclipse.platform" name="org.eclipse.equinox.preferences" rev="3.8.0" conf="eclipse-202006->default" transitive="false" />
<dependency org="org.eclipse.platform" name="org.eclipse.core.resources" rev="3.13.700" conf="eclipse-202006->default" transitive="false" />
<dependency org="org.eclipse.platform" name="org.eclipse.core.jobs" rev="3.10.800" conf="eclipse-202006->default" transitive="false" />
<dependency org="org.eclipse.platform" name="org.eclipse.osgi" rev="3.15.300" conf="eclipse-202006->default" transitive="false" />
diff --git a/buildScripts/tests.ant.xml b/buildScripts/tests.ant.xml
index f78bfae9..cb840048 100644
--- a/buildScripts/tests.ant.xml
+++ b/buildScripts/tests.ant.xml
@@ -119,6 +119,7 @@ This buildfile is part of projectlombok.org. It takes care of compiling and runn
<classpath refid="cp.stripe" />
<classpath location="build/lombok" />
<classpath location="build/tests" />
+ <classpath location="build/teststubs" />
<test name="lombok.TestJavac" />
</junit>
</sequential>
diff --git a/buildScripts/website.ant.xml b/buildScripts/website.ant.xml
index 9efb2668..730b79c2 100644
--- a/buildScripts/website.ant.xml
+++ b/buildScripts/website.ant.xml
@@ -150,6 +150,19 @@ such as applying the templates to produce the website, converting the changelog
<website.make version="${lombok.version.live}" fullversion="${lombok.fullversion.live}" cmd="all" />
</target>
+ <target name="website.open" depends="website.build, compile.support" description="Builds the website, then serves it locally, opening a browser.">
+ <local name="dir.build.website" />
+ <property name="dir.build.website" location="build/website" />
+ <java classname="lombok.website.RunSite" failonerror="true">
+ <classpath>
+ <path refid="cp.buildtools" />
+ <pathelement location="build/support" />
+ </classpath>
+ <arg value="${dir.build.website}" />
+ <arg value="open" />
+ </java>
+ </target>
+
<target name="website.print-all-versions" depends="compile.support">
<java classname="lombok.website.WebsiteMaker" failonerror="true">
<classpath>
diff --git a/doc/changelog.markdown b/doc/changelog.markdown
index b7fbdd7d..91fdd6a5 100644
--- a/doc/changelog.markdown
+++ b/doc/changelog.markdown
@@ -2,7 +2,6 @@ Lombok Changelog
----------------
### v1.18.13 "Edgy Guinea Pig"
-* POTENTIAL FIX: Kotlin incremental compiler on gradle 3.6.1 [Issue #2412](https://github.com/rzwitserloot/lombok/issues/2412)
* PERFORMANCE: Several performance improvements during parsing/compilation, both using javac and Eclipse. Thanks __@Rawi01__!
* PERFORMANCE: The generated equals method will first compare primitives, then primitive wrappers and then reference fields. Manual re-ordering is possible using `@Include(rank=n)`. [Pull Request #2485](https://github.com/rzwitserloot/lombok/pull/2485), [Issue #1543](https://github.com/rzwitserloot/lombok/issues/1543)
* IMPROBABLE BREAKING CHANGE: The generated hashcode has changed for classes that include both primitive fields and reference fields.
diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java
index 60b98a94..01a4b576 100644
--- a/src/core/lombok/ConfigurationKeys.java
+++ b/src/core/lombok/ConfigurationKeys.java
@@ -140,7 +140,7 @@ public class ConfigurationKeys {
* NB: GWT projects, and probably android projects, should explicitly set this key to {@code true} for the entire project.
*
* <br>
- * <em>BREAKING CHANGE</em>: Starting with lombok v1.16.20, defaults to {@code false} instead of {@code true}, as {@code @ConstructorProperties} requires extra modules in JDK9.
+ * <em>BREAKING CHANGE</em>: Starting with lombok v1.16.20, defaults to {@code true} instead of {@code false}, as {@code @ConstructorProperties} requires extra modules in JDK9.
*
* @see ConfigurationKeys#ANY_CONSTRUCTOR_ADD_CONSTRUCTOR_PROPERTIES
* @deprecated Since version 2.0, use {@link #ANY_CONSTRUCTOR_ADD_CONSTRUCTOR_PROPERTIES} instead.
diff --git a/src/core/lombok/core/PostCompiler.java b/src/core/lombok/core/PostCompiler.java
index e17f806e..72f4b3a2 100644
--- a/src/core/lombok/core/PostCompiler.java
+++ b/src/core/lombok/core/PostCompiler.java
@@ -72,10 +72,12 @@ public final class PostCompiler {
// no need to call super
byte[] original = toByteArray();
byte[] copy = null;
- try {
- copy = applyTransformations(original, fileName, diagnostics);
- } catch (Exception e) {
- diagnostics.addWarning(String.format("Error during the transformation of '%s'; no post-compilation has been applied", fileName));
+ if (original.length > 0) {
+ try {
+ copy = applyTransformations(original, fileName, diagnostics);
+ } catch (Exception e) {
+ diagnostics.addWarning(String.format("Error during the transformation of '%s'; no post-compilation has been applied", fileName));
+ }
}
if (copy == null) {
diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java
index c4b60475..92a9a142 100644
--- a/src/core/lombok/core/handlers/HandlerUtil.java
+++ b/src/core/lombok/core/handlers/HandlerUtil.java
@@ -759,6 +759,7 @@ public class HandlerUtil {
}
private static final Pattern SECTION_FINDER = Pattern.compile("^\\s*\\**\\s*[-*][-*]+\\s*([GS]ETTER|WITH(?:ER)?)\\s*[-*][-*]+\\s*\\**\\s*$", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
+ private static final Pattern LINE_BREAK_FINDER = Pattern.compile("(\\r?\\n)?");
public static String stripLinesWithTagFromJavadoc(String javadoc, String regexpFragment) {
Pattern p = Pattern.compile("^\\s*\\**\\s*" + regexpFragment + "\\s*\\**\\s*$", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
@@ -767,27 +768,29 @@ public class HandlerUtil {
}
public static String stripSectionsFromJavadoc(String javadoc) {
- Matcher m = SECTION_FINDER.matcher(javadoc);
- if (!m.find()) return javadoc;
+ Matcher sectionMatcher = SECTION_FINDER.matcher(javadoc);
+ if (!sectionMatcher.find()) return javadoc;
- return javadoc.substring(0, m.start());
+ return javadoc.substring(0, sectionMatcher.start());
}
public static String getJavadocSection(String javadoc, String sectionNameSpec) {
String[] sectionNames = sectionNameSpec.split("\\|");
- Matcher m = SECTION_FINDER.matcher(javadoc);
+ Matcher sectionMatcher = SECTION_FINDER.matcher(javadoc);
+ Matcher lineBreakMatcher = LINE_BREAK_FINDER.matcher(javadoc);
int sectionStart = -1;
int sectionEnd = -1;
- while (m.find()) {
+ while (sectionMatcher.find()) {
boolean found = false;
- for (String sectionName : sectionNames) if (m.group(1).equalsIgnoreCase(sectionName)) {
+ for (String sectionName : sectionNames) if (sectionMatcher.group(1).equalsIgnoreCase(sectionName)) {
found = true;
break;
}
if (found) {
- sectionStart = m.end() + 1;
+ lineBreakMatcher.find(sectionMatcher.end());
+ sectionStart = lineBreakMatcher.end();
} else if (sectionStart != -1) {
- sectionEnd = m.start();
+ sectionEnd = sectionMatcher.start();
}
}
diff --git a/src/core/lombok/eclipse/EclipseAST.java b/src/core/lombok/eclipse/EclipseAST.java
index b45ac72d..d53856af 100644
--- a/src/core/lombok/eclipse/EclipseAST.java
+++ b/src/core/lombok/eclipse/EclipseAST.java
@@ -350,7 +350,7 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> {
if (!changed) clearChanged();
}
- private static boolean isComplete(CompilationUnitDeclaration unit) {
+ public static boolean isComplete(CompilationUnitDeclaration unit) {
return (unit.bits & ASTNode.HasAllMethodBodies) != 0;
}
diff --git a/src/core/lombok/eclipse/TransformEclipseAST.java b/src/core/lombok/eclipse/TransformEclipseAST.java
index 6fcde937..59a0709e 100644
--- a/src/core/lombok/eclipse/TransformEclipseAST.java
+++ b/src/core/lombok/eclipse/TransformEclipseAST.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2019 The Project Lombok Authors.
+ * Copyright (C) 2009-2020 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
@@ -24,6 +24,9 @@ package lombok.eclipse;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.Map;
+import java.util.WeakHashMap;
import lombok.ConfigurationKeys;
import lombok.core.LombokConfiguration;
@@ -63,6 +66,7 @@ public class TransformEclipseAST {
public static boolean disableLombok = false;
private static final HistogramTracker lombokTracker;
+ private static Map<CompilationUnitDeclaration, State> transformationStates = Collections.synchronizedMap(new WeakHashMap<CompilationUnitDeclaration, State>());
static {
String v = System.getProperty("lombok.histogram");
@@ -130,6 +134,30 @@ public class TransformEclipseAST {
}
/**
+ * Check if lombok already handled the given AST. This method will return
+ * <code>true</code> once for diet mode and once for full mode.
+ *
+ * The reason for this is that Eclipse invokes the transform method multiple
+ * times during compilation and it is enough to transform it once and not
+ * repeat the whole thing over and over again.
+ *
+ * @param ast The AST node belonging to the compilation unit (java speak for a single source file).
+ * @return <code>true</code> if this AST was already handled by lombok.
+ */
+ public static boolean alreadyTransformed(CompilationUnitDeclaration ast) {
+ State state = transformationStates.get(ast);
+
+ if (state == State.FULL) return true;
+ if (state == State.DIET) {
+ if (!EclipseAST.isComplete(ast)) return true;
+ transformationStates.put(ast, State.FULL);
+ } else {
+ transformationStates.put(ast, State.DIET);
+ }
+ return false;
+ }
+
+ /**
* This method is called immediately after Eclipse finishes building a CompilationUnitDeclaration, which is
* the top-level AST node when Eclipse parses a source file. The signature is 'magic' - you should not
* change it!
@@ -144,6 +172,7 @@ public class TransformEclipseAST {
if (disableLombok) return;
if (Symbols.hasSymbol("lombok.disable")) return;
+ if (alreadyTransformed(ast)) return;
// Do NOT abort if (ast.bits & ASTNode.HasAllMethodBodies) != 0 - that doesn't work.
@@ -243,4 +272,9 @@ public class TransformEclipseAST {
nextPriority = Math.min(nextPriority, handlers.handleAnnotation(top, annotationNode, annotation, priority));
}
}
+
+ private static enum State {
+ DIET,
+ FULL
+ }
}
diff --git a/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java b/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java
index 9343011f..cee3912c 100644
--- a/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java
+++ b/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java
@@ -171,10 +171,10 @@ public class HandleFieldNameConstants extends EclipseAnnotationHandler<FieldName
injectMethod(fieldsType, constructor);
}
+ Clinit cli = null;
if (genClinit) {
- Clinit cli = new Clinit(parent.compilationResult);
+ cli = new Clinit(parent.compilationResult);
injectMethod(fieldsType, cli);
- cli.traverse(generatedByVisitor, ((TypeDeclaration) fieldsType.get()).scope);
}
for (EclipseNode fieldNode : fields) {
@@ -202,5 +202,9 @@ public class HandleFieldNameConstants extends EclipseAnnotationHandler<FieldName
injectField(fieldsType, constantField);
constantField.traverse(generatedByVisitor, ((TypeDeclaration) fieldsType.get()).initializerScope);
}
+
+ if (genClinit) {
+ cli.traverse(generatedByVisitor, ((TypeDeclaration) fieldsType.get()).scope);
+ }
}
}
diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
index 8a1ed5e7..2379d0a0 100644
--- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
+++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
@@ -39,6 +39,7 @@ import java.util.regex.Pattern;
import javax.lang.model.element.Element;
+import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.BoundKind;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Scope;
@@ -1126,7 +1127,25 @@ public class JavacHandlerUtil {
}
}
}
-
+
+ static class JCAnnotationReflect {
+ private static Field ATTRIBUTE;
+
+ static {
+ try {
+ ATTRIBUTE = Permit.getField(JCAnnotation.class, "attribute");
+ } catch (Exception ignore) {}
+ }
+
+ static Attribute.Compound getAttribute(JCAnnotation jcAnnotation) {
+ try {
+ return (Attribute.Compound) ATTRIBUTE.get(jcAnnotation);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ }
+
// jdk9 support, types have changed, names stay the same
static class ClassSymbolMembersField {
private static final Field membersField;
@@ -1177,8 +1196,10 @@ public class JavacHandlerUtil {
* Also takes care of updating the JavacAST.
*/
public static void injectMethod(JavacNode typeNode, JCMethodDecl method, List<Type> paramTypes, Type returnType) {
+ Context context = typeNode.getContext();
+ Symtab symtab = Symtab.instance(context);
JCClassDecl type = (JCClassDecl) typeNode.get();
-
+
if (method.getName().contentEquals("<init>")) {
//Scan for default constructor, and remove it.
int idx = 0;
@@ -1195,7 +1216,7 @@ public class JavacHandlerUtil {
idx++;
}
}
-
+
addSuppressWarningsAll(method.mods, typeNode, method.pos, getGeneratedBy(method), typeNode.getContext());
addGenerated(method.mods, typeNode, method.pos, getGeneratedBy(method), typeNode.getContext());
type.defs = type.defs.append(method);
@@ -1203,18 +1224,38 @@ public class JavacHandlerUtil {
List<Symbol.VarSymbol> params = null;
if (method.getParameters() != null && !method.getParameters().isEmpty()) {
ListBuffer<Symbol.VarSymbol> newParams = new ListBuffer<Symbol.VarSymbol>();
- for (JCTree.JCVariableDecl param : method.getParameters()) {
- if (param.sym != null) newParams.append(param.sym);
+ for (int i = 0; i < method.getParameters().size(); i++) {
+ JCTree.JCVariableDecl param = method.getParameters().get(i);
+ if (param.sym == null) {
+ Type paramType = paramTypes == null ? param.getType().type : paramTypes.get(i);
+ VarSymbol varSymbol = new VarSymbol(param.mods.flags, param.name, paramType, symtab.noSymbol);
+ List<JCAnnotation> annotations = param.getModifiers().getAnnotations();
+ if (annotations != null && !annotations.isEmpty()) {
+ ListBuffer<Attribute.Compound> newAnnotations = new ListBuffer<Attribute.Compound>();
+ for (JCAnnotation jcAnnotation : annotations) {
+ Attribute.Compound attribute = JCAnnotationReflect.getAttribute(jcAnnotation);
+ if (attribute != null) {
+ newAnnotations.append(attribute);
+ }
+ }
+ if (annotations.length() == newAnnotations.length()) {
+ varSymbol.appendAttributes(newAnnotations.toList());
+ }
+ }
+ newParams.append(varSymbol);
+ } else {
+ newParams.append(param.sym);
+ }
}
params = newParams.toList();
if (params.length() != method.getParameters().length()) params = null;
}
fixMethodMirror(typeNode.getContext(), typeNode.getElement(), method.getModifiers().flags, method.getName(), paramTypes, params, returnType);
-
+
typeNode.add(method, Kind.METHOD);
}
-
+
private static void fixMethodMirror(Context context, Element typeMirror, long access, Name methodName, List<Type> paramTypes, List<Symbol.VarSymbol> params, Type returnType) {
if (typeMirror == null || paramTypes == null || returnType == null) return;
ClassSymbol cs = (ClassSymbol) typeMirror;
diff --git a/src/delombok/lombok/delombok/PrettyPrinter.java b/src/delombok/lombok/delombok/PrettyPrinter.java
index 208b215f..54fa4ebf 100644
--- a/src/delombok/lombok/delombok/PrettyPrinter.java
+++ b/src/delombok/lombok/delombok/PrettyPrinter.java
@@ -188,12 +188,6 @@ public class PrettyPrinter extends JCTree.Visitor {
return getEndPosition(tree, compilationUnit);
}
- private static int lineEndPos(String s, int start) {
- int pos = s.indexOf('\n', start);
- if (pos < 0) pos = s.length();
- return pos;
- }
-
private boolean needsAlign, needsNewLine, onNewLine = true, needsSpace, aligned;
public static final class UncheckedIOException extends RuntimeException {
@@ -434,23 +428,25 @@ public class PrettyPrinter extends JCTree.Visitor {
private void printDocComment(JCTree tree) {
String dc = getJavadocFor(tree);
if (dc == null) return;
+
aPrintln("/**");
- int pos = 0;
- int endpos = lineEndPos(dc, pos);
boolean atStart = true;
- while (pos < dc.length()) {
- String line = dc.substring(pos, endpos);
- if (line.trim().isEmpty() && atStart) {
+
+ for (String line : dc.split("\\r?\\n")) {
+ if (atStart && line.trim().isEmpty()) {
atStart = false;
continue;
}
+
atStart = false;
aPrint(" *");
- if (pos < dc.length() && dc.charAt(pos) > ' ') print(" ");
- println(dc.substring(pos, endpos));
- pos = endpos + 1;
- endpos = lineEndPos(dc, pos);
+ if (!line.isEmpty() && !Character.isWhitespace(line.charAt(0))) {
+ print(" ");
+ }
+
+ println(line);
}
+
aPrintln(" */");
}
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java
index 056852c8..f22e78a8 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java
@@ -35,11 +35,13 @@ import org.eclipse.jdt.internal.compiler.ast.FunctionalExpression;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
@@ -227,14 +229,16 @@ public class PatchVal {
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");
- if (valInForStatement) return false;
- break;
+ if (val) {
+ 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 =
+ 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;
+ }
}
}
@@ -264,6 +268,7 @@ public class PatchVal {
}
TypeBinding resolved = null;
+ Constant oldConstant = init.constant;
try {
resolved = decomponent ? getForEachComponentType(init, scope) : resolveForExpression(init, scope);
} catch (NullPointerException e) {
@@ -280,6 +285,10 @@ public class PatchVal {
} catch (Exception e) {
// Some type thing failed.
}
+ } else {
+ if (init instanceof MessageSend && ((MessageSend) init).actualReceiverType == null) {
+ init.constant = oldConstant;
+ }
}
}
diff --git a/src/stubs/com/sun/tools/javac/code/Symbol.java b/src/stubs/com/sun/tools/javac/code/Symbol.java
index 7324cb8e..15b04148 100644
--- a/src/stubs/com/sun/tools/javac/code/Symbol.java
+++ b/src/stubs/com/sun/tools/javac/code/Symbol.java
@@ -24,7 +24,7 @@ import com.sun.tools.javac.util.Name;
public abstract class Symbol implements Element {
public Type type;
public Name name;
-
+
public long flags() { return 0; }
public boolean isStatic() { return false; }
public boolean isConstructor() { return false; }
@@ -38,7 +38,9 @@ public abstract class Symbol implements Element {
@Override public Name getSimpleName() { return null; }
@Override public java.util.List<Symbol> getEnclosedElements() { return null; }
@Override public Element getEnclosingElement() { return null; }
-
+ public void appendAttributes(List<Attribute.Compound> l) {
+ }
+
public static abstract class TypeSymbol extends Symbol {}
public static class MethodSymbol extends Symbol implements ExecutableElement {
@@ -60,6 +62,8 @@ public abstract class Symbol implements Element {
public static class VarSymbol extends Symbol implements VariableElement {
public Type type;
+ public VarSymbol(long flags, Name name, Type type, Symbol owner) {
+ }
@Override public ElementKind getKind() { return null; }
@Override public Set<Modifier> getModifiers() { return null; }
@Override public <R, P> R accept(ElementVisitor<R, P> v, P p) { return null; }
diff --git a/src/stubs/com/sun/tools/javac/code/Symtab.java b/src/stubs/com/sun/tools/javac/code/Symtab.java
index 2b524e4c..8d823531 100644
--- a/src/stubs/com/sun/tools/javac/code/Symtab.java
+++ b/src/stubs/com/sun/tools/javac/code/Symtab.java
@@ -5,6 +5,7 @@ package com.sun.tools.javac.code;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.TypeSymbol;
import com.sun.tools.javac.util.Context;
public class Symtab {
@@ -14,6 +15,7 @@ public class Symtab {
public Type objectType;
public static Symtab instance(Context context) {return null;}
public Type unknownType;
+ public TypeSymbol noSymbol;
// JDK 9
public ModuleSymbol unnamedModule;
diff --git a/src/support/lombok/website/RunSite.java b/src/support/lombok/website/RunSite.java
new file mode 100644
index 00000000..17e158c0
--- /dev/null
+++ b/src/support/lombok/website/RunSite.java
@@ -0,0 +1,103 @@
+package lombok.website;
+
+import static spark.Spark.*;
+
+import java.awt.Desktop;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import spark.Request;
+import spark.Response;
+import spark.Route;
+
+public class RunSite {
+ private static final int DEFAULT_PORT = 4569;
+ private final Path base;
+
+ public RunSite(Path base) {
+ this.base = base;
+ }
+
+ public static void main(String[] args) throws Exception {
+ boolean open = args.length > 1 && args[1].equals("open");
+ new RunSite(Paths.get(args[0])).go(open);
+ }
+
+ private void go(boolean open) throws Exception {
+ port(DEFAULT_PORT);
+ get("/", serve("main.html"));
+ get("/setup/overview", serve("setup/main.html"));
+ get("/setup", serve("setup/main.html"));
+ get("/features", serve("features/index.html"));
+ get("/features/all", serve("features/index.html"));
+ get("/features/experimental/all", serve("features/experimental/index.html"));
+ get("/features/experimental", serve("features/experimental/index.html"));
+
+ serveDir("/", base);
+
+ System.out.println("Serving page from " + base + " -- hit enter to stop");
+ if (open) Opener.open("http://localhost:" + DEFAULT_PORT + "/");
+ System.in.read();
+ System.exit(0);
+ }
+
+ private void serveDir(String sub, Path dir) throws IOException {
+ DirectoryStream<Path> ds = Files.newDirectoryStream(dir);
+ try {
+ for (Path c : ds) {
+ String n = c.getFileName().toString();
+ if (n.equals(".") || n.equals("..")) continue;
+ if (Files.isDirectory(c)) {
+ serveDir(sub + n + "/", c);
+ continue;
+ }
+ String rel = base.relativize(c).toString();
+ get(sub + n, serve(rel));
+ if (n.endsWith(".html")) get(sub + n.substring(0, n.length() - 5), serve(rel));
+ }
+ } finally {
+ ds.close();
+ }
+ }
+
+ private static class Opener {
+ public static void open(String url) throws Exception {
+ Desktop.getDesktop().browse(new URI(url));
+ }
+ }
+
+ private Route serve(final String path) {
+ final Path tgt = base.resolve(path);
+
+ return new Route() {
+ @Override public Object handle(Request req, Response res) throws Exception {
+ res.type(mapMime(path));
+ return Files.readAllBytes(tgt);
+ }
+ };
+ }
+
+ private String mapMime(String path) {
+ if (path.endsWith(".css")) return "text/css; charset=UTF-8";
+ if (path.endsWith(".js")) return "text/javascript; charset=UTF-8";
+ if (path.endsWith(".png")) return "image/png";
+ if (path.endsWith(".gif")) return "image/gif";
+ if (path.endsWith(".jpg")) return "image/jpeg";
+ if (path.endsWith(".mp4")) return "video/mp4";
+ if (path.endsWith(".m4v")) return "video/mp4";
+ if (path.endsWith(".ogv")) return "video/ogg";
+ if (path.endsWith(".webm")) return "video/webm";
+ if (path.endsWith(".ico")) return "image/x-icon";
+ if (path.endsWith(".pdf")) return "application/pdf";
+ if (path.endsWith(".json")) return "application/json";
+ if (path.endsWith(".xml")) return "text/xml";
+ if (path.endsWith(".woff")) return "font/woff";
+ if (path.endsWith(".woff2")) return "font/woff2";
+ if (path.endsWith(".html")) return "text/html; charset=UTF-8";
+ return "text/plain; charset=UTF-8";
+ }
+}
diff --git a/test/configuration/src/lombok/core/configuration/TestConfiguration.java b/test/configuration/src/lombok/core/configuration/TestConfiguration.java
index 3032daf3..504c36b2 100644
--- a/test/configuration/src/lombok/core/configuration/TestConfiguration.java
+++ b/test/configuration/src/lombok/core/configuration/TestConfiguration.java
@@ -65,8 +65,8 @@ public class TestConfiguration {
outStream.flush();
errStream.flush();
- String out = new String(rawOut.toByteArray()).replace("\r\n", "\n").replace('\\', '/').replaceAll(Pattern.quote(normalizedName) + "|" + Pattern.quote(baseName), "BASE/").trim();
- String err = new String(rawErr.toByteArray()).replace("\r\n", "\n").replace('\\', '/').replaceAll(Pattern.quote(normalizedName) + "|" + Pattern.quote(baseName), "BASE/").trim();
+ String out = new String(rawOut.toByteArray()).replace('\\', '/').replaceAll(Pattern.quote(normalizedName) + "|" + Pattern.quote(baseName), "BASE/").trim();
+ String err = new String(rawErr.toByteArray()).replace('\\', '/').replaceAll(Pattern.quote(normalizedName) + "|" + Pattern.quote(baseName), "BASE/").trim();
checkContent(directory, out, "out");
checkContent(directory, err, "err");
diff --git a/test/core/src/lombok/AbstractRunTests.java b/test/core/src/lombok/AbstractRunTests.java
index 8e73e122..448f77ab 100644
--- a/test/core/src/lombok/AbstractRunTests.java
+++ b/test/core/src/lombok/AbstractRunTests.java
@@ -285,7 +285,7 @@ public abstract class AbstractRunTests {
endIdx--;
}
- return in.substring(0, endIdx);
+ return in.substring(0, endIdx + 1);
}
private static String[] removeBlanks(String[] in) {
diff --git a/test/core/src/lombok/RunTestsViaEcj.java b/test/core/src/lombok/RunTestsViaEcj.java
index 3a6e1702..5c29533c 100644
--- a/test/core/src/lombok/RunTestsViaEcj.java
+++ b/test/core/src/lombok/RunTestsViaEcj.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 The Project Lombok Authors.
+ * Copyright (C) 2010-2020 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
@@ -23,20 +23,29 @@ package lombok;
import java.io.File;
import java.io.StringWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
import lombok.eclipse.Eclipse;
import lombok.javac.CapturingDiagnosticListener.CompilerMessage;
+import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
@@ -46,7 +55,6 @@ import org.eclipse.jdt.internal.compiler.batch.FileSystem;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
-import org.eclipse.jdt.internal.core.CompilationUnit;
public class RunTestsViaEcj extends AbstractRunTests {
protected CompilerOptions ecjCompilerOptions() {
@@ -104,7 +112,8 @@ public class RunTestsViaEcj extends AbstractRunTests {
};
String source = readFile(file);
- final CompilationUnit sourceUnit = new TestCompilationUnit(file.getName(), source);
+ char[] sourceArray = source.toCharArray();
+ final ICompilationUnit sourceUnit = new TestCompilationUnit(file.getName(), source);
Compiler ecjCompiler = new Compiler(createFileSystem(file, minVersion), ecjErrorHandlingPolicy(), ecjCompilerOptions(), bitbucketRequestor, new DefaultProblemFactory(Locale.ENGLISH)) {
@Override protected synchronized void addCompilationUnit(ICompilationUnit inUnit, CompilationUnitDeclaration parsedUnit) {
@@ -127,11 +136,75 @@ public class RunTestsViaEcj extends AbstractRunTests {
if (cud == null) result.append("---- No CompilationUnit provided by ecj ----");
else result.append(cud.toString());
+ if (eclipseAvailable()) {
+ EclipseDomConversion.toDomAst(cud, sourceArray);
+ }
+
+ return true;
+ }
+
+ private boolean eclipseAvailable() {
+ try {
+ Class.forName("org.eclipse.jdt.core.dom.CompilationUnit");
+ } catch (Throwable t) {
+ return false;
+ }
+
return true;
}
private static final String bootRuntimePath = System.getProperty("delombok.bootclasspath");
+ private static class EclipseDomConversion {
+ static CompilationUnit toDomAst(CompilationUnitDeclaration cud, final char[] source) {
+ Map<String, String> options = new HashMap<String, String>();
+ options.put(JavaCore.COMPILER_SOURCE, "11");
+ options.put("org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures", "enabled");
+ try {
+ org.eclipse.jdt.internal.core.CompilationUnit ccu = new org.eclipse.jdt.internal.core.CompilationUnit(null, null, null) {
+ @Override public char[] getContents() {
+ return source;
+ }
+ };
+ return AST.convertCompilationUnit(4, cud, options, false, ccu, 0, null);
+ } catch (SecurityException e) {
+ try {
+ debugClasspathConflicts("org/eclipse/jdt/internal/compiler");
+ } catch (Exception e2) {
+ throw Lombok.sneakyThrow(e2);
+ }
+ throw e;
+ }
+ }
+ }
+
+ @SuppressWarnings({"all"})
+ private static void debugClasspathConflicts(String prefixToLookFor) throws Exception {
+ String[] paths = System.getProperty("java.class.path").split(":");
+ for (String p : paths) {
+ Path cp = Paths.get(p);
+ if (Files.isDirectory(cp)) {
+ if (Files.isDirectory(cp.resolve(prefixToLookFor))) System.out.println("** DIR-BASED: " + cp);
+ } else if (Files.isRegularFile(cp)) {
+ JarFile jf = new JarFile(cp.toFile());
+ try {
+ Enumeration<JarEntry> jes = jf.entries();
+ while (jes.hasMoreElements()) {
+ JarEntry je = jes.nextElement();
+ if (je.getName().startsWith(prefixToLookFor)) {
+ System.out.println("** JAR-BASED: " + cp);
+ break;
+ }
+ }
+ } finally {
+ jf.close();
+ }
+ } else {
+ System.out.println("** MISSING: " + cp);
+ }
+ }
+ }
+
private FileSystem createFileSystem(File file, int minVersion) {
List<String> classpath = new ArrayList<String>();
for (Iterator<String> i = classpath.iterator(); i.hasNext();) {
@@ -152,7 +225,7 @@ public class RunTestsViaEcj extends AbstractRunTests {
return new FileSystem(classpath.toArray(new String[0]), new String[] {file.getAbsolutePath()}, "UTF-8");
}
- private static final class TestCompilationUnit extends CompilationUnit {
+ private static final class TestCompilationUnit extends org.eclipse.jdt.internal.core.CompilationUnit {
private final char[] source;
private final char[] mainTypeName;
diff --git a/test/transform/resource/after-delombok/DelegateWithVarargs2.java b/test/transform/resource/after-delombok/DelegateWithVarargs2.java
new file mode 100644
index 00000000..a8ff6e3b
--- /dev/null
+++ b/test/transform/resource/after-delombok/DelegateWithVarargs2.java
@@ -0,0 +1,12 @@
+class DelegateWithVarargs2 {
+ private DelegateWithVarargs2.B bar;
+ public class B {
+ public void varargs(Object[]... keys) {
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public void varargs(final java.lang.Object[]... keys) {
+ this.bar.varargs(keys);
+ }
+}
+
diff --git a/test/transform/resource/after-delombok/GetterSetterJavadoc.java b/test/transform/resource/after-delombok/GetterSetterJavadoc.java
index ae662da7..78d120a4 100644
--- a/test/transform/resource/after-delombok/GetterSetterJavadoc.java
+++ b/test/transform/resource/after-delombok/GetterSetterJavadoc.java
@@ -115,7 +115,7 @@ class GetterSetterJavadoc4 {
/**
* Some text
*
- * @param fieldName Hello, World5
+ * @param fieldName Hello, World4
* @return {@code this}.
*/
@java.lang.SuppressWarnings("all")
diff --git a/test/transform/resource/after-ecj/DelegateWithVarargs2.java b/test/transform/resource/after-ecj/DelegateWithVarargs2.java
new file mode 100644
index 00000000..ed0cddf5
--- /dev/null
+++ b/test/transform/resource/after-ecj/DelegateWithVarargs2.java
@@ -0,0 +1,17 @@
+import lombok.experimental.Delegate;
+class DelegateWithVarargs2 {
+ public class B {
+ public B() {
+ super();
+ }
+ public void varargs(Object[]... keys) {
+ }
+ }
+ private @Delegate DelegateWithVarargs2.B bar;
+ DelegateWithVarargs2() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") void varargs(final java.lang.Object[]... keys) {
+ this.bar.varargs(keys);
+ }
+}
diff --git a/test/transform/resource/before/DelegateWithVarargs2.java b/test/transform/resource/before/DelegateWithVarargs2.java
new file mode 100644
index 00000000..8a3dbf14
--- /dev/null
+++ b/test/transform/resource/before/DelegateWithVarargs2.java
@@ -0,0 +1,9 @@
+import lombok.experimental.Delegate;
+
+class DelegateWithVarargs2 {
+ @Delegate private DelegateWithVarargs2.B bar;
+
+ public class B {
+ public void varargs(Object[]... keys) {}
+ }
+}
diff --git a/website/resources/img/eclipse-p2-step1.png b/website/resources/img/eclipse-p2-step1.png
new file mode 100644
index 00000000..92cdef86
--- /dev/null
+++ b/website/resources/img/eclipse-p2-step1.png
Binary files differ
diff --git a/website/resources/img/eclipse-p2-step2.png b/website/resources/img/eclipse-p2-step2.png
new file mode 100644
index 00000000..84139ad8
--- /dev/null
+++ b/website/resources/img/eclipse-p2-step2.png
Binary files differ
diff --git a/website/templates/features/Builder.html b/website/templates/features/Builder.html
index f9897d03..1b6c6e62 100644
--- a/website/templates/features/Builder.html
+++ b/website/templates/features/Builder.html
@@ -132,7 +132,7 @@
</li>
</ul>
</p><p>
- If your identifiers are written in common english, lombok assumes that the name of any collection with <code>@Singular</code> on it is an english plural and will attempt to automatically singularize that name. If this is possible, the add-one method will use this name. For example, if your collection is called <code>statuses</code>, then the add-one method will automatically be called <code>status</code>. You can also specify the singular form of your identifier explictly by passing the singular form as argument to the annotation like so: <code>@Singular("axis") List&lt;Line&gt; axes;</code>.<br />
+ If your identifiers are written in common english, lombok assumes that the name of any collection with <code>@Singular</code> on it is an english plural and will attempt to automatically singularize that name. If this is possible, the add-one method will use this name. For example, if your collection is called <code>statuses</code>, then the add-one method will automatically be called <code>status</code>. You can also specify the singular form of your identifier explicitly by passing the singular form as argument to the annotation like so: <code>@Singular("axis") List&lt;Line&gt; axes;</code>.<br />
If lombok cannot singularize your identifier, or it is ambiguous, lombok will generate an error and force you to explicitly specify the singular name.
</p><p>
The snippet below does not show what lombok generates for a <code>@Singular</code> field/parameter because it is rather complicated. You can view a snippet <a href="builderSingular">here</a>.
diff --git a/website/templates/setup/eclipse.html b/website/templates/setup/eclipse.html
index 85304c83..d9621501 100644
--- a/website/templates/setup/eclipse.html
+++ b/website/templates/setup/eclipse.html
@@ -23,4 +23,16 @@
<img src="/img/eclipse-about.png" />
</p>
</@s.introduction>
+ <@s.section title="Via eclipse plugin installer">
+ <em>WARNING: This plugin installer is currently unsigned, and we have given up on figuring out how to fix that; if team eclipse or somebody else can help us out, we're all ears!</em>
+ <p>
+ You can install lombok directly from within eclipse, and in that way, you can also include lombok as part of your team eclipse deployment configuration. To do this, use
+ update site <code>https://projectlombok.org/p2</code>:<br />
+ <br />
+ <img width="448" height="431" src="/img/eclipse-p2-step1.png" /><br />
+ <br />
+ <br />
+ <img width="626" height="216" src="/img/eclipse-p2-step2.png" />
+ </p>
+ </@s.section>
</@s.scaffold>
diff --git a/website/templates/setup/kobalt.html b/website/templates/setup/kobalt.html
index 26adf23d..beb60d8c 100644
--- a/website/templates/setup/kobalt.html
+++ b/website/templates/setup/kobalt.html
@@ -3,7 +3,7 @@
<@s.scaffold title="Kobalt">
<@s.introduction>
<p>
- To set up lombok with any build tool, you have to specify that the lombok dependency is required to compile your source code, but does not need to be present when running/testing/jarring/otherwise deploying your code. Generally this is called a 'provided' dependency. This page explains how to integrate lombok with the <a href="http://beust.com/kobalt/home/index.html">Kobalt</a> buid tool.
+ To set up lombok with any build tool, you have to specify that the lombok dependency is required to compile your source code, but does not need to be present when running/testing/jarring/otherwise deploying your code. Generally this is called a 'provided' dependency. This page explains how to integrate lombok with the <a href="http://beust.com/kobalt/home/index.html">Kobalt</a> build tool.
</p><p>
Lombok is available in maven central, so telling Kobalt to download lombok is easy.
</p>