aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-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
7 files changed, 108 insertions, 24 deletions
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;