diff options
-rw-r--r-- | src/core/lombok/core/AnnotationProcessor.java | 144 | ||||
-rw-r--r-- | src/core/lombok/javac/apt/Processor.java | 34 |
2 files changed, 147 insertions, 31 deletions
diff --git a/src/core/lombok/core/AnnotationProcessor.java b/src/core/lombok/core/AnnotationProcessor.java new file mode 100644 index 00000000..19748611 --- /dev/null +++ b/src/core/lombok/core/AnnotationProcessor.java @@ -0,0 +1,144 @@ +package lombok.core; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +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; + +@SupportedAnnotationTypes("*") +@SupportedSourceVersion(SourceVersion.RELEASE_6) +public class AnnotationProcessor extends AbstractProcessor { + private static String trace(Throwable t) { + StringWriter w = new StringWriter(); + t.printStackTrace(new PrintWriter(w, true)); + return w.toString(); + } + + static abstract class ProcessorDescriptor { + abstract boolean want(ProcessingEnvironment procEnv, List<String> delayedWarnings); + abstract String getName(); + abstract boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv); + } + + private final List<ProcessorDescriptor> registered = Arrays.asList(new JavacDescriptor(), new EcjDescriptor()); + private final List<ProcessorDescriptor> active = new ArrayList<ProcessorDescriptor>(); + private final List<String> delayedWarnings = new ArrayList<String>(); + + static class JavacDescriptor extends ProcessorDescriptor { + private Processor processor; + + @Override String getName() { + return "sun/apple javac 1.6"; + } + + @Override boolean want(ProcessingEnvironment procEnv, List<String> delayedWarnings) { + if (!procEnv.getClass().getName().equals("com.sun.tools.javac.processing.JavacProcessingEnvironment")) return false; + + try { + processor = (Processor)Class.forName("lombok.javac.apt.Processor").newInstance(); + } catch (Exception e) { + delayedWarnings.add("You found a bug in lombok; lombok.javac.apt.Processor is not available. Lombok will not run during this compilation: " + trace(e)); + return false; + } catch (NoClassDefFoundError e) { + delayedWarnings.add("Can't load javac processor due to (most likely) a class loader problem: " + trace(e)); + return false; + } + + processor.init(procEnv); + return true; + } + + @Override boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { + return processor.process(annotations, roundEnv); + } + } + + static class EcjDescriptor extends ProcessorDescriptor { + private Processor processor; + + @Override String getName() { + return "ECJ"; + } + + @Override boolean want(ProcessingEnvironment procEnv, List<String> delayedWarnings) { + if (!procEnv.getClass().getName().startsWith("org.eclipse.jdt.")) return false; + boolean inEclipse; + try { + Class.forName("org.eclipse.core.runtime.Platform"); //if this works, we're in eclipse. + inEclipse = true; + } catch (ClassNotFoundException e) { + inEclipse = false; //We're in ecj. + } + + if (inEclipse) { + delayedWarnings.add("You should not install lombok.jar as an annotation processor in eclipse. Instead, run lombok.jar as a java application and follow the instructions."); + return false; + } + + try { + processor = (Processor)Class.forName("lombok.eclipse.apt.Processor").newInstance(); + } catch (Exception e) { + delayedWarnings.add("You found a bug in lombok; lombok.eclipse.apt.Processor is not available. Lombok will not run during this compilation: " + trace(e)); + return false; + } catch (NoClassDefFoundError e) { + delayedWarnings.add("Can't load eclipse processor due to (most likely) a class loader problem: " + trace(e)); + return false; + } + + processor.init(procEnv); + return true; + } + + @Override boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { + return processor.process(annotations, roundEnv); + } + } + + @Override public void init(ProcessingEnvironment procEnv) { + super.init(procEnv); + for (ProcessorDescriptor proc : registered) { + if (proc.want(procEnv, delayedWarnings)) active.add(proc); + } + + if (active.isEmpty() && delayedWarnings.isEmpty()) { + StringBuilder supported = new StringBuilder(); + for (ProcessorDescriptor proc : registered) { + if (supported.length() > 0) supported.append(", "); + supported.append(proc.getName()); + } + procEnv.getMessager().printMessage(Kind.WARNING, String.format("You aren't using a compiler supported by lombok, so lombok will not work and has been disabled.\n" + + "Your processor is: %s\nLombok supports: %s", procEnv.getClass().getName(), supported)); + } + } + + @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { + if (!delayedWarnings.isEmpty()) { + Set<? extends Element> rootElements = roundEnv.getRootElements(); + if (!rootElements.isEmpty()) { + Element firstRoot = rootElements.iterator().next(); + for (String warning : delayedWarnings) processingEnv.getMessager().printMessage(Kind.WARNING, warning, firstRoot); + delayedWarnings.clear(); + } + } + + boolean handled = false; + for (ProcessorDescriptor proc : active) { + handled |= proc.process(annotations, roundEnv); + } + + return handled; + } +} diff --git a/src/core/lombok/javac/apt/Processor.java b/src/core/lombok/javac/apt/Processor.java index b779a680..31cedf03 100644 --- a/src/core/lombok/javac/apt/Processor.java +++ b/src/core/lombok/javac/apt/Processor.java @@ -32,7 +32,6 @@ 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 lombok.javac.JavacTransformer; @@ -55,47 +54,20 @@ import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; @SupportedAnnotationTypes("*") @SupportedSourceVersion(SourceVersion.RELEASE_6) public class Processor extends AbstractProcessor { - private ProcessingEnvironment rawProcessingEnv; private JavacProcessingEnvironment processingEnv; private JavacTransformer transformer; private Trees trees; - private String errorToShow; /** {@inheritDoc} */ @Override public void init(ProcessingEnvironment procEnv) { super.init(procEnv); - this.rawProcessingEnv = procEnv; - String className = procEnv.getClass().getName(); - if (className.startsWith("org.eclipse.jdt.")) { - errorToShow = "You should not install lombok.jar as an annotation processor in eclipse. Instead, run lombok.jar as a java application and follow the instructions."; - procEnv.getMessager().printMessage(Kind.WARNING, errorToShow); - this.processingEnv = null; - } else if (!procEnv.getClass().getName().equals("com.sun.tools.javac.processing.JavacProcessingEnvironment")) { - procEnv.getMessager().printMessage(Kind.WARNING, "You aren't using a compiler based around javac v1.6, so lombok will not work properly.\n" + - "Your processor class is: " + className); - this.processingEnv = null; - this.errorToShow = null; - } else { - this.processingEnv = (JavacProcessingEnvironment) procEnv; - transformer = new JavacTransformer(procEnv.getMessager()); - trees = Trees.instance(procEnv); - this.errorToShow = null; - } + this.processingEnv = (JavacProcessingEnvironment) procEnv; + transformer = new JavacTransformer(procEnv.getMessager()); + trees = Trees.instance(procEnv); } /** {@inheritDoc} */ @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - if (processingEnv == null) { - if (errorToShow != null) { - Set<? extends Element> rootElements = roundEnv.getRootElements(); - if (!rootElements.isEmpty()) { - rawProcessingEnv.getMessager().printMessage(Kind.WARNING, errorToShow, rootElements.iterator().next()); - errorToShow = null; - } - } - return false; - } - IdentityHashMap<JCCompilationUnit, Void> units = new IdentityHashMap<JCCompilationUnit, Void>(); for (Element element : roundEnv.getRootElements()) { JCCompilationUnit unit = toUnit(element); |