From 04d041a7dcb4f57c5b5bf460cf78cddfaba4853b Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Tue, 9 Nov 2010 20:32:47 +0100 Subject: Delegate annotation --- src/core/lombok/Delegate.java | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/core/lombok/Delegate.java (limited to 'src/core') diff --git a/src/core/lombok/Delegate.java b/src/core/lombok/Delegate.java new file mode 100644 index 00000000..0bbaed0d --- /dev/null +++ b/src/core/lombok/Delegate.java @@ -0,0 +1,26 @@ +/* + * Copyright © 2010 Reinier Zwitserloot, Roel Spilker and Robbert Jan Grootjans. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok; + +public @interface Delegate { + Class value() default java.lang.Object.class; +} -- cgit From 0951ea38fe11189cdc4c2778fdad9e9e3ad6a6ae Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Tue, 9 Nov 2010 20:35:34 +0100 Subject: Experiment to try and make java 'self referential' by deleting the Enter and MemberEnter state. So far it doesn't work yet. --- src/core/lombok/eclipse/handlers/HandleVal.java | 2 +- src/core/lombok/javac/HandlerLibrary.java | 39 +++++++++++----------- src/core/lombok/javac/JavacAnnotationHandler.java | 5 +++ src/core/lombok/javac/JavacResolution.java | 1 + src/core/lombok/javac/JavacTransformer.java | 34 ++++++++++++++++--- src/core/lombok/javac/apt/Processor.java | 3 +- src/core/lombok/javac/handlers/HandleCleanup.java | 6 +++- .../lombok/javac/handlers/HandleConstructor.java | 12 +++++++ src/core/lombok/javac/handlers/HandleData.java | 4 +++ .../javac/handlers/HandleEqualsAndHashCode.java | 4 +++ src/core/lombok/javac/handlers/HandleGetter.java | 4 +++ src/core/lombok/javac/handlers/HandleLog.java | 18 +++++++++- src/core/lombok/javac/handlers/HandlePrintAST.java | 4 +++ src/core/lombok/javac/handlers/HandleSetter.java | 4 +++ .../lombok/javac/handlers/HandleSneakyThrows.java | 4 +++ .../lombok/javac/handlers/HandleSynchronized.java | 4 +++ src/core/lombok/javac/handlers/HandleToString.java | 4 +++ src/core/lombok/javac/handlers/HandleVal.java | 4 ++- src/delombok/lombok/delombok/Delombok.java | 3 +- .../lombok/netbeans/agent/NetbeansEntryPoint.java | 2 +- 20 files changed, 130 insertions(+), 31 deletions(-) (limited to 'src/core') diff --git a/src/core/lombok/eclipse/handlers/HandleVal.java b/src/core/lombok/eclipse/handlers/HandleVal.java index b3cfa879..7f4f36fb 100644 --- a/src/core/lombok/eclipse/handlers/HandleVal.java +++ b/src/core/lombok/eclipse/handlers/HandleVal.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009-2010 Reinier Zwitserloot, Roel Spilker and Robbert Jan Grootjans. + * Copyright © 2010 Reinier Zwitserloot, Roel Spilker and Robbert Jan Grootjans. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/core/lombok/javac/HandlerLibrary.java b/src/core/lombok/javac/HandlerLibrary.java index 5b792874..8eb7be9f 100644 --- a/src/core/lombok/javac/HandlerLibrary.java +++ b/src/core/lombok/javac/HandlerLibrary.java @@ -51,7 +51,7 @@ public class HandlerLibrary { private final Map> annotationHandlers = new HashMap>(); private final Collection visitorHandlers = new ArrayList(); private final Messager messager; - private boolean skipPrintAST = true; + private int phase = 0; /** * Creates a new HandlerLibrary that will report any problems or errors to the provided messager. @@ -70,6 +70,10 @@ public class HandlerLibrary { this.annotationClass = annotationClass; } + public boolean isResolutionBased() { + return handler.isResolutionBased(); + } + public boolean handle(final JavacNode node) { return handler.handle(Javac.createAnnotation(annotationClass, node), (JCAnnotation)node.get(), node); } @@ -160,12 +164,14 @@ public class HandlerLibrary { boolean handled = false; for (String fqn : resolver.findTypeMatches(node, rawType)) { boolean isPrintAST = fqn.equals(PrintAST.class.getName()); - if (isPrintAST == skipPrintAST) continue; + if (isPrintAST && phase != 2) continue; + if (!isPrintAST && phase == 2) continue; AnnotationHandlerContainer container = annotationHandlers.get(fqn); if (container == null) continue; try { - handled |= container.handle(node); + if (container.isResolutionBased() && phase == 1) handled |= container.handle(node); + if (!container.isResolutionBased() && phase == 0) handled |= container.handle(node); } catch (AnnotationValueDecodeFail fail) { fail.owner.setError(fail.getMessage(), fail.idx); } catch (Throwable t) { @@ -183,13 +189,8 @@ public class HandlerLibrary { */ public void callASTVisitors(JavacAST ast) { for (JavacASTVisitor visitor : visitorHandlers) try { - if (!visitor.isResolutionBased()) ast.traverse(visitor); - } catch (Throwable t) { - javacError(String.format("Lombok visitor handler %s failed", visitor.getClass()), t); - } - - for (JavacASTVisitor visitor : visitorHandlers) try { - if (visitor.isResolutionBased()) ast.traverse(visitor); + if (!visitor.isResolutionBased() && phase == 0) ast.traverse(visitor); + if (visitor.isResolutionBased() && phase == 1) ast.traverse(visitor); } catch (Throwable t) { javacError(String.format("Lombok visitor handler %s failed", visitor.getClass()), t); } @@ -197,17 +198,17 @@ public class HandlerLibrary { /** * Lombok does not currently support triggering annotations in a specified order; the order is essentially - * random right now. This lack of order is particularly annoying for the {@code PrintAST} annotation, - * which is almost always intended to run last. Hence, this hack, which lets it in fact run last. - * - * @see #skipAllButPrintAST() + * random right now. As a temporary hack we've identified 3 important phases. */ - public void skipPrintAST() { - skipPrintAST = true; + public void setPreResolutionPhase() { + phase = 0; + } + + public void setPostResolutionPhase() { + phase = 1; } - /** @see #skipPrintAST() */ - public void skipAllButPrintAST() { - skipPrintAST = false; + public void setPrintASTPhase() { + phase = 2; } } diff --git a/src/core/lombok/javac/JavacAnnotationHandler.java b/src/core/lombok/javac/JavacAnnotationHandler.java index 5b6fe4ce..ee330ecb 100644 --- a/src/core/lombok/javac/JavacAnnotationHandler.java +++ b/src/core/lombok/javac/JavacAnnotationHandler.java @@ -55,4 +55,9 @@ public interface JavacAnnotationHandler { * compile session (you've handled it), or {@code false} to indicate you aren't done yet. */ boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode); + + /** + * Return true if this handler requires resolution. + */ + boolean isResolutionBased(); } diff --git a/src/core/lombok/javac/JavacResolution.java b/src/core/lombok/javac/JavacResolution.java index e0eb436d..26ff34d0 100644 --- a/src/core/lombok/javac/JavacResolution.java +++ b/src/core/lombok/javac/JavacResolution.java @@ -11,6 +11,7 @@ import javax.lang.model.type.TypeKind; import javax.tools.DiagnosticListener; import com.sun.tools.javac.code.BoundKind; +import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.code.Type.ArrayType; diff --git a/src/core/lombok/javac/JavacTransformer.java b/src/core/lombok/javac/JavacTransformer.java index 5f145460..c703b1c7 100644 --- a/src/core/lombok/javac/JavacTransformer.java +++ b/src/core/lombok/javac/JavacTransformer.java @@ -22,16 +22,18 @@ package lombok.javac; import java.util.ArrayList; -import java.util.List; import javax.annotation.processing.Messager; +import com.sun.tools.javac.comp.Enter; +import com.sun.tools.javac.comp.MemberEnter; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.List; public class JavacTransformer { private final HandlerLibrary handlers; @@ -42,18 +44,39 @@ public class JavacTransformer { this.handlers = HandlerLibrary.load(messager); } - public boolean transform(Context context, Iterable compilationUnits) { - List asts = new ArrayList(); + public boolean transform(Context context, java.util.List compilationUnitsRaw) { + List compilationUnits; + if (compilationUnitsRaw instanceof List) { + compilationUnits = (List)compilationUnitsRaw; + } else { + compilationUnits = List.nil(); + for (int i = compilationUnitsRaw.size() -1; i >= 0; i--) { + compilationUnits = compilationUnits.prepend(compilationUnitsRaw.get(i)); + } + } + + java.util.List asts = new ArrayList(); for (JCCompilationUnit unit : compilationUnits) asts.add(new JavacAST(messager, context, unit)); - handlers.skipPrintAST(); + handlers.setPreResolutionPhase(); + for (JavacAST ast : asts) { + ast.traverse(new AnnotationVisitor()); + handlers.callASTVisitors(ast); + } + + context.put(Enter.class, (Enter) null); + context.put(MemberEnter.class, (MemberEnter) null); + Enter.instance(context).main(compilationUnits); + + handlers.setPostResolutionPhase(); for (JavacAST ast : asts) { ast.traverse(new AnnotationVisitor()); handlers.callASTVisitors(ast); } - handlers.skipAllButPrintAST(); + + handlers.setPrintASTPhase(); for (JavacAST ast : asts) { ast.traverse(new AnnotationVisitor()); } @@ -61,6 +84,7 @@ public class JavacTransformer { for (JavacAST ast : asts) { if (ast.isChanged()) return true; } + return false; } diff --git a/src/core/lombok/javac/apt/Processor.java b/src/core/lombok/javac/apt/Processor.java index 037f5ba5..58631c66 100644 --- a/src/core/lombok/javac/apt/Processor.java +++ b/src/core/lombok/javac/apt/Processor.java @@ -26,6 +26,7 @@ import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URL; +import java.util.ArrayList; import java.util.Enumeration; import java.util.IdentityHashMap; import java.util.Map; @@ -172,7 +173,7 @@ public class Processor extends AbstractProcessor { if (unit != null) units.put(unit, null); } - transformer.transform(processingEnv.getContext(), units.keySet()); + transformer.transform(processingEnv.getContext(), new ArrayList(units.keySet())); return false; } diff --git a/src/core/lombok/javac/handlers/HandleCleanup.java b/src/core/lombok/javac/handlers/HandleCleanup.java index 779dd3ea..7210c5e7 100644 --- a/src/core/lombok/javac/handlers/HandleCleanup.java +++ b/src/core/lombok/javac/handlers/HandleCleanup.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -154,4 +154,8 @@ public class HandleCleanup implements JavacAnnotationHandler { } } } + + @Override public boolean isResolutionBased() { + return false; + } } diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java index c2332974..d56c976f 100644 --- a/src/core/lombok/javac/handlers/HandleConstructor.java +++ b/src/core/lombok/javac/handlers/HandleConstructor.java @@ -69,6 +69,10 @@ public class HandleConstructor { new HandleConstructor().generateConstructor(typeNode, level, fields, staticName, false, false); return true; } + + @Override public boolean isResolutionBased() { + return false; + } } @ProviderFor(JavacAnnotationHandler.class) @@ -86,6 +90,10 @@ public class HandleConstructor { new HandleConstructor().generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, false, suppressConstructorProperties); return true; } + + @Override public boolean isResolutionBased() { + return false; + } } private static List findRequiredFields(JavacNode typeNode) { @@ -131,6 +139,10 @@ public class HandleConstructor { new HandleConstructor().generateConstructor(typeNode, level, fields, staticName, false, suppressConstructorProperties); return true; } + + @Override public boolean isResolutionBased() { + return false; + } } public void generateRequiredArgsConstructor(JavacNode typeNode, AccessLevel level, String staticName, boolean skipIfConstructorExists) { diff --git a/src/core/lombok/javac/handlers/HandleData.java b/src/core/lombok/javac/handlers/HandleData.java index 2087c133..682b7fe4 100644 --- a/src/core/lombok/javac/handlers/HandleData.java +++ b/src/core/lombok/javac/handlers/HandleData.java @@ -63,4 +63,8 @@ public class HandleData implements JavacAnnotationHandler { return true; } + + @Override public boolean isResolutionBased() { + return false; + } } diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index c5475fb1..376823cf 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -479,4 +479,8 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler { return treeMaker.MethodDef(treeMaker.Modifiers(access, nonNulls.appendList(nullables)), methodName, methodType, methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue); } + + @Override public boolean isResolutionBased() { + return false; + } } diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java index 03e40d7f..c72892cc 100644 --- a/src/core/lombok/javac/handlers/HandleLog.java +++ b/src/core/lombok/javac/handlers/HandleLog.java @@ -121,6 +121,10 @@ public class HandleLog { @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { return processAnnotation(LoggingFramework.COMMONS, annotation, annotationNode); } + + @Override public boolean isResolutionBased() { + return false; + } } /** @@ -131,7 +135,11 @@ public class HandleLog { @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { return processAnnotation(LoggingFramework.JUL, annotation, annotationNode); } - } + + @Override public boolean isResolutionBased() { + return false; + } + } /** * Handles the {@link lombok.extern.log4j.Log} annotation for javac. @@ -141,6 +149,10 @@ public class HandleLog { @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { return processAnnotation(LoggingFramework.LOG4J, annotation, annotationNode); } + + @Override public boolean isResolutionBased() { + return false; + } } /** @@ -151,6 +163,10 @@ public class HandleLog { @Override public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { return processAnnotation(LoggingFramework.SLF4J, annotation, annotationNode); } + + @Override public boolean isResolutionBased() { + return false; + } } enum LoggingFramework { diff --git a/src/core/lombok/javac/handlers/HandlePrintAST.java b/src/core/lombok/javac/handlers/HandlePrintAST.java index 4c25694b..61b877d6 100644 --- a/src/core/lombok/javac/handlers/HandlePrintAST.java +++ b/src/core/lombok/javac/handlers/HandlePrintAST.java @@ -54,4 +54,8 @@ public class HandlePrintAST implements JavacAnnotationHandler { return true; } + + @Override public boolean isResolutionBased() { + return false; + } } diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index 98b68e4a..9c7a233a 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -238,4 +238,8 @@ public class HandleSetter implements JavacAnnotationHandler { return v.visitNoType(this, p); } } + + @Override public boolean isResolutionBased() { + return false; + } } diff --git a/src/core/lombok/javac/handlers/HandleSneakyThrows.java b/src/core/lombok/javac/handlers/HandleSneakyThrows.java index b2337f67..0f37a80e 100644 --- a/src/core/lombok/javac/handlers/HandleSneakyThrows.java +++ b/src/core/lombok/javac/handlers/HandleSneakyThrows.java @@ -110,4 +110,8 @@ public class HandleSneakyThrows implements JavacAnnotationHandler return maker.Try(tryBlock, List.of(maker.Catch(catchParam, catchBody)), null); } + + @Override public boolean isResolutionBased() { + return false; + } } diff --git a/src/core/lombok/javac/handlers/HandleSynchronized.java b/src/core/lombok/javac/handlers/HandleSynchronized.java index a095aaf1..b1394b02 100644 --- a/src/core/lombok/javac/handlers/HandleSynchronized.java +++ b/src/core/lombok/javac/handlers/HandleSynchronized.java @@ -107,4 +107,8 @@ public class HandleSynchronized implements JavacAnnotationHandler return true; } + + @Override public boolean isResolutionBased() { + return false; + } } diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java index e3cb0294..f52602c3 100644 --- a/src/core/lombok/javac/handlers/HandleToString.java +++ b/src/core/lombok/javac/handlers/HandleToString.java @@ -247,4 +247,8 @@ public class HandleToString implements JavacAnnotationHandler { } return typeName; } + + @Override public boolean isResolutionBased() { + return false; + } } diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java index 5da6fec0..983f2d86 100644 --- a/src/core/lombok/javac/handlers/HandleVal.java +++ b/src/core/lombok/javac/handlers/HandleVal.java @@ -1,5 +1,5 @@ /* - * Copyright © 2010 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2010 Reinier Zwitserloot, Roel Spilker and Robbert Jan Grootjans. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,8 +31,10 @@ import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop; import com.sun.tools.javac.tree.JCTree.JCExpression; +import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCNewArray; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; diff --git a/src/delombok/lombok/delombok/Delombok.java b/src/delombok/lombok/delombok/Delombok.java index 6866d97f..846b448f 100644 --- a/src/delombok/lombok/delombok/Delombok.java +++ b/src/delombok/lombok/delombok/Delombok.java @@ -383,7 +383,8 @@ public class Delombok { compiler.enterTrees(toJavacList(roots)); for (JCCompilationUnit unit : roots) { - boolean changed = new JavacTransformer(messager).transform(context, Collections.singleton(unit)); + // Run one single massive transform instead of a lot of singleton calls, as this causes a heck of a lot of refilling of the enter cache. + boolean changed = new JavacTransformer(messager).transform(context, Collections.singletonList(unit)); DelombokResult result = new DelombokResult(commentsMap.get(unit).comments, unit, force || changed); if (verbose) feedback.printf("File: %s [%s]\n", unit.sourcefile.getName(), result.isChanged() ? "delomboked" : "unchanged"); Writer rawWriter; diff --git a/src/netbeansAgent/lombok/netbeans/agent/NetbeansEntryPoint.java b/src/netbeansAgent/lombok/netbeans/agent/NetbeansEntryPoint.java index 963b70b5..f1f02d2c 100644 --- a/src/netbeansAgent/lombok/netbeans/agent/NetbeansEntryPoint.java +++ b/src/netbeansAgent/lombok/netbeans/agent/NetbeansEntryPoint.java @@ -69,7 +69,7 @@ public class NetbeansEntryPoint implements TaskListener { if (TaskEvent.Kind.PARSE == event.getKind()) { JavacTransformer transformer = new JavacTransformer(new DummyMessager()); //TODO hook into netbeans error reporting! JCCompilationUnit compilationUnit = (JCCompilationUnit) event.getCompilationUnit(); - transformer.transform(context, Collections.singleton(compilationUnit)); + transformer.transform(context, Collections.singletonList(compilationUnit)); } } } -- cgit From 186b16c28cf461f88a3b5eecd2fa4523af2949d9 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Tue, 9 Nov 2010 23:52:54 +0100 Subject: EqualsAndHashCode no longer worked right when working on a class with 0 fileds. Fixed. Thanks to Philipp Eichhorn for spotting this problem! --- .../eclipse/handlers/HandleEqualsAndHashCode.java | 2 +- .../javac/handlers/HandleEqualsAndHashCode.java | 36 ++++++++++++---------- 2 files changed, 20 insertions(+), 18 deletions(-) (limited to 'src/core') diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java index 23d24fb0..2b830241 100644 --- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java @@ -505,7 +505,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler other = (MyType) o; */ { - if (!fields.isEmpty()) { + if (!fields.isEmpty() || needsCanEqual) { LocalDeclaration other = new LocalDeclaration(otherName, pS, pE); other.modifiers |= ClassFileConstants.AccFinal; Eclipse.setGeneratedBy(other, source); diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index f824986c..8d524964 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -356,24 +356,26 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler other = (MyType) o; */ { - final JCExpression selfType1, selfType2; - List wildcards1 = List.nil(); - List wildcards2 = List.nil(); - for (int i = 0 ; i < type.typarams.length() ; i++) { - wildcards1 = wildcards1.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null)); - wildcards2 = wildcards2.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null)); - } - - if (type.typarams.isEmpty()) { - selfType1 = maker.Ident(type.name); - selfType2 = maker.Ident(type.name); - } else { - selfType1 = maker.TypeApply(maker.Ident(type.name), wildcards1); - selfType2 = maker.TypeApply(maker.Ident(type.name), wildcards2); + if (!fields.isEmpty() || needsCanEqual) { + final JCExpression selfType1, selfType2; + List wildcards1 = List.nil(); + List wildcards2 = List.nil(); + for (int i = 0 ; i < type.typarams.length() ; i++) { + wildcards1 = wildcards1.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null)); + wildcards2 = wildcards2.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null)); + } + + if (type.typarams.isEmpty()) { + selfType1 = maker.Ident(type.name); + selfType2 = maker.Ident(type.name); + } else { + selfType1 = maker.TypeApply(maker.Ident(type.name), wildcards1); + selfType2 = maker.TypeApply(maker.Ident(type.name), wildcards2); + } + + statements = statements.append( + maker.VarDef(maker.Modifiers(Flags.FINAL), otherName, selfType1, maker.TypeCast(selfType2, maker.Ident(oName)))); } - - statements = statements.append( - maker.VarDef(maker.Modifiers(Flags.FINAL), otherName, selfType1, maker.TypeCast(selfType2, maker.Ident(oName)))); } /* if (!other.canEqual(this)) return false; */ { -- cgit From 63519f9ae601e00430c5fd542bedf79beb688db3 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 10 Nov 2010 00:24:10 +0100 Subject: Undone something that'll never work anyway --- src/core/lombok/javac/JavacResolution.java | 1 - src/core/lombok/javac/JavacTransformer.java | 6 ------ 2 files changed, 7 deletions(-) (limited to 'src/core') diff --git a/src/core/lombok/javac/JavacResolution.java b/src/core/lombok/javac/JavacResolution.java index 26ff34d0..e0eb436d 100644 --- a/src/core/lombok/javac/JavacResolution.java +++ b/src/core/lombok/javac/JavacResolution.java @@ -11,7 +11,6 @@ import javax.lang.model.type.TypeKind; import javax.tools.DiagnosticListener; import com.sun.tools.javac.code.BoundKind; -import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.code.Type.ArrayType; diff --git a/src/core/lombok/javac/JavacTransformer.java b/src/core/lombok/javac/JavacTransformer.java index c703b1c7..5d1e79af 100644 --- a/src/core/lombok/javac/JavacTransformer.java +++ b/src/core/lombok/javac/JavacTransformer.java @@ -25,8 +25,6 @@ import java.util.ArrayList; import javax.annotation.processing.Messager; -import com.sun.tools.javac.comp.Enter; -import com.sun.tools.javac.comp.MemberEnter; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; @@ -65,10 +63,6 @@ public class JavacTransformer { handlers.callASTVisitors(ast); } - context.put(Enter.class, (Enter) null); - context.put(MemberEnter.class, (MemberEnter) null); - Enter.instance(context).main(compilationUnits); - handlers.setPostResolutionPhase(); for (JavacAST ast : asts) { ast.traverse(new AnnotationVisitor()); -- cgit From 2bc8ad4dfd6e34e15f2bd7a661d62bc26cc13379 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 10 Nov 2010 01:27:00 +0100 Subject: 'val' now fully works on javac, even when referring to lombok-generated code, by (ab)using the annotation processor's round system. This breaks delombok though. That'll have to be fixed next. --- src/core/lombok/javac/JavacTransformer.java | 33 ++++++++-------- .../javac/apt/InterceptingJavaFileManager.java | 22 +++++++++++ src/core/lombok/javac/apt/Processor.java | 45 +++++++++++++++++++--- src/core/lombok/javac/handlers/HandleVal.java | 2 - src/delombok/lombok/delombok/Delombok.java | 3 +- 5 files changed, 82 insertions(+), 23 deletions(-) (limited to 'src/core') diff --git a/src/core/lombok/javac/JavacTransformer.java b/src/core/lombok/javac/JavacTransformer.java index 5d1e79af..e90f780b 100644 --- a/src/core/lombok/javac/JavacTransformer.java +++ b/src/core/lombok/javac/JavacTransformer.java @@ -42,7 +42,7 @@ public class JavacTransformer { this.handlers = HandlerLibrary.load(messager); } - public boolean transform(Context context, java.util.List compilationUnitsRaw) { + public boolean transform(boolean postResolution, Context context, java.util.List compilationUnitsRaw) { List compilationUnits; if (compilationUnitsRaw instanceof List) { compilationUnits = (List)compilationUnitsRaw; @@ -57,22 +57,25 @@ public class JavacTransformer { for (JCCompilationUnit unit : compilationUnits) asts.add(new JavacAST(messager, context, unit)); - handlers.setPreResolutionPhase(); - for (JavacAST ast : asts) { - ast.traverse(new AnnotationVisitor()); - handlers.callASTVisitors(ast); - } - - handlers.setPostResolutionPhase(); - for (JavacAST ast : asts) { - ast.traverse(new AnnotationVisitor()); - handlers.callASTVisitors(ast); + if (!postResolution) { + handlers.setPreResolutionPhase(); + for (JavacAST ast : asts) { + ast.traverse(new AnnotationVisitor()); + handlers.callASTVisitors(ast); + } } - - handlers.setPrintASTPhase(); - for (JavacAST ast : asts) { - ast.traverse(new AnnotationVisitor()); + if (postResolution) { + handlers.setPostResolutionPhase(); + for (JavacAST ast : asts) { + ast.traverse(new AnnotationVisitor()); + handlers.callASTVisitors(ast); + } + + handlers.setPrintASTPhase(); + for (JavacAST ast : asts) { + ast.traverse(new AnnotationVisitor()); + } } for (JavacAST ast : asts) { diff --git a/src/core/lombok/javac/apt/InterceptingJavaFileManager.java b/src/core/lombok/javac/apt/InterceptingJavaFileManager.java index 2b570eb0..738804ea 100644 --- a/src/core/lombok/javac/apt/InterceptingJavaFileManager.java +++ b/src/core/lombok/javac/apt/InterceptingJavaFileManager.java @@ -21,13 +21,19 @@ */ package lombok.javac.apt; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; import java.util.Iterator; import java.util.Set; import javax.tools.FileObject; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; import javax.tools.JavaFileObject.Kind; import lombok.core.DiagnosticsReceiver; @@ -42,6 +48,22 @@ final class InterceptingJavaFileManager implements JavaFileManager { } @Override public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException { + if (className.startsWith("lombok.dummy.ForceNewRound")) { + String name = className.replace(".", "/") + kind.extension; + return new SimpleJavaFileObject(URI.create(name), kind) { + @Override public OutputStream openOutputStream() throws IOException { + return new ByteArrayOutputStream(); + } + + @Override public InputStream openInputStream() throws IOException { + return new ByteArrayInputStream(new byte[0]); + } + + @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + return ""; + } + }; + } JavaFileObject fileObject = delegate.getJavaFileForOutput(location, className, kind, sibling); if (kind != Kind.CLASS) { return fileObject; diff --git a/src/core/lombok/javac/apt/Processor.java b/src/core/lombok/javac/apt/Processor.java index 58631c66..b5d5c81c 100644 --- a/src/core/lombok/javac/apt/Processor.java +++ b/src/core/lombok/javac/apt/Processor.java @@ -23,6 +23,7 @@ package lombok.javac.apt; import java.io.IOException; import java.io.InputStream; +import java.io.Writer; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URL; @@ -41,7 +42,9 @@ import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic.Kind; import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; import lombok.Lombok; import lombok.core.DiagnosticsReceiver; @@ -49,6 +52,7 @@ import lombok.javac.JavacTransformer; import com.sun.source.util.TreePath; import com.sun.source.util.Trees; +import com.sun.tools.javac.processing.JavacFiler; import com.sun.tools.javac.processing.JavacProcessingEnvironment; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.util.Context; @@ -75,12 +79,12 @@ public class Processor extends AbstractProcessor { @Override public void init(ProcessingEnvironment procEnv) { super.init(procEnv); this.processingEnv = (JavacProcessingEnvironment) procEnv; - placePostCompileHook(); + placePostCompileAndDontMakeForceRoundDummiesHook(); transformer = new JavacTransformer(procEnv.getMessager()); trees = Trees.instance(procEnv); } - private void placePostCompileHook() { + private void placePostCompileAndDontMakeForceRoundDummiesHook() { stopJavacProcessingEnvironmentFromClosingOurClassloader(); Context context = processingEnv.getContext(); @@ -101,6 +105,9 @@ public class Processor extends AbstractProcessor { JavaFileManager newFiler = new InterceptingJavaFileManager(originalFiler, receiver); ht.put(key, newFiler); + Field filerFileManagerField = JavacFiler.class.getDeclaredField("fileManager"); + filerFileManagerField.setAccessible(true); + filerFileManagerField.set(processingEnv.getFiler(), newFiler); } } catch (Exception e) { throw Lombok.sneakyThrow(e); @@ -165,15 +172,43 @@ public class Processor extends AbstractProcessor { } } + private final IdentityHashMap rootsAtPhase0 = new IdentityHashMap(); + private final IdentityHashMap rootsAtPhase1 = new IdentityHashMap(); + private int dummyCount = 0; + /** {@inheritDoc} */ @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { - IdentityHashMap units = new IdentityHashMap(); + if (roundEnv.processingOver()) return false; + + if (!rootsAtPhase0.isEmpty()) { + ArrayList cus = new ArrayList(rootsAtPhase0.keySet()); + transformer.transform(true, processingEnv.getContext(), cus); + rootsAtPhase1.putAll(rootsAtPhase0); + rootsAtPhase0.clear(); + } + for (Element element : roundEnv.getRootElements()) { JCCompilationUnit unit = toUnit(element); - if (unit != null) units.put(unit, null); + if (unit != null) { + if (!rootsAtPhase1.containsKey(unit)) rootsAtPhase0.put(unit, null); + } } - transformer.transform(processingEnv.getContext(), new ArrayList(units.keySet())); + if (!rootsAtPhase0.isEmpty()) { + ArrayList cus = new ArrayList(rootsAtPhase0.keySet()); + transformer.transform(false, processingEnv.getContext(), cus); + JavacFiler filer = (JavacFiler) processingEnv.getFiler(); + if (!filer.newFiles()) { + try { + JavaFileObject dummy = filer.createSourceFile("lombok.dummy.ForceNewRound" + (dummyCount++)); + Writer w = dummy.openWriter(); + w.close(); + } catch (Exception e) { + processingEnv.getMessager().printMessage(Kind.WARNING, + "Can't force a new processing round. Lombok features that require resolution won't work."); + } + } + } return false; } diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java index 983f2d86..bf938362 100644 --- a/src/core/lombok/javac/handlers/HandleVal.java +++ b/src/core/lombok/javac/handlers/HandleVal.java @@ -31,10 +31,8 @@ import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop; import com.sun.tools.javac.tree.JCTree.JCExpression; -import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCNewArray; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; diff --git a/src/delombok/lombok/delombok/Delombok.java b/src/delombok/lombok/delombok/Delombok.java index 846b448f..95ceb309 100644 --- a/src/delombok/lombok/delombok/Delombok.java +++ b/src/delombok/lombok/delombok/Delombok.java @@ -384,7 +384,8 @@ public class Delombok { for (JCCompilationUnit unit : roots) { // Run one single massive transform instead of a lot of singleton calls, as this causes a heck of a lot of refilling of the enter cache. - boolean changed = new JavacTransformer(messager).transform(context, Collections.singletonList(unit)); + // XXX This isn't enough - we need to call transform again after resetting everything. + boolean changed = new JavacTransformer(messager).transform(false, context, Collections.singletonList(unit)); DelombokResult result = new DelombokResult(commentsMap.get(unit).comments, unit, force || changed); if (verbose) feedback.printf("File: %s [%s]\n", unit.sourcefile.getName(), result.isChanged() ? "delomboked" : "unchanged"); Writer rawWriter; -- cgit From 5b5a3713e2436706f80e782ed26479b066205ab4 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 10 Nov 2010 22:18:07 +0100 Subject: Fix for javac: 'val x = null;' is now valid, and results in x being of type Object. --- src/core/lombok/javac/JavacResolution.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/core') diff --git a/src/core/lombok/javac/JavacResolution.java b/src/core/lombok/javac/JavacResolution.java index e0eb436d..2845328d 100644 --- a/src/core/lombok/javac/JavacResolution.java +++ b/src/core/lombok/javac/JavacResolution.java @@ -325,6 +325,8 @@ public class JavacResolution { // NB: There's such a thing as maker.Type(type), but this doesn't work very well; it screws up anonymous classes, captures, and adds an extra prefix dot for some reason too. // -- so we write our own take on that here. + if (type.tag == TypeTags.BOT) return createJavaLangObject(maker, ast); + if (type.isPrimitive()) return primitiveToJCTree(type.getKind(), maker); if (type.isErroneous()) throw new TypeNotConvertibleException("Type cannot be resolved"); -- cgit From 249566813149f8e6984561d9d2ba4e348974dc1a Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 10 Nov 2010 22:19:26 +0100 Subject: Delombok has been fixed to work more like a true javac run now. As a result, its now compatible with resolution again (i.e. resolution based transformers are applied correctly when delomboking). --- src/core/lombok/javac/JavacTransformer.java | 9 +++--- src/core/lombok/javac/TrackChangedAsts.java | 10 +++++++ src/delombok/lombok/delombok/Delombok.java | 46 ++++++++++------------------- 3 files changed, 30 insertions(+), 35 deletions(-) create mode 100644 src/core/lombok/javac/TrackChangedAsts.java (limited to 'src/core') diff --git a/src/core/lombok/javac/JavacTransformer.java b/src/core/lombok/javac/JavacTransformer.java index e90f780b..f9757894 100644 --- a/src/core/lombok/javac/JavacTransformer.java +++ b/src/core/lombok/javac/JavacTransformer.java @@ -42,7 +42,7 @@ public class JavacTransformer { this.handlers = HandlerLibrary.load(messager); } - public boolean transform(boolean postResolution, Context context, java.util.List compilationUnitsRaw) { + public void transform(boolean postResolution, Context context, java.util.List compilationUnitsRaw) { List compilationUnits; if (compilationUnitsRaw instanceof List) { compilationUnits = (List)compilationUnitsRaw; @@ -78,11 +78,10 @@ public class JavacTransformer { } } - for (JavacAST ast : asts) { - if (ast.isChanged()) return true; + TrackChangedAsts changes = context.get(TrackChangedAsts.class); + if (changes != null) for (JavacAST ast : asts) { + if (ast.isChanged()) changes.changed.add((JCCompilationUnit) ast.top().get()); } - - return false; } private class AnnotationVisitor extends JavacASTAdapter { diff --git a/src/core/lombok/javac/TrackChangedAsts.java b/src/core/lombok/javac/TrackChangedAsts.java new file mode 100644 index 00000000..fa6c0f18 --- /dev/null +++ b/src/core/lombok/javac/TrackChangedAsts.java @@ -0,0 +1,10 @@ +package lombok.javac; + +import java.util.HashSet; +import java.util.Set; + +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; + +public class TrackChangedAsts { + public final Set changed = new HashSet(); +} \ No newline at end of file diff --git a/src/delombok/lombok/delombok/Delombok.java b/src/delombok/lombok/delombok/Delombok.java index 95ceb309..6fc77c59 100644 --- a/src/delombok/lombok/delombok/Delombok.java +++ b/src/delombok/lombok/delombok/Delombok.java @@ -41,16 +41,11 @@ import java.util.List; import java.util.ListIterator; import java.util.Map; -import javax.annotation.processing.Messager; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.Element; import javax.tools.DiagnosticListener; import javax.tools.JavaFileObject; -import javax.tools.Diagnostic.Kind; import lombok.javac.DeleteLombokAnnotations; -import lombok.javac.JavacTransformer; +import lombok.javac.TrackChangedAsts; import com.sun.tools.javac.main.JavaCompiler; import com.sun.tools.javac.main.OptionName; @@ -358,6 +353,7 @@ public class Delombok { options.put(OptionName.ENCODING, charset.name()); if (classpath != null) options.put(OptionName.CLASSPATH, classpath); if (sourcepath != null) options.put(OptionName.SOURCEPATH, sourcepath); + options.put("compilePolicy", "attr"); CommentCollectingScanner.Factory.preRegister(context); JavaCompiler compiler = new JavaCompiler(context); @@ -367,6 +363,9 @@ public class Delombok { List roots = new ArrayList(); Map commentsMap = new IdentityHashMap(); Map baseMap = new IdentityHashMap(); + + compiler.initProcessAnnotations(Collections.singleton(new lombok.javac.apt.Processor())); + for (File fileToParse : filesToParse) { Comments comments = new Comments(); context.put(Comments.class, comments); @@ -379,14 +378,18 @@ public class Delombok { roots.add(unit); } - if (compiler.errorCount() > 0) return false; - compiler.enterTrees(toJavacList(roots)); + if (compiler.errorCount() > 0) { + // At least one parse error. No point continuing (a real javac run doesn't either). + return false; + } + + TrackChangedAsts tca = new TrackChangedAsts(); + context.put(TrackChangedAsts.class, tca); + + JavaCompiler delegate = compiler.processAnnotations(compiler.enterTrees(toJavacList(roots))); for (JCCompilationUnit unit : roots) { - // Run one single massive transform instead of a lot of singleton calls, as this causes a heck of a lot of refilling of the enter cache. - // XXX This isn't enough - we need to call transform again after resetting everything. - boolean changed = new JavacTransformer(messager).transform(false, context, Collections.singletonList(unit)); - DelombokResult result = new DelombokResult(commentsMap.get(unit).comments, unit, force || changed); + DelombokResult result = new DelombokResult(commentsMap.get(unit).comments, unit, force || tca.changed.contains(unit)); if (verbose) feedback.printf("File: %s [%s]\n", unit.sourcefile.getName(), result.isChanged() ? "delomboked" : "unchanged"); Writer rawWriter; if (presetWriter != null) rawWriter = presetWriter; @@ -399,6 +402,7 @@ public class Delombok { writer.close(); } } + delegate.close(); return true; } @@ -411,24 +415,6 @@ public class Delombok { } } - private static final Messager messager = new Messager() { - @Override public void printMessage(Kind kind, CharSequence msg) { - System.out.printf("%s: %s\n", kind, msg); - } - - @Override public void printMessage(Kind kind, CharSequence msg, Element e) { - System.out.printf("%s: %s\n", kind, msg); - } - - @Override public void printMessage(Kind kind, CharSequence msg, Element e, AnnotationMirror a) { - System.out.printf("%s: %s\n", kind, msg); - } - - @Override public void printMessage(Kind kind, CharSequence msg, Element e, AnnotationMirror a, AnnotationValue v) { - System.out.printf("%s: %s\n", kind, msg); - } - }; - private static String canonical(File dir) { try { return dir.getCanonicalPath(); -- cgit