diff options
48 files changed, 285 insertions, 1239 deletions
@@ -130,10 +130,8 @@ the common tasks and can be called on to run the main aspects of all the sub-scr <ivy:compile destdir="build/lombok" source="1.6" target="1.6"> <src path="src/core" /> <src path="src/delombok" /> - <src path="src/netbeansAgent" /> <include name="lombok/javac/**" /> <include name="lombok/delombok/**" /> - <include name="lombok/netbeans/**" /> <classpath location="build/lombok" /> <classpath refid="build.path" /> </ivy:compile> @@ -165,7 +163,6 @@ the common tasks and can be called on to run the main aspects of all the sub-scr <ivy:eclipsegen> <srcdir dir="src/core" /> <srcdir dir="src/eclipseAgent" /> - <srcdir dir="src/netbeansAgent" /> <srcdir dir="src/installer" /> <srcdir dir="src/delombok" /> <srcdir dir="experimental/src" /> @@ -250,7 +247,6 @@ the common tasks and can be called on to run the main aspects of all the sub-scr <sources> <fileset dir="src/core" /> <fileset dir="src/eclipseAgent" /> - <fileset dir="src/netbeansAgent" /> <fileset dir="src/installer" /> <fileset dir="src/delombok" /> <fileset dir="experimental/src" /> diff --git a/src/netbeansAgent/lombok/netbeans/agent/package-info.java b/src/core/lombok/Delegate.java index a6a2f2db..0bbaed0d 100644 --- a/src/netbeansAgent/lombok/netbeans/agent/package-info.java +++ b/src/core/lombok/Delegate.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 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 @@ -19,8 +19,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +package lombok; -/** - * Contains the mechanism that instruments netbeans by being loaded as a javaagent. - */ -package lombok.netbeans.agent; +public @interface Delegate { + Class<?> value() default java.lang.Object.class; +} 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<String, AnnotationHandlerContainer<?>> annotationHandlers = new HashMap<String, AnnotationHandlerContainer<?>>(); private final Collection<JavacASTVisitor> visitorHandlers = new ArrayList<JavacASTVisitor>(); 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<T extends Annotation> { * compile session (you've handled it), or {@code false} to indicate you aren't done yet. */ boolean handle(AnnotationValues<T> 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..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"); diff --git a/src/core/lombok/javac/JavacTransformer.java b/src/core/lombok/javac/JavacTransformer.java index 5f145460..f9757894 100644 --- a/src/core/lombok/javac/JavacTransformer.java +++ b/src/core/lombok/javac/JavacTransformer.java @@ -22,7 +22,6 @@ package lombok.javac; import java.util.ArrayList; -import java.util.List; import javax.annotation.processing.Messager; @@ -32,6 +31,7 @@ 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,26 +42,46 @@ public class JavacTransformer { this.handlers = HandlerLibrary.load(messager); } - public boolean transform(Context context, Iterable<JCCompilationUnit> compilationUnits) { - List<JavacAST> asts = new ArrayList<JavacAST>(); + public void transform(boolean postResolution, Context context, java.util.List<JCCompilationUnit> compilationUnitsRaw) { + List<JCCompilationUnit> compilationUnits; + if (compilationUnitsRaw instanceof List<?>) { + compilationUnits = (List<JCCompilationUnit>)compilationUnitsRaw; + } else { + compilationUnits = List.nil(); + for (int i = compilationUnitsRaw.size() -1; i >= 0; i--) { + compilationUnits = compilationUnits.prepend(compilationUnitsRaw.get(i)); + } + } + + java.util.List<JavacAST> asts = new ArrayList<JavacAST>(); for (JCCompilationUnit unit : compilationUnits) asts.add(new JavacAST(messager, context, unit)); - handlers.skipPrintAST(); - 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.skipAllButPrintAST(); - 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) { - 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<JCCompilationUnit> changed = new HashSet<JCCompilationUnit>(); +}
\ No newline at end of file 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 037f5ba5..b5d5c81c 100644 --- a/src/core/lombok/javac/apt/Processor.java +++ b/src/core/lombok/javac/apt/Processor.java @@ -23,9 +23,11 @@ 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; +import java.util.ArrayList; import java.util.Enumeration; import java.util.IdentityHashMap; import java.util.Map; @@ -40,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; @@ -48,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; @@ -74,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(); @@ -100,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); @@ -164,15 +172,43 @@ public class Processor extends AbstractProcessor { } } + private final IdentityHashMap<JCCompilationUnit, Void> rootsAtPhase0 = new IdentityHashMap<JCCompilationUnit, Void>(); + private final IdentityHashMap<JCCompilationUnit, Void> rootsAtPhase1 = new IdentityHashMap<JCCompilationUnit, Void>(); + private int dummyCount = 0; + /** {@inheritDoc} */ @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - IdentityHashMap<JCCompilationUnit, Void> units = new IdentityHashMap<JCCompilationUnit, Void>(); + if (roundEnv.processingOver()) return false; + + if (!rootsAtPhase0.isEmpty()) { + ArrayList<JCCompilationUnit> cus = new ArrayList<JCCompilationUnit>(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(), units.keySet()); + if (!rootsAtPhase0.isEmpty()) { + ArrayList<JCCompilationUnit> cus = new ArrayList<JCCompilationUnit>(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/HandleCleanup.java b/src/core/lombok/javac/handlers/HandleCleanup.java index d72898b8..cbbdc007 100644 --- a/src/core/lombok/javac/handlers/HandleCleanup.java +++ b/src/core/lombok/javac/handlers/HandleCleanup.java @@ -156,4 +156,8 @@ public class HandleCleanup implements JavacAnnotationHandler<Cleanup> { } } } + + @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<JavacNode> 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 6767f073..682b7fe4 100644 --- a/src/core/lombok/javac/handlers/HandleData.java +++ b/src/core/lombok/javac/handlers/HandleData.java @@ -33,8 +33,6 @@ import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCClassDecl; -import com.sun.tools.javac.tree.JCTree.JCExpression; -import com.sun.tools.javac.util.List; /** * Handles the {@code lombok.Data} annotation for javac. @@ -65,4 +63,8 @@ public class HandleData implements JavacAnnotationHandler<Data> { 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 e076b295..8799f2e1 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -483,4 +483,8 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd private JCStatement returnBool(TreeMaker maker, boolean bool) { return maker.Return(maker.Literal(TypeTags.BOOLEAN, bool ? 1 : 0)); } + + @Override public boolean isResolutionBased() { + return false; + } } diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index ab4bcb60..be1bc49a 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -221,7 +221,6 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { return true; } - private JCMethodDecl createGetter(long access, JavacNode field, TreeMaker treeMaker, List<JCExpression> onMethod, boolean lazy) { JCVariableDecl fieldNode = (JCVariableDecl) field.get(); @@ -367,4 +366,8 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { private JCExpression copyType(TreeMaker treeMaker, JCVariableDecl fieldNode) { return fieldNode.type != null ? treeMaker.Type(fieldNode.type) : fieldNode.vartype; } + + @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<lombok.extern.apachecommons.Log> 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<lombok.extern.jul.Log> 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<lombok.extern.log4j.Log> 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<lombok.extern.slf4j.Log> 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<PrintAST> { 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 e6a39577..875c63dd 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -250,4 +250,8 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> { 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<SneakyThrows> 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<Synchronized> 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 64200904..82e32c06 100644 --- a/src/core/lombok/javac/handlers/HandleToString.java +++ b/src/core/lombok/javac/handlers/HandleToString.java @@ -250,4 +250,8 @@ public class HandleToString implements JavacAnnotationHandler<ToString> { } 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..bf938362 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 diff --git a/src/delombok/lombok/delombok/Delombok.java b/src/delombok/lombok/delombok/Delombok.java index 6866d97f..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<JCCompilationUnit> roots = new ArrayList<JCCompilationUnit>(); Map<JCCompilationUnit, Comments> commentsMap = new IdentityHashMap<JCCompilationUnit, Comments>(); Map<JCCompilationUnit, File> baseMap = new IdentityHashMap<JCCompilationUnit, File>(); + + compiler.initProcessAnnotations(Collections.singleton(new lombok.javac.apt.Processor())); + for (File fileToParse : filesToParse) { Comments comments = new Comments(); context.put(Comments.class, comments); @@ -379,12 +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) { - boolean changed = new JavacTransformer(messager).transform(context, Collections.singleton(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; @@ -397,6 +402,7 @@ public class Delombok { writer.close(); } } + delegate.close(); return true; } @@ -409,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(); diff --git a/src/installer/lombok/installer/netbeans/NetbeansFinder.java b/src/installer/lombok/installer/netbeans/NetbeansFinder.java deleted file mode 100644 index 28cdffac..00000000 --- a/src/installer/lombok/installer/netbeans/NetbeansFinder.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright © 2009 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 - * 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.installer.netbeans; - -import static java.util.Arrays.asList; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import lombok.installer.CorruptedIdeLocationException; -import lombok.installer.IdeFinder; -import lombok.installer.IdeLocation; - -import org.mangosdk.spi.ProviderFor; - -/** Utility class for doing various OS-specific operations related to finding Netbeans installations. */ -@ProviderFor(IdeFinder.class) -public class NetbeansFinder extends IdeFinder { - /** - * Returns a list of paths of Netbeans installations. - * - * Netbeans installations are found by checking for the existence of 'netbeans.exe' in the following locations: - * <ul> - * <li>X:\*Program Files*\*NetBeans*</li> - * <li>X:\*NetBeans*</li> - * </ul> - * - * Where 'X' is tried for all local disk drives, unless there's a problem calling fsutil, in which case only - * C: is tried. - */ - private void findNetbeansOnWindows(List<IdeLocation> locations, List<CorruptedIdeLocationException> problems) { - List<String> driveLetters = asList("C"); - try { - driveLetters = getDrivesOnWindows(); - } catch (Throwable ignore) { - ignore.printStackTrace(); - } - - //Various try/catch/ignore statements are in this for loop. Weird conditions on the disk can cause exceptions, - //such as an unformatted drive causing a NullPointerException on listFiles. Best action is almost invariably to just - //continue onwards. - for (String letter : driveLetters) { - try { - File f = new File(letter + ":\\"); - for (File dir : f.listFiles()) { - if (!dir.isDirectory()) continue; - try { - if (dir.getName().toLowerCase().contains("netbeans")) { - String netbeansLocation = findNetbeansOnWindows1(dir); - if (netbeansLocation != null) { - try { - IdeLocation newLocation = NetbeansLocationProvider.create0(netbeansLocation); - if (newLocation != null) locations.add(newLocation); - } catch (CorruptedIdeLocationException e) { - problems.add(e); - } - } - } - } catch (Exception ignore) {} - - try { - if (dir.getName().toLowerCase().contains("program files")) { - for (File dir2 : dir.listFiles()) { - if (!dir2.isDirectory()) continue; - if (dir2.getName().toLowerCase().contains("netbeans")) { - String netbeansLocation = findNetbeansOnWindows1(dir2); - if (netbeansLocation != null) { - try { - IdeLocation newLocation = NetbeansLocationProvider.create0(netbeansLocation); - if (newLocation != null) locations.add(newLocation); - } catch (CorruptedIdeLocationException e) { - problems.add(e); - } - } - } - } - } - } catch (Exception ignore) {} - } - } catch (Exception ignore) {} - } - } - - /** Checks if the provided directory contains 'netbeans.exe', and if so, returns the directory, otherwise null. */ - private String findNetbeansOnWindows1(File dir) { - if (new File(dir, "bin/netbeans.exe").isFile()) return dir.getAbsolutePath(); - return null; - } - - /** - * Calls the OS-dependent 'find Netbeans' routine. If the local OS doesn't have a routine written for it, - * null is returned. - * - * @param locations - * List of valid netbeans locations - provide an empty list; this - * method will fill it. - * @param problems - * List of netbeans locations that seem to contain half-baked - * netbeanses that can't be installed. Provide an empty list; this - * method will fill it. - */ - @Override - public void findIdes(List<IdeLocation> locations, List<CorruptedIdeLocationException> problems) { - switch (getOS()) { - case WINDOWS: - findNetbeansOnWindows(locations, problems); - break; - case MAC_OS_X: - findNetbeansOnMac(locations, problems); - break; - default: - case UNIX: - findNetbeansOnUnix(locations, problems); - break; - } - } - - /** Scans a couple of likely locations on linux. */ - private void findNetbeansOnUnix(List<IdeLocation> locations, List<CorruptedIdeLocationException> problems) { - List<String> guesses = new ArrayList<String>(); - - File d; - - d = new File("/usr/bin/netbeans"); - if (d.exists()) guesses.add(d.getPath()); - d = new File("/usr/local/bin/netbeans"); - if (d.exists()) guesses.add(d.getPath()); - d = new File(System.getProperty("user.home", "."), "bin/netbeans"); - if (d.exists()) guesses.add(d.getPath()); - - findNetbeansInSubDir("/usr/local/share", guesses); - findNetbeansInSubDir("/usr/local", guesses); - findNetbeansInSubDir("/usr/share", guesses); - findNetbeansInSubDir(System.getProperty("user.home", "."), guesses); - - for (String guess : guesses) { - try { - IdeLocation newLocation = NetbeansLocationProvider.create0(guess); - if (newLocation != null) locations.add(newLocation); - } catch (CorruptedIdeLocationException e) { - problems.add(e); - } - } - } - - private static void findNetbeansInSubDir(String dir, List<String> guesses) { - File d = new File(dir); - if (!d.isDirectory()) return; - for (File f : d.listFiles()) { - if (f.isDirectory() && f.getName().toLowerCase().contains("netbeans")) { - File possible = new File(f, "bin/netbeans"); - if (possible.exists()) guesses.add(possible.getAbsolutePath()); - } - } - } - - /** - * Scans /Applications for any folder named 'Eclipse' - */ - private static void findNetbeansOnMac(List<IdeLocation> locations, List<CorruptedIdeLocationException> problems) { - for (File dir : new File("/Applications").listFiles()) { - if (!dir.isDirectory()) continue; - if (dir.getName().toLowerCase().startsWith("netbeans") && dir.getName().toLowerCase().endsWith(".app")) { - try { - IdeLocation newLocation = NetbeansLocationProvider.create0(dir.getAbsolutePath()); - if (newLocation != null) locations.add(newLocation); - } catch (CorruptedIdeLocationException e) { - problems.add(e); - } - } - if (dir.getName().toLowerCase().contains("netbeans")) { - for (File dir2 : dir.listFiles()) { - if (!dir2.isDirectory()) continue; - if (dir2.getName().toLowerCase().startsWith("netbeans") && dir2.getName().toLowerCase().endsWith(".app")) { - try { - IdeLocation newLocation = NetbeansLocationProvider.create0(dir2.getAbsolutePath()); - if (newLocation != null) locations.add(newLocation); - } catch (CorruptedIdeLocationException e) { - problems.add(e); - } - } - } - } - } - } -} diff --git a/src/installer/lombok/installer/netbeans/NetbeansLocation.java b/src/installer/lombok/installer/netbeans/NetbeansLocation.java deleted file mode 100644 index 6db57207..00000000 --- a/src/installer/lombok/installer/netbeans/NetbeansLocation.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * 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 - * 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.installer.netbeans; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import lombok.installer.CorruptedIdeLocationException; -import lombok.installer.IdeFinder; -import lombok.installer.IdeLocation; -import lombok.installer.InstallException; -import lombok.installer.Installer; -import lombok.installer.UninstallException; - -public class NetbeansLocation extends IdeLocation { - private final String name; - private final File netbeansConfPath; - private final String version; - private final int versionFirst, versionSecond; - private final boolean hasLombok; - - private static final String OS_NEWLINE = IdeFinder.getOS().getLineEnding(); - - NetbeansLocation(String nameOfLocation, File pathToNetbeansConf) throws CorruptedIdeLocationException { - this.name = nameOfLocation; - this.netbeansConfPath = pathToNetbeansConf; - try { - this.hasLombok = checkForLombok(netbeansConfPath); - } catch (IOException e) { - throw new CorruptedIdeLocationException( - "I can't read the configuration file of the Netbeans installed at " + name + "\n" + - "You may need to run this installer with root privileges if you want to modify that Netbeans.", "netbeans", e); - } - this.version = findNetbeansVersion(netbeansConfPath); - int first, second; - String[] vs = version.split("\\."); - try { - first = Integer.parseInt(vs[0]); - } catch (Exception e) { - first = 0; - } - try { - second = Integer.parseInt(vs[1]); - } catch (Exception e) { - second = 0; - } - this.versionFirst = first; - this.versionSecond = second; - } - - public boolean versionIsPre68() { - return versionFirst < 6 || (versionFirst == 6 && versionSecond < 8); - } - - public boolean versionIs68() { - return versionFirst == 6 && versionSecond == 8; - } - - public boolean versionIsPost68() { - return versionFirst > 6 || (versionFirst == 6 && versionSecond > 8); - } - - @Override public int hashCode() { - return netbeansConfPath.hashCode(); - } - - @Override public boolean equals(Object o) { - if (!(o instanceof NetbeansLocation)) return false; - return ((NetbeansLocation)o).netbeansConfPath.equals(netbeansConfPath); - } - - /** - * Returns the name of this location; generally the path to the netbeans executable. - */ - @Override - public String getName() { - return name; - } - - /** - * @return true if the Netbeans installation has been instrumented with lombok. - */ - @Override - public boolean hasLombok() { - return hasLombok; - } - - private final String ID_CHARS = "(?:\\\\.|[^\"\\\\])*"; - private final Pattern JAVA_AGENT_LINE_MATCHER = Pattern.compile( - "^\\s*netbeans_default_options\\s*=\\s*\"\\s*" + ID_CHARS + "(?<=[ \"])(-J-javaagent:\\\\\".*lombok.*\\.jar\\\\\")(?=[ \"])" + ID_CHARS +"\\s*\"\\s*(?:#.*)?$", Pattern.CASE_INSENSITIVE); - - private final Pattern OPTIONS_LINE_MATCHER = Pattern.compile( - "^\\s*netbeans_default_options\\s*=\\s*\"\\s*" + ID_CHARS + "\\s*(\")\\s*(?:#.*)?$", Pattern.CASE_INSENSITIVE); - - private String findNetbeansVersion(File iniFile) { - String forcedVersion = System.getProperty("force.netbeans.version", null); - if (forcedVersion != null) return forcedVersion; - - try { - for (File child : iniFile.getParentFile().getParentFile().listFiles()) { - if (!child.isDirectory()) continue; - String name = child.getName(); - if (name == null || !name.startsWith("nb")) continue; - String version = name.substring(2); - File versionFile = new File(child, "VERSION.txt"); - if (versionFile.exists() && versionFile.canRead() && !versionFile.isDirectory()) { - try { - version = readVersionFile(versionFile); - } catch (IOException e) { - // Intentional Fallthrough - } - } - if (version != null && version.length() > 0) { - return version; - } - } - } catch (NullPointerException e) { - // Intentional Fallthrough - } - - return "UNKNOWN"; - } - - private static String readVersionFile(File file) throws IOException { - FileInputStream fis = new FileInputStream(file); - StringBuilder version = new StringBuilder(); - try { - BufferedReader br = new BufferedReader(new InputStreamReader(fis, "UTF-8")); - for (String line = br.readLine(); line != null; line = br.readLine()) { - if (line.startsWith("#")) continue; - if (version.length() > 0) version.append(" "); - version.append(line); - } - return version.toString(); - } finally { - fis.close(); - } - } - - private boolean checkForLombok(File iniFile) throws IOException { - if (!iniFile.exists()) return false; - FileInputStream fis = new FileInputStream(iniFile); - try { - BufferedReader br = new BufferedReader(new InputStreamReader(fis)); - String line; - while ((line = br.readLine()) != null) { - if (JAVA_AGENT_LINE_MATCHER.matcher(line.trim()).matches()) return true; - } - - return false; - } finally { - fis.close(); - } - } - - /** - * Uninstalls lombok from this location. - * It's a no-op if lombok wasn't there in the first place, - * and it will remove a half-succeeded lombok installation as well. - * - * @throws UninstallException - * If there's an obvious I/O problem that is preventing - * installation. bugs in the uninstall code will probably throw - * other exceptions; this is intentional. - */ - @Override - public void uninstall() throws UninstallException { - final List<File> lombokJarsForWhichCantDeleteSelf = new ArrayList<File>(); - File dir = netbeansConfPath.getParentFile(); - - StringBuilder newContents = new StringBuilder(); - if (netbeansConfPath.exists()) { - try { - FileInputStream fis = new FileInputStream(netbeansConfPath); - try { - BufferedReader br = new BufferedReader(new InputStreamReader(fis)); - String line; - while ((line = br.readLine()) != null) { - Matcher m = JAVA_AGENT_LINE_MATCHER.matcher(line); - if (m.matches()) { - newContents.append(line.substring(0, m.start(1)) + line.substring(m.end(1))); - } else { - newContents.append(line); - } - newContents.append(OS_NEWLINE); - } - } finally { - fis.close(); - } - - FileOutputStream fos = new FileOutputStream(netbeansConfPath); - try { - fos.write(newContents.toString().getBytes()); - } finally { - fos.close(); - } - } catch (IOException e) { - throw new UninstallException("Cannot uninstall lombok from " + name + generateWriteErrorMessage(), e); - } - } - - File lombokJar = new File(dir, "lombok.jar"); - if (lombokJar.exists()) { - if (!lombokJar.delete()) { - if (IdeFinder.getOS() == IdeFinder.OS.WINDOWS && Installer.isSelf(lombokJar.getAbsolutePath())) { - lombokJarsForWhichCantDeleteSelf.add(lombokJar); - } else { - throw new UninstallException( - "Can't delete " + lombokJar.getAbsolutePath() + generateWriteErrorMessage(), null); - } - } - } - - if (!lombokJarsForWhichCantDeleteSelf.isEmpty()) { - throw new UninstallException(true, - "lombok.jar cannot delete itself on windows.\nHowever, lombok has been uncoupled from your netbeans.\n" + - "You can safely delete this jar file. You can find it at:\n" + - lombokJarsForWhichCantDeleteSelf.get(0).getAbsolutePath(), null); - } - } - - private static String generateWriteErrorMessage() { - String osSpecificError; - - switch (IdeFinder.getOS()) { - default: - case MAC_OS_X: - case UNIX: - osSpecificError = ":\nStart terminal, go to the directory with lombok.jar, and run: sudo java -jar lombok.jar"; - break; - case WINDOWS: - osSpecificError = ":\nStart a new cmd (dos box) with admin privileges, go to the directory with lombok.jar, and run: java -jar lombok.jar"; - break; - } - - return ", probably because this installer does not have the access rights.\n" + - "Try re-running the installer with administrative privileges" + osSpecificError; - } - - /** - * Install lombok into the Netbeans at this location. - * If lombok is already there, it is overwritten neatly (upgrade mode). - * - * @throws InstallException - * If there's an obvious I/O problem that is preventing - * installation. bugs in the install code will probably throw - * other exceptions; this is intentional. - */ - @Override - public String install() throws InstallException { - if ("UNKNOWN".equals(version)) { - throw new InstallException(String.format( - "Can't determine version of Netbeans installed at:\n%s\n\n" + - "Your Netbeans version determines what this installer does:\n" + - "Pre 6.8: Lombok is not compatible with netbeans pre 6.8, and thus won't install.\n" + - "6.8: Lombok will install itself into Netbeans.\n" + - "6.9 and later: NetBeans supports lombok natively. This installer will explain how to enable it.\n\n" + - "If you know your netbeans version, you can force this by starting the installer with:\n" + - "java -Dforce.netbeans.version=6.8 -jar lombok.jar", this.getName()), null); - } - - if (versionIsPre68()) { - throw new InstallException(String.format( - "Lombok is not compatible with Netbeans versions prior to 6.8.\n" + - "Therefore, lombok will not be installed at:\n%s\nbecause it is version: %s", - this.getName(), version), null); - } - if (versionIsPost68()) { - try { - uninstall(); - } catch (Exception e) { - // Well, we tried. Lombok on 6.9 doesn't do anything, so we'll leave it then. - } - - throw new InstallException(true, String.format( - "Starting with NetBeans 6.9, lombok is natively supported and does not need to be installed at:\n%s\n\n" + - "To use lombok.jar in your netbeans project:\n" + - "1. Add lombok.jar to your project (Go to Project Properties, 'Libraries' page, and add lombok.jar in the 'Compile' tab).\n" + - "2. Enable Annotation Processors (Go to Project Properties, 'Build/Compiling' page, and check 'Enable Annotation Processing in Editor').\n" + - "\n" + - "NB: In the first release of NetBeans 6.9, due to a netbeans bug, maven-based projects don't run annotation processors. This \n" + - "issue should be fixed by the great folks at NetBeans soon.", this.getName()), null); - } - - boolean installSucceeded = false; - StringBuilder newContents = new StringBuilder(); - - File lombokJar = new File(netbeansConfPath.getParentFile(), "lombok.jar"); - - /* No need to copy lombok.jar to itself, obviously. On windows this would generate an error so we check for this. */ - if (!Installer.isSelf(lombokJar.getAbsolutePath())) { - File ourJar = findOurJar(); - byte[] b = new byte[524288]; - boolean readSucceeded = true; - try { - FileOutputStream out = new FileOutputStream(lombokJar); - try { - readSucceeded = false; - InputStream in = new FileInputStream(ourJar); - try { - while (true) { - int r = in.read(b); - if (r == -1) break; - if (r > 0) readSucceeded = true; - out.write(b, 0, r); - } - } finally { - in.close(); - } - } finally { - out.close(); - } - } catch (IOException e) { - try { - lombokJar.delete(); - } catch (Throwable ignore) { /* Nothing we can do about that. */ } - if (!readSucceeded) throw new InstallException( - "I can't read my own jar file. I think you've found a bug in this installer!\nI suggest you restart it " + - "and use the 'what do I do' link, to manually install lombok. Also, tell us about this at:\n" + - "http://groups.google.com/group/project-lombok - Thanks!", e); - throw new InstallException("I can't write to your Netbeans directory at " + name + generateWriteErrorMessage(), e); - } - } - - try { - FileInputStream fis = new FileInputStream(netbeansConfPath); - try { - BufferedReader br = new BufferedReader(new InputStreamReader(fis)); - String line; - while ((line = br.readLine()) != null) { - Matcher m = JAVA_AGENT_LINE_MATCHER.matcher(line); - if (m.matches()) { - newContents.append(line.substring(0, m.start(1))); - newContents.append("-J-javaagent:\\\"" + canonical(lombokJar) + "\\\""); - newContents.append(line.substring(m.end(1))); - newContents.append(OS_NEWLINE); - continue; - } - - m = OPTIONS_LINE_MATCHER.matcher(line); - if (m.matches()) { - newContents.append(line.substring(0, m.start(1))); - newContents.append(" ").append("-J-javaagent:\\\"" + canonical(lombokJar) +"\\\"\""); - newContents.append(line.substring(m.end(1))).append(OS_NEWLINE); - continue; - } - - newContents.append(line).append(OS_NEWLINE); - } - } finally { - fis.close(); - } - - FileOutputStream fos = new FileOutputStream(netbeansConfPath); - try { - fos.write(newContents.toString().getBytes()); - } finally { - fos.close(); - } - installSucceeded = true; - } catch (IOException e) { - throw new InstallException("Cannot install lombok at " + name + generateWriteErrorMessage(), e); - } finally { - if (!installSucceeded) try { - lombokJar.delete(); - } catch (Throwable ignore) {} - } - - if (!installSucceeded) { - throw new InstallException("I can't find the netbeans.conf file. Is this a real Netbeans installation?", null); - } - - return "If you start netbeans with custom parameters, you'll need to add:<br>" + - "<code>-J-javaagent:\\\"" + canonical(lombokJar) + "\\\"</code><br>" + - "as parameter as well."; - } - - @Override public URL getIdeIcon() { - return NetbeansLocation.class.getResource("netbeans.png"); - } -} diff --git a/src/installer/lombok/installer/netbeans/NetbeansLocationProvider.java b/src/installer/lombok/installer/netbeans/NetbeansLocationProvider.java deleted file mode 100644 index 68a00756..00000000 --- a/src/installer/lombok/installer/netbeans/NetbeansLocationProvider.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright © 2009 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 - * 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.installer.netbeans; - -import static lombok.installer.IdeLocation.canonical; - -import java.io.File; -import java.io.IOException; -import java.util.regex.Pattern; - -import lombok.installer.CorruptedIdeLocationException; -import lombok.installer.IdeLocation; -import lombok.installer.IdeLocationProvider; -import lombok.installer.IdeFinder.OS; - -import org.mangosdk.spi.ProviderFor; - -@ProviderFor(IdeLocationProvider.class) -public class NetbeansLocationProvider implements IdeLocationProvider { - - @Override public IdeLocation create(String path) throws CorruptedIdeLocationException { - return create0(path); - } - - /** - * Create a new NetbeansLocation by pointing at either the directory containing the executable, or the executable itself, - * or a netbeans.conf file. - * - * @throws NotAnIdeLocationException - * If this isn't an Eclipse executable or a directory with an - * Eclipse executable. - */ - static NetbeansLocation create0(String path) throws CorruptedIdeLocationException { - if (path == null) throw new NullPointerException("path"); - File p = new File(path); - - if (!p.exists()) return null; - if (p.isDirectory()) { - String name = p.getName().toLowerCase(); - if (name.endsWith(".app") && name.startsWith("netbeans")) { - File conf = new File(p, "Contents/Resources/NetBeans/etc/netbeans.conf"); - if (conf.exists()) return new NetbeansLocation(path, conf); - } - - File f = new File(p, "bin/netbeans"); - if (f.isFile()) return findNetbeansConfFromExe(f, 0); - f = new File(p, "bin/netbeans.exe"); - if (f.isFile()) return findNetbeansConfFromExe(f, 0); - f = new File(p, "etc/netbeans.conf"); - if (f.isFile()) return new NetbeansLocation(canonical(f.getParentFile().getParentFile()), f); - } - - if (p.isFile()) { - if (p.getName().equalsIgnoreCase("netbeans.conf")) { - return new NetbeansLocation(canonical(p.getParentFile().getParentFile()), p); - } - - if (p.getName().equalsIgnoreCase("netbeans") || p.getName().equalsIgnoreCase("netbeans.exe")) { - return findNetbeansConfFromExe(p, 0); - } - } - - return null; - } - - private static NetbeansLocation findNetbeansConfFromExe(File exePath, int loopCounter) throws CorruptedIdeLocationException { - /* Try looking for netbeans.conf as etc/netbeans.conf */ { - File conf = new File(exePath.getParentFile(), "etc/netbeans.conf"); - if (conf.isFile()) return new NetbeansLocation(canonical(exePath), conf); - } - - /* Try looking for netbeans.conf as ../etc/netbeans.conf */ { - File conf = new File(exePath.getParentFile().getParentFile(), "etc/netbeans.conf"); - if (conf.isFile()) return new NetbeansLocation(canonical(exePath), conf); - } - - /* If executable is a soft link, follow it and retry. */ { - if (loopCounter < 50) { - try { - String oPath = exePath.getAbsolutePath(); - String nPath = exePath.getCanonicalPath(); - if (!oPath.equals(nPath)) try { - return findNetbeansConfFromExe(new File(nPath), loopCounter + 1); - } catch (CorruptedIdeLocationException ignore) { - // Unlinking didn't help find a netbeans, so continue. - } - } catch (IOException ignore) { /* okay, that didn't work, assume it isn't a soft link then. */ } - } - } - - /* If we get this far, we lose. */ - return null; - } - - @Override public Pattern getLocationSelectors(OS os) { - switch (os) { - case MAC_OS_X: - return Pattern.compile("^(netbeans|netbeans\\.conf|NetBeans.*\\.app)$", Pattern.CASE_INSENSITIVE); - case WINDOWS: - return Pattern.compile("^(netbeans\\.exe|netbeans\\.conf)$", Pattern.CASE_INSENSITIVE); - default: - case UNIX: - return Pattern.compile("^(netbeans|netbeans\\.conf)$", Pattern.CASE_INSENSITIVE); - } - } -} diff --git a/src/installer/lombok/installer/netbeans/netbeans.png b/src/installer/lombok/installer/netbeans/netbeans.png Binary files differdeleted file mode 100644 index 43fe63cc..00000000 --- a/src/installer/lombok/installer/netbeans/netbeans.png +++ /dev/null diff --git a/src/netbeansAgent/lombok/netbeans/agent/NetbeansEntryPoint.java b/src/netbeansAgent/lombok/netbeans/agent/NetbeansEntryPoint.java deleted file mode 100644 index 963b70b5..00000000 --- a/src/netbeansAgent/lombok/netbeans/agent/NetbeansEntryPoint.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright © 2009 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 - * 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.netbeans.agent; - -import java.util.Collections; - -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.Diagnostic.Kind; - -import lombok.javac.JavacTransformer; - -import com.sun.source.util.TaskEvent; -import com.sun.source.util.TaskListener; -import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; -import com.sun.tools.javac.util.Context; - -public class NetbeansEntryPoint implements TaskListener { - public class DummyMessager implements Messager { - @Override public void printMessage(Kind kind, CharSequence msg) { - System.err.printf("%s: %s\n", kind, msg); - } - - @Override public void printMessage(Kind kind, CharSequence msg, Element e) { - printMessage(kind, msg); - } - - @Override public void printMessage(Kind kind, CharSequence msg, Element e, AnnotationMirror a) { - printMessage(kind, msg); - } - - @Override public void printMessage(Kind kind, CharSequence msg, Element e, AnnotationMirror a, AnnotationValue v) { - printMessage(kind, msg); - } - } - - private final Context context; - - public NetbeansEntryPoint(Context context) { - this.context = context; - } - - @Override public void started(TaskEvent event) { - //we run at the end, so all the action is in #finished. - } - - @Override public void finished(TaskEvent event) { - 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)); - } - } -} diff --git a/src/netbeansAgent/lombok/netbeans/agent/NetbeansPatcher.java b/src/netbeansAgent/lombok/netbeans/agent/NetbeansPatcher.java deleted file mode 100644 index ffe491ae..00000000 --- a/src/netbeansAgent/lombok/netbeans/agent/NetbeansPatcher.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright © 2009 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 - * 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.netbeans.agent; - -import java.lang.instrument.Instrumentation; - -import lombok.core.Agent; -import lombok.patcher.Hook; -import lombok.patcher.MethodTarget; -import lombok.patcher.ScriptManager; -import lombok.patcher.StackRequest; -import lombok.patcher.scripts.ScriptBuilder; - -/** - * This is a java-agent that patches some of netbeans's classes so that lombok is initialized as Javac TaskListener, - * allowing us to change AST nodes anytime netbeans parses source code. It also fixes some of the places in netbeans that - * can't deal with generated code. - * - * The hard work on figuring out where to patch has been done by Jan Lahoda (jlahoda@netbeans.org) - */ -public class NetbeansPatcher extends Agent { - @Override - public void runAgent(String agentArgs, Instrumentation instrumentation, boolean injected) throws Exception { - registerPatchScripts(instrumentation, injected); - } - - private static void registerPatchScripts(Instrumentation instrumentation, boolean reloadExistingClasses) { - ScriptManager sm = new ScriptManager(); - sm.registerTransformer(instrumentation); - - patchNetbeansClassLoader(sm); - patchNetbeansJavac(sm); - patchNetbeansMissingPositionAwareness(sm); - - if (reloadExistingClasses) sm.reloadClasses(instrumentation); - } - - private static void patchNetbeansClassLoader(ScriptManager sm) { - sm.addScript(ScriptBuilder.exitEarly() - .transplant().request(StackRequest.PARAM1, StackRequest.PARAM2) - .target(new MethodTarget("org.netbeans.StandardModule$OneModuleClassLoader", "<init>")) - .decisionMethod(new Hook("lombok.netbeans.agent.PatchFixes", "addSelfToClassLoader", "void", "org.netbeans.Module", "java.util.List")) - .build()); - sm.addScript(ScriptBuilder.exitEarly() - .transplant() - .request(StackRequest.THIS, StackRequest.PARAM1) - .target(new MethodTarget("org.netbeans.ProxyClassLoader", "getResource")) - .decisionMethod(new Hook("lombok.netbeans.agent.PatchFixes", "getResource_decision", "boolean", "java.lang.ClassLoader", "java.lang.String")) - .valueMethod(new Hook("lombok.netbeans.agent.PatchFixes", "getResource_value", "java.net.URL", "java.lang.ClassLoader", "java.lang.String")) - .build()); - sm.addScript(ScriptBuilder.exitEarly() - .transplant() - .request(StackRequest.THIS, StackRequest.PARAM1) - .target(new MethodTarget("org.netbeans.ProxyClassLoader", "getResources")) - .decisionMethod(new Hook("lombok.netbeans.agent.PatchFixes", "getResources_decision", "boolean", "java.lang.ClassLoader", "java.lang.String")) - .valueMethod(new Hook("lombok.netbeans.agent.PatchFixes", "getResources_value", "java.util.Enumeration", "java.lang.ClassLoader", "java.lang.String")) - .build()); - sm.addScript(ScriptBuilder.exitEarly() - .transplant() - .target(new MethodTarget("org.netbeans.ProxyClassLoader", "loadClass")) - .request(StackRequest.THIS, StackRequest.PARAM1) - .decisionMethod(new Hook("lombok.netbeans.agent.PatchFixes", "loadClass_decision", "boolean", "java.lang.ClassLoader", "java.lang.String")) - .valueMethod(new Hook("lombok.netbeans.agent.PatchFixes", "loadClass_value", "java.lang.Class", "java.lang.ClassLoader", "java.lang.String")) - .build()); - } - - private static void patchNetbeansJavac(ScriptManager sm) { - sm.addScript(ScriptBuilder.wrapReturnValue() - .request(StackRequest.THIS, StackRequest.PARAM1) - .transplant() - .target(new MethodTarget("com.sun.tools.javac.api.JavacTaskImpl", "setTaskListener")) - .wrapMethod(new Hook("lombok.netbeans.agent.PatchFixes", "fixContentOnSetTaskListener", "void", - "com.sun.tools.javac.api.JavacTaskImpl", "com.sun.source.util.TaskListener")) - .build()); - - sm.addScript(ScriptBuilder.wrapReturnValue() - .request(StackRequest.RETURN_VALUE, StackRequest.PARAM1) - .transplant() - .target(new MethodTarget("org.netbeans.modules.java.source.parsing.JavacParser", "createJavacTask", - "com.sun.tools.javac.api.JavacTaskImpl", - "org.netbeans.api.java.source.ClasspathInfo", "javax.tools.DiagnosticListener", "java.lang.String", "boolean", - "com.sun.tools.javac.api.ClassNamesForFileOraculum", "com.sun.tools.javac.util.CancelService")) - .wrapMethod(new Hook("lombok.netbeans.agent.PatchFixes", "addTaskListenerWhenCallingJavac", "void", - "com.sun.tools.javac.api.JavacTaskImpl", "org.netbeans.api.java.source.ClasspathInfo")) - .build()); - } - - private static void patchNetbeansMissingPositionAwareness(ScriptManager sm) { - sm.addScript(ScriptBuilder.replaceMethodCall() - .target(new MethodTarget("org.netbeans.modules.java.editor.overridden.ComputeAnnotations", - "createAnnotations")) - .methodToReplace(new Hook("com.sun.source.util.Trees", "getTree", "com.sun.source.tree.Tree", - "javax.lang.model.element.Element")) - .replacementMethod(new Hook("lombok.netbeans.agent.PatchFixes", "returnNullForGeneratedNode", "com.sun.source.tree.Tree", - "com.sun.source.util.Trees", "javax.lang.model.element.Element", "java.lang.Object")) - .requestExtra(StackRequest.PARAM1).transplant() - .build()); - - sm.addScript(ScriptBuilder.replaceMethodCall() - .target(new MethodTarget("org.netbeans.modules.java.source.parsing.FindMethodRegionsVisitor", - "visitMethod")) - .methodToReplace(new Hook("com.sun.source.util.SourcePositions", "getEndPosition", "long", - "com.sun.source.tree.CompilationUnitTree", "com.sun.source.tree.Tree")) - .replacementMethod(new Hook("lombok.netbeans.agent.PatchFixes", "returnMinus1ForGeneratedNode", "long", - "com.sun.source.util.SourcePositions", "com.sun.source.tree.CompilationUnitTree", "com.sun.source.tree.Tree")) - .transplant().build()); - - sm.addScript(ScriptBuilder.wrapMethodCall() - .target(new MethodTarget("org.netbeans.modules.java.source.save.CasualDiff", "filterHidden")) - .methodToWrap(new Hook("java.lang.Iterable", "iterator", "java.util.Iterator")) - .wrapMethod(new Hook("lombok.netbeans.agent.PatchFixes", "filterGenerated", "java.util.Iterator", - "java.util.Iterator")) - .transplant().build()); - } -} diff --git a/src/netbeansAgent/lombok/netbeans/agent/PatchFixes.java b/src/netbeansAgent/lombok/netbeans/agent/PatchFixes.java deleted file mode 100644 index f45a4736..00000000 --- a/src/netbeansAgent/lombok/netbeans/agent/PatchFixes.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright © 2009 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 - * 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.netbeans.agent; - -import java.io.File; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.URL; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; - -import javax.lang.model.element.Element; - -import lombok.Lombok; -import lombok.patcher.inject.LiveInjector; - -import org.netbeans.Module; -import org.netbeans.ProxyClassLoader; -import org.netbeans.api.java.source.ClasspathInfo; - -import com.sun.source.tree.CompilationUnitTree; -import com.sun.source.tree.Tree; -import com.sun.source.util.SourcePositions; -import com.sun.source.util.TaskListener; -import com.sun.source.util.Trees; -import com.sun.tools.javac.api.JavacTaskImpl; -import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.util.Context; - -// A lot of the footwork on the netbeans support has been done by Jan Lahoda, who is awesome. (jlahoda@netbeans.org) -// This footwork was converted into a patch script form by me (rzwitserloot). See: -// http://code.google.com/p/projectlombok/issues/detail?id=20#c3 -public class PatchFixes { - public static boolean loadClass_decision(ClassLoader loader, String name) throws Exception { - return name.startsWith("lombok."); - } - - public static Class<?> loadClass_value(ClassLoader loader, String name) throws Exception { - int last = name.lastIndexOf('.'); - String pkg = (last >= 0) ? name.substring(0, last) : ""; - Method m = ProxyClassLoader.class.getDeclaredMethod("selfLoadClass", String.class, String.class); - m.setAccessible(true); - return (Class<?>)m.invoke(loader, pkg, name); - } - - public static boolean getResource_decision(ClassLoader loader, String name) throws Exception { - return name.startsWith("META-INF/services/lombok."); - } - - public static URL getResource_value(ClassLoader loader, String name) throws Exception { - Method m = ProxyClassLoader.class.getDeclaredMethod("findResource", String.class); - m.setAccessible(true); - return (URL) m.invoke(loader, name); - } - - public static boolean getResources_decision(ClassLoader loader, String name) throws Exception { - return name.startsWith("META-INF/services/lombok."); - } - - public static Enumeration<?> getResources_value(ClassLoader loader, String name) throws Exception { - Method m = ProxyClassLoader.class.getDeclaredMethod("findResources", String.class); - m.setAccessible(true); - return (Enumeration<?>) m.invoke(loader, name); - } - - public static void addSelfToClassLoader(Module module, List<File> classPath) { - if (module.getJarFile().getName().equals("org-netbeans-libs-javacimpl.jar")) { - String lombokJarLoc = LiveInjector.findPathJar(Lombok.class); - classPath.add(new File(lombokJarLoc)); - } - } - - public static void fixContentOnSetTaskListener(JavacTaskImpl that, TaskListener taskListener) throws Throwable { - Context context = that.getContext(); - - if (context.get(TaskListener.class) != null) - context.put(TaskListener.class, (TaskListener)null); - if (taskListener != null) { - try { - Method m = JavacTaskImpl.class.getDeclaredMethod("wrap", TaskListener.class); - try { - m.setAccessible(true); - } catch (SecurityException ignore) {} - TaskListener w = (TaskListener)m.invoke(that, taskListener); - context.put(TaskListener.class, w); - } catch (InvocationTargetException e) { - throw e.getCause(); - } - } - } - - public static Tree returnNullForGeneratedNode(Trees trees, Element element, Object o) throws Throwable { - try { - Tree tree = trees.getTree(element); - if (tree == null) return null; - CompilationUnitTree unit = (CompilationUnitTree) o.getClass().getMethod("getCompilationUnit").invoke(o); - int startPos = (int) trees.getSourcePositions().getStartPosition(unit, tree); - if (startPos == -1) return null; - return tree; - } catch (InvocationTargetException e) { - throw e.getCause(); - } - } - - public static long returnMinus1ForGeneratedNode(SourcePositions that, CompilationUnitTree cu, Tree tree) { - int start = (int) that.getStartPosition(cu, tree); - if (start < 0) return -1; - return that.getEndPosition(cu, tree); - } - - public static void addTaskListenerWhenCallingJavac(JavacTaskImpl task, - ClasspathInfo cpInfo) throws Exception { - if (task == null) return; - Class<?> entryPoint = JavacTaskImpl.class.getClassLoader().loadClass("lombok.netbeans.agent.NetbeansEntryPoint"); - if (entryPoint == null) { - /* TODO tell the user that lombok is not working. loadClass is not supposed to return null, but netbeans' loader does anyway. */ - System.err.println("[LOMBOK] ClassLoader not patched correctly."); - } else { - task.setTaskListener((TaskListener) entryPoint.getConstructor(Context.class).newInstance(task.getContext())); - } - } - - public static Iterator<JCTree> filterGenerated(final Iterator<JCTree> it) { - return new Iterator<JCTree>() { - private JCTree next; - private boolean hasNext; - - { - calc(); - } - - private void calc() { - while (it.hasNext()) { - JCTree n = it.next(); - if (n.pos != -1) { - hasNext = true; - next = n; - return; - } - } - - hasNext = false; - next = null; - } - - @Override public boolean hasNext() { - return hasNext; - } - - @Override public JCTree next() { - if (!hasNext) throw new NoSuchElementException(); - JCTree n = next; - calc(); - return n; - } - - @Override public void remove() { - throw new UnsupportedOperationException(); - } - }; - } -} diff --git a/test/core/src/lombok/AbstractRunTests.java b/test/core/src/lombok/AbstractRunTests.java index 7d5992be..7bf2f452 100644 --- a/test/core/src/lombok/AbstractRunTests.java +++ b/test/core/src/lombok/AbstractRunTests.java @@ -28,6 +28,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; +import java.io.StringReader; import java.io.StringWriter; import java.util.ArrayList; import java.util.List; @@ -35,17 +36,26 @@ import java.util.List; public abstract class AbstractRunTests { protected static final String LINE_SEPARATOR = System.getProperty("line.separator"); - public void compareFile(DirectoryRunner.TestParams params, File file) throws Throwable { + public boolean compareFile(DirectoryRunner.TestParams params, File file) throws Throwable { StringBuilder messages = new StringBuilder(); StringWriter writer = new StringWriter(); transformCode(messages, writer, file); + String expectedFile = readFile(params.getAfterDirectory(), file, false); + String expectedMessages = readFile(params.getMessagesDirectory(), file, true); + + StringReader r = new StringReader(expectedFile); + BufferedReader br = new BufferedReader(r); + if ("//ignore".equals(br.readLine())) return false; + compare( file.getName(), - readFile(params.getAfterDirectory(), file, false), + expectedFile, writer.toString(), - readFile(params.getMessagesDirectory(), file, true), + expectedMessages, messages.toString(), params.printErrors()); + + return true; } protected abstract void transformCode(StringBuilder message, StringWriter result, File file) throws Throwable; diff --git a/test/core/src/lombok/DirectoryRunner.java b/test/core/src/lombok/DirectoryRunner.java index 89fe6ab0..f84198f8 100644 --- a/test/core/src/lombok/DirectoryRunner.java +++ b/test/core/src/lombok/DirectoryRunner.java @@ -118,15 +118,13 @@ public class DirectoryRunner extends Runner { } switch (params.getCompiler()) { case DELOMBOK: - new RunTestsViaDelombok().compareFile(params, file); - break; + return new RunTestsViaDelombok().compareFile(params, file); case ECJ: - new RunTestsViaEcj().compareFile(params, file); - break; + return new RunTestsViaEcj().compareFile(params, file); + default: case JAVAC: throw new UnsupportedOperationException(); } - return true; } private boolean mustIgnore(File file) throws FileNotFoundException, IOException { diff --git a/test/core/src/lombok/RunTestsViaDelombok.java b/test/core/src/lombok/RunTestsViaDelombok.java index 59a0ee89..bcaa66a2 100644 --- a/test/core/src/lombok/RunTestsViaDelombok.java +++ b/test/core/src/lombok/RunTestsViaDelombok.java @@ -45,7 +45,9 @@ public class RunTestsViaDelombok extends AbstractRunTests { delombok.setDiagnosticsListener(new DiagnosticListener<JavaFileObject>() { @Override public void report(Diagnostic<? extends JavaFileObject> d) { String msg = d.getMessage(Locale.ENGLISH); - Matcher m = Pattern.compile("^" + Pattern.quote(file.getAbsolutePath()) + "\\s*:\\s*\\d+\\s*:\\s*(?:warning:\\s*)?(.*)$").matcher(msg); + Matcher m = Pattern.compile( + "^" + Pattern.quote(file.getAbsolutePath()) + + "\\s*:\\s*\\d+\\s*:\\s*(?:warning:\\s*)?(.*)$", Pattern.DOTALL).matcher(msg); if (m.matches()) msg = m.group(1); messages.append(String.format("%d:%d %s %s\n", d.getLineNumber(), d.getColumnNumber(), d.getKind(), msg)); } diff --git a/test/pretty/resource/after/Annotation.java b/test/pretty/resource/after/Annotation.java index 06fe62b3..6b3b35b8 100644 --- a/test/pretty/resource/after/Annotation.java +++ b/test/pretty/resource/after/Annotation.java @@ -6,7 +6,7 @@ class Annotation { } public void method(@SuppressWarnings("unused") int x) { } - public void method2(@SuppressWarnings(value = {"unused"}) int y) { + public void method2(@SuppressWarnings({"unused"}) int y) { } public void method3(@SuppressWarnings({"unused", "unchecked"}) int z) { } diff --git a/test/pretty/resource/before/Annotation.java b/test/pretty/resource/before/Annotation.java index 24868acd..edd1a5e7 100644 --- a/test/pretty/resource/before/Annotation.java +++ b/test/pretty/resource/before/Annotation.java @@ -1,4 +1,3 @@ -//ignore @SuppressWarnings("all") class Annotation { @Override diff --git a/test/transform/resource/after-delombok/ValErrors.java b/test/transform/resource/after-delombok/ValErrors.java index 5ac785ab..770a7e95 100644 --- a/test/transform/resource/after-delombok/ValErrors.java +++ b/test/transform/resource/after-delombok/ValErrors.java @@ -1,8 +1,8 @@ public class ValErrors { - public void nullType() { - final val a = null; - } public void unresolvableExpression() { - final val c = d; + final java.lang.Object c = d; + } + public void arrayInitializer() { + val e = {"foo", "bar"}; } }
\ No newline at end of file diff --git a/test/transform/resource/after-delombok/ValWeirdTypes.java b/test/transform/resource/after-delombok/ValWeirdTypes.java index 66212906..34beb80b 100644 --- a/test/transform/resource/after-delombok/ValWeirdTypes.java +++ b/test/transform/resource/after-delombok/ValWeirdTypes.java @@ -44,4 +44,14 @@ public class ValWeirdTypes<Z> { final java.util.AbstractList<java.lang.String> d = c ? a : b; java.util.RandomAccess confirm = c ? a : b; } + public void nullType() { + final java.lang.Object nully = null; + } + public void testArrays() { + final int[] intArray = new int[]{1, 2, 3}; + final java.lang.Object[][] multiDimArray = new Object[][]{{}}; + final int[] copy = intArray; + final java.lang.Object[] single = multiDimArray[0]; + final int singleInt = copy[0]; + } }
\ No newline at end of file diff --git a/test/transform/resource/after-ecj/ValComplex.java b/test/transform/resource/after-ecj/ValComplex.java new file mode 100644 index 00000000..cb06d3c1 --- /dev/null +++ b/test/transform/resource/after-ecj/ValComplex.java @@ -0,0 +1 @@ +//ignore
\ No newline at end of file diff --git a/test/transform/resource/after-ecj/ValErrors.java b/test/transform/resource/after-ecj/ValErrors.java new file mode 100644 index 00000000..cb06d3c1 --- /dev/null +++ b/test/transform/resource/after-ecj/ValErrors.java @@ -0,0 +1 @@ +//ignore
\ No newline at end of file diff --git a/test/transform/resource/after-ecj/ValInFor.java b/test/transform/resource/after-ecj/ValInFor.java new file mode 100644 index 00000000..cb06d3c1 --- /dev/null +++ b/test/transform/resource/after-ecj/ValInFor.java @@ -0,0 +1 @@ +//ignore
\ No newline at end of file diff --git a/test/transform/resource/after-ecj/ValLessSimple.java b/test/transform/resource/after-ecj/ValLessSimple.java new file mode 100644 index 00000000..cb06d3c1 --- /dev/null +++ b/test/transform/resource/after-ecj/ValLessSimple.java @@ -0,0 +1 @@ +//ignore
\ No newline at end of file diff --git a/test/transform/resource/after-ecj/ValSimple.java b/test/transform/resource/after-ecj/ValSimple.java new file mode 100644 index 00000000..cb06d3c1 --- /dev/null +++ b/test/transform/resource/after-ecj/ValSimple.java @@ -0,0 +1 @@ +//ignore
\ No newline at end of file diff --git a/test/transform/resource/after-ecj/ValWeirdTypes.java b/test/transform/resource/after-ecj/ValWeirdTypes.java new file mode 100644 index 00000000..cb06d3c1 --- /dev/null +++ b/test/transform/resource/after-ecj/ValWeirdTypes.java @@ -0,0 +1 @@ +//ignore
\ No newline at end of file diff --git a/test/transform/resource/before/ValErrors.java b/test/transform/resource/before/ValErrors.java index 742bca6d..7c5c0a8b 100644 --- a/test/transform/resource/before/ValErrors.java +++ b/test/transform/resource/before/ValErrors.java @@ -1,9 +1,9 @@ public class ValErrors { - public void nullType() { - val a = null; - } - public void unresolvableExpression() { val c = d; } + + public void arrayInitializer() { + val e = { "foo", "bar"}; + } }
\ No newline at end of file diff --git a/test/transform/resource/before/ValWeirdTypes.java b/test/transform/resource/before/ValWeirdTypes.java index 6f6eb9db..855fb91f 100644 --- a/test/transform/resource/before/ValWeirdTypes.java +++ b/test/transform/resource/before/ValWeirdTypes.java @@ -51,4 +51,16 @@ public class ValWeirdTypes<Z> { val d = c ? a : b; java.util.RandomAccess confirm = c ? a : b; } + + public void nullType() { + val nully = null; + } + + public void testArrays() { + val intArray = new int[] {1, 2, 3}; + val multiDimArray = new Object[][] {{}}; + val copy = intArray; + val single = multiDimArray[0]; + val singleInt = copy[0]; + } }
\ No newline at end of file diff --git a/test/transform/resource/messages-delombok/ValErrors.java.messages b/test/transform/resource/messages-delombok/ValErrors.java.messages index feba6912..ca7baeab 100644 --- a/test/transform/resource/messages-delombok/ValErrors.java.messages +++ b/test/transform/resource/messages-delombok/ValErrors.java.messages @@ -1,2 +1,2 @@ -3:21 ERROR Cannot use 'val' here because initializer expression does not have a representable type: <nulltype> -7:21 ERROR Cannot use 'val' here because initializer expression does not have a representable type: Type cannot be resolved +3:21 ERROR Cannot use 'val' here because initializer expression does not have a representable type: Type cannot be resolved +7:21 ERROR 'val' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... }) diff --git a/test/transform/resource/messages-idempotent/ValErrors.java.messages b/test/transform/resource/messages-idempotent/ValErrors.java.messages new file mode 100644 index 00000000..ebeee317 --- /dev/null +++ b/test/transform/resource/messages-idempotent/ValErrors.java.messages @@ -0,0 +1 @@ +6:21 ERROR 'val' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... }) diff --git a/test/transform/src/lombok/transform/TestLombokFilesIdempotent.java b/test/transform/src/lombok/transform/TestLombokFilesIdempotent.java index 63d34820..6a874bfc 100644 --- a/test/transform/src/lombok/transform/TestLombokFilesIdempotent.java +++ b/test/transform/src/lombok/transform/TestLombokFilesIdempotent.java @@ -40,6 +40,11 @@ public class TestLombokFilesIdempotent implements DirectoryRunner.TestParams { } @Override + public File getMessagesDirectory() { + return new File("test/transform/resource/messages-idempotent"); + } + + @Override public DirectoryRunner.Compiler getCompiler() { return DirectoryRunner.Compiler.DELOMBOK; } @@ -48,9 +53,4 @@ public class TestLombokFilesIdempotent implements DirectoryRunner.TestParams { public boolean printErrors() { return true; } - - @Override - public File getMessagesDirectory() { - return null; - } } |