diff options
author | Reinier Zwitserloot <reinier@tipit.to> | 2009-06-16 03:04:46 +0200 |
---|---|---|
committer | Reinier Zwitserloot <reinier@tipit.to> | 2009-06-16 03:04:46 +0200 |
commit | f36be2eb01bcbff01a513d64bff2d1aba54460b1 (patch) | |
tree | 7d49ebe90cb836e054c35d2a4382be6b999ca452 /src/lombok/apt | |
parent | d78a04d74886101c81de77659b067d16cb2d0de2 (diff) | |
download | lombok-f36be2eb01bcbff01a513d64bff2d1aba54460b1.tar.gz lombok-f36be2eb01bcbff01a513d64bff2d1aba54460b1.tar.bz2 lombok-f36be2eb01bcbff01a513d64bff2d1aba54460b1.zip |
Implemented a lot of stuff for javac, but we ran into 2 major issues still to be implemented:
1. The visit mode of a lombok handler (does not trigger off of annotations, instead sees every field, method, type, and statement), needs to be coded,
2. triggering off of annotations via APT's annotation handling system skips method-local classes. We'll need to recode this via an AST visitor like we need for issue #1
Other than that, triggering off of annotations works swimmingly!
Diffstat (limited to 'src/lombok/apt')
-rw-r--r-- | src/lombok/apt/AnnotationTransponder.java | 111 | ||||
-rw-r--r-- | src/lombok/apt/HandleANY_ecj.java | 17 | ||||
-rw-r--r-- | src/lombok/apt/HandleGetter_javac.java | 77 | ||||
-rw-r--r-- | src/lombok/apt/HandlerForCompiler.java | 16 | ||||
-rw-r--r-- | src/lombok/apt/PKG.java | 70 | ||||
-rw-r--r-- | src/lombok/apt/Processor.java | 35 |
6 files changed, 0 insertions, 326 deletions
diff --git a/src/lombok/apt/AnnotationTransponder.java b/src/lombok/apt/AnnotationTransponder.java deleted file mode 100644 index 01a79c12..00000000 --- a/src/lombok/apt/AnnotationTransponder.java +++ /dev/null @@ -1,111 +0,0 @@ -package lombok.apt; - -import static lombok.apt.PKG.CURRENT_SUPPORT; -import static lombok.apt.PKG.isInstanceOf; -import static lombok.apt.PKG.readResource; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Constructor; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.annotation.processing.RoundEnvironment; -import javax.lang.model.element.Element; -import javax.tools.Diagnostic; - -/** - * Responsible for redirecting the need to handle an annotation to a class that knows how to handle a given annotation type in a given compiler environment. - * Will dynamically locate a class in this package using the naming pattern: "HandleFoo_compilerType", e.g. "HandleGetter_ecj". - * Responsible for injecting the proper class into the right classloader so that it has open access to the classes required to inspect the live AST and - * modify it so that annotations can cause changes to the live AST. - * - * @author rzwitserloot - * - * @param <T> The annotation class that this transponder should handle (example: Getter.class). - */ -public class AnnotationTransponder<T extends Annotation> { - private HandlerForCompiler<T> impl; - private final ProcessingEnvironment processEnv; - private final RoundEnvironment roundEnv; - private String error; - - @SuppressWarnings("unchecked") - private void createInstance(Class<T> annotation, ClassLoader loader, String compilerType) { - try { - if ( loader == null ) loader = AnnotationTransponder.class.getClassLoader(); - Class<?> implClass; - try { - implClass = loader.loadClass(String.format( - "org.javanext.apt.Handle%s_%s", annotation.getSimpleName(), compilerType)); - } catch ( ClassNotFoundException e ) { - implClass = loader.loadClass(String.format("lombok.apt.HandleANY_%s", compilerType)); - } - - Constructor<?> constructor; - - constructor = implClass.getDeclaredConstructor(); - constructor.setAccessible(true); - impl = (HandlerForCompiler<T>)constructor.newInstance(); - impl.processEnv = processEnv; - impl.roundEnv = roundEnv; - try { - impl.init(); - } catch ( Exception e ) { - error = "Exception initializing handler: " + e; - impl = null; - } - } catch ( Exception e ) { - e.printStackTrace(); - error = "You are using " + compilerType + " but a version that's changed the compiler internals. I can't work with it."; - } - } - - public AnnotationTransponder(Class<T> annotation, RoundEnvironment roundEnv, ProcessingEnvironment processEnv) { - this.processEnv = processEnv; - this.roundEnv = roundEnv; - if ( isInstanceOf(processEnv, "com.sun.tools.javac.processing.JavacProcessingEnvironment") ) { - createInstance(annotation, null, "javac"); - } else if ( isInstanceOf(processEnv, "org.eclipse.jdt.internal.apt.pluggable.core.dispatch.IdeBuildProcessingEnvImpl") ) { - final ClassLoader[] parentLoaders = - new ClassLoader[] { processEnv.getClass().getClassLoader(), AnnotationTransponder.class.getClassLoader() }; - - ClassLoader loader = new ClassLoader() { - @Override public Class<?> findClass(String name) throws ClassNotFoundException { - if ( name.equals(HandlerForCompiler.class.getName()) ) return HandlerForCompiler.class; - if ( name.startsWith(AnnotationTransponder.class.getPackage().getName()) ) { - byte[] data = readResource(name.replace(".", "/") + ".class"); - return defineClass(name, data, 0, data.length); - } - for ( int i = 0 ; i < parentLoaders.length ; i++ ) { - try { - return parentLoaders[i].loadClass(name); - } catch ( ClassNotFoundException e ) { - if ( i == parentLoaders.length -1 ) throw e; - } - } - - return null; - } - }; - - createInstance(annotation, loader, "ecj"); - } else { - impl = null; - this.error = "I cannot work with your compiler. I currently only support " + CURRENT_SUPPORT + ".\n" + - "This is a: " + processEnv.getClass(); - } - } - - - public void handle(Element element, T annotation) { - if ( impl == null ) { - processEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, error, element); - } else { - try { - impl.handle(element, annotation); - } catch ( Exception e ) { - e.printStackTrace(); - processEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, "Exception in JavaNext: " + e, element); - } - } - } -} diff --git a/src/lombok/apt/HandleANY_ecj.java b/src/lombok/apt/HandleANY_ecj.java deleted file mode 100644 index 587444d9..00000000 --- a/src/lombok/apt/HandleANY_ecj.java +++ /dev/null @@ -1,17 +0,0 @@ -package lombok.apt; - -import java.lang.annotation.Annotation; - -import javax.lang.model.element.Element; -import javax.tools.Diagnostic; - -public class HandleANY_ecj extends HandlerForCompiler<Annotation> { - @Override public void handle(Element element, Annotation annotation) throws Exception { - //TODO: We should find eclipse's eclipse.ini file and patch us in as a javaagent and bootclasspath/a. - //Though, we should probably use reflection to find eclipse's SWT system and generate a popup dialog for - //confirmation. - - String msg = "You'll need to install the eclipse patch. See http://lombok.github.org/ for more info."; - processEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, msg, element); - } -} diff --git a/src/lombok/apt/HandleGetter_javac.java b/src/lombok/apt/HandleGetter_javac.java deleted file mode 100644 index bfa2746d..00000000 --- a/src/lombok/apt/HandleGetter_javac.java +++ /dev/null @@ -1,77 +0,0 @@ -package lombok.apt; - -import java.lang.reflect.Modifier; - -import javax.annotation.processing.Messager; -import javax.lang.model.element.Element; -import javax.lang.model.element.TypeElement; -import javax.tools.Diagnostic; - -import lombok.Getter; - -import com.sun.source.tree.MethodTree; -import com.sun.source.util.Trees; -import com.sun.tools.javac.code.Symbol; -import com.sun.tools.javac.code.Type; -import com.sun.tools.javac.processing.JavacProcessingEnvironment; -import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.TreeMaker; -import com.sun.tools.javac.tree.JCTree.JCAnnotation; -import com.sun.tools.javac.tree.JCTree.JCBlock; -import com.sun.tools.javac.tree.JCTree.JCClassDecl; -import com.sun.tools.javac.tree.JCTree.JCExpression; -import com.sun.tools.javac.tree.JCTree.JCStatement; -import com.sun.tools.javac.tree.JCTree.JCTypeParameter; -import com.sun.tools.javac.tree.JCTree.JCVariableDecl; -import com.sun.tools.javac.util.List; -import com.sun.tools.javac.util.Name; - -class HandleGetter_javac extends HandlerForCompiler<Getter> { - private final Trees trees; - private final Messager messager; - private JavacProcessingEnvironment env; - - HandleGetter_javac() { - this.messager = processEnv.getMessager(); - this.trees = Trees.instance(processEnv); - } - - @Override public void init() { - this.env = (JavacProcessingEnvironment)processEnv; - } - - @Override public void handle(Element element, Getter getter) { - if ( !element.getKind().isField() ) { - messager.printMessage(Diagnostic.Kind.ERROR, "@Getter is only supported on a field."); - return; - } - - TypeElement classElement = (TypeElement)element.getEnclosingElement(); - JCClassDecl javacClassTree = (JCClassDecl)trees.getTree(classElement); - - Name.Table nameTable = Name.Table.instance(env.getContext()); - TreeMaker treeMaker = TreeMaker.instance(env.getContext()); - - MethodTree getterMethod = createGetter(element, treeMaker, nameTable); - javacClassTree.defs = javacClassTree.defs.append((JCTree)getterMethod); - } - - private MethodTree createGetter(Element field, TreeMaker treeMaker, Name.Table nameTable) { - JCStatement returnStatement = treeMaker.Return(treeMaker.Ident((Symbol)field)); - - //TODO Trab the position in the source file of the field by looking it up in the JCClassDecl, - //and copy it into the 'position' info for the Ident and Return AST Nodes. - - JCBlock methodBody = treeMaker.Block(0, List.of(returnStatement)); - Name methodName = Name.fromString(nameTable, PKG.toGetterName(field)); - JCExpression methodType = treeMaker.Type((Type)field.asType()); - - List<JCTypeParameter> methodGenericParams = List.nil(); - List<JCVariableDecl> parameters = List.nil(); - List<JCExpression> throwsClauses = List.nil(); - JCExpression annotationMethodDefaultValue = null; - - return treeMaker.MethodDef(treeMaker.Modifiers(Modifier.PUBLIC, List.<JCAnnotation>nil()), methodName, methodType, - methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue); - } -} diff --git a/src/lombok/apt/HandlerForCompiler.java b/src/lombok/apt/HandlerForCompiler.java deleted file mode 100644 index 7eb29385..00000000 --- a/src/lombok/apt/HandlerForCompiler.java +++ /dev/null @@ -1,16 +0,0 @@ -package lombok.apt; - -import java.lang.annotation.Annotation; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.annotation.processing.RoundEnvironment; -import javax.lang.model.element.Element; - -public abstract class HandlerForCompiler<T extends Annotation> { - protected ProcessingEnvironment processEnv; - protected RoundEnvironment roundEnv; - - public void init() throws Exception {} - - public abstract void handle(Element element, T annotation) throws Exception; -} diff --git a/src/lombok/apt/PKG.java b/src/lombok/apt/PKG.java deleted file mode 100644 index 2808e31e..00000000 --- a/src/lombok/apt/PKG.java +++ /dev/null @@ -1,70 +0,0 @@ -package lombok.apt; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -import javax.lang.model.element.Element; -import javax.lang.model.type.TypeKind; - -import lombok.Lombok; -import lombok.core.TransformationsUtil; - - -class PKG { - static final String CURRENT_SUPPORT = "javac 1.6 and eclipse (ecj)."; - - private PKG() {} - - static boolean isInstanceOf(Object o, String className) { - if ( o == null ) return false; - return isInstanceOf(o.getClass(), className); - } - - static boolean isInstanceOf(Class<?> c, String className) { - if ( c == Object.class || c == null ) return false; - - if ( c.getName().equals(className) ) return true; - - if ( isInstanceOf(c.getSuperclass(), className) ) return true; - for ( Class<?> iface : c.getInterfaces() ) { - if ( isInstanceOf(iface, className) ) return true; - } - - return false; - } - - static byte[] readResource(String name) { - return readResource(PKG.class.getClassLoader(), name); - } - - static byte[] readResource(ClassLoader loader, String name) { - InputStream in = loader.getResourceAsStream(name); - if ( in == null ) throw Lombok.sneakyThrow(new IOException("Not found: " + name)); - - try { - return readStream(in); - } catch (IOException e) { - throw Lombok.sneakyThrow(e); - } - } - - static String toGetterName(Element field) { - CharSequence fieldName = field.getSimpleName(); - - boolean isBoolean = field.asType().getKind() == TypeKind.BOOLEAN; - - return TransformationsUtil.toGetterName(fieldName, isBoolean); - } - - static byte[] readStream(InputStream in) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] b = new byte[65536]; - while ( true ) { - int r = in.read(b); - if ( r == -1 ) break; - if ( r > 0 ) baos.write(b, 0, r); - } - return baos.toByteArray(); - } -} diff --git a/src/lombok/apt/Processor.java b/src/lombok/apt/Processor.java deleted file mode 100644 index d63ec006..00000000 --- a/src/lombok/apt/Processor.java +++ /dev/null @@ -1,35 +0,0 @@ -package lombok.apt; - -import java.lang.annotation.Annotation; -import java.util.Set; - -import javax.annotation.processing.AbstractProcessor; -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 lombok.Getter; - - -@SupportedAnnotationTypes("lombok.*") -@SupportedSourceVersion(SourceVersion.RELEASE_6) -public class Processor extends AbstractProcessor { - @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - for ( TypeElement typeElement : annotations ) { - if ( typeElement.getQualifiedName().contentEquals(Getter.class.getName()) ) - return handle(roundEnv, Getter.class, typeElement); - } - - return false; - } - - private <T extends Annotation> boolean handle(RoundEnvironment roundEnv, Class<T> annotation, TypeElement typeElement) { - for ( Element element : roundEnv.getElementsAnnotatedWith(typeElement) ) { - new AnnotationTransponder<T>(annotation, roundEnv, processingEnv).handle(element, element.getAnnotation(annotation)); - } - return true; - } -} |