diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/lombok/core/PostCompiler.java | 10 | ||||
-rw-r--r-- | src/core/lombok/eclipse/EclipseAST.java | 2 | ||||
-rw-r--r-- | src/core/lombok/eclipse/TransformEclipseAST.java | 36 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java | 8 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/JavacHandlerUtil.java | 55 | ||||
-rw-r--r-- | src/eclipseAgent/lombok/eclipse/agent/PatchVal.java | 25 | ||||
-rw-r--r-- | src/stubs/com/sun/tools/javac/code/Symbol.java | 8 | ||||
-rw-r--r-- | src/stubs/com/sun/tools/javac/code/Symtab.java | 2 | ||||
-rw-r--r-- | src/support/lombok/website/RunSite.java | 107 |
9 files changed, 228 insertions, 25 deletions
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/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 2523103f..efc4bf61 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -40,6 +40,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; @@ -1127,7 +1128,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; @@ -1178,8 +1197,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; @@ -1196,7 +1217,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); @@ -1204,18 +1225,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/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..ad4a3731 --- /dev/null +++ b/src/support/lombok/website/RunSite.java @@ -0,0 +1,107 @@ +package lombok.website; + +import static spark.Spark.*; + +import java.awt.Desktop; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +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; +import spark.resource.InputStreamResource; + +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"; + } +} |