diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/java/lombok/ClassLoaderWorkaround.java | 74 | ||||
-rw-r--r-- | src/lombok/agent/eclipse/EclipseParserPatcher.java | 47 | ||||
-rw-r--r-- | src/lombok/agent/eclipse/EclipseParserTransformer.java | 83 | ||||
-rw-r--r-- | src/lombok/agent/eclipse/TransformCompilationUnitDeclaration.java | 22 | ||||
-rw-r--r-- | src/lombok/eclipse/HandleGetter_ecj.java (renamed from src/lombok/agent/eclipse/HandleGetter_ecj.java) | 9 | ||||
-rw-r--r-- | src/lombok/eclipse/TransformEclipseAST.java | 60 |
6 files changed, 67 insertions, 228 deletions
diff --git a/src/java/lombok/ClassLoaderWorkaround.java b/src/java/lombok/ClassLoaderWorkaround.java deleted file mode 100644 index c533424d..00000000 --- a/src/java/lombok/ClassLoaderWorkaround.java +++ /dev/null @@ -1,74 +0,0 @@ -package java.lombok; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Method; - -/** - * Allows you to load a class off of any place that is injected into a class loader (which doesn't know how to load the class you're injecting). - * - * Example: Injecting lombok's Eclipse Parser patching code into eclipse's OSGi BundleLoader. - * - * @author rzwitserloot - */ -public class ClassLoaderWorkaround { - private static boolean initialized; - private static Method m; - - public static void transformCompilationUnitDeclaration(Object cud) throws Exception { - if ( !initialized ) initialize(cud); - if ( m == null ) throw new ClassNotFoundException("lombok.agent.eclipse.TransformCompilationUnitDeclaration"); - m.invoke(null, cud); - } - - private static void initialize(Object cud) { - final ClassLoader parent = cud.getClass().getClassLoader(); - ClassLoader loader = new ClassLoader() { - @Override public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { - if ( name.startsWith("lombok.") ) { - InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(name.replace(".", "/") + ".class"); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - byte[] b = new byte[65536]; - try { - while ( true ) { - int r = in.read(b); - if ( r == -1 ) break; - if ( r > 0 ) out.write(b, 0, r); - } - - in.close(); - byte[] data = out.toByteArray(); - Class<?> result = defineClass(name, data, 0, data.length); - if ( resolve ) resolveClass(result); - return result; - } catch ( IOException e ) { - throw new ClassNotFoundException(); - } - } else { - try { - Class<?> result = ClassLoader.getSystemClassLoader().loadClass(name); - if ( resolve ) resolveClass(result); - return result; - } catch ( ClassNotFoundException e ) { - Class<?> result = parent.loadClass(name); - if ( resolve ) resolveClass(result); - return result; - } - } - } - }; - - try { - Class<?> c = loader.loadClass("lombok.agent.eclipse.TransformCompilationUnitDeclaration"); - for ( Method m : c.getMethods() ) { - if ( m.getName().equals("transform") ) { - ClassLoaderWorkaround.m = m; - break; - } - } - } catch ( ClassNotFoundException ignore ) {} - initialized = true; - } -} diff --git a/src/lombok/agent/eclipse/EclipseParserPatcher.java b/src/lombok/agent/eclipse/EclipseParserPatcher.java deleted file mode 100644 index abe26683..00000000 --- a/src/lombok/agent/eclipse/EclipseParserPatcher.java +++ /dev/null @@ -1,47 +0,0 @@ -package lombok.agent.eclipse; - -import java.lang.instrument.ClassFileTransformer; -import java.lang.instrument.IllegalClassFormatException; -import java.lang.instrument.Instrumentation; -import java.lang.instrument.UnmodifiableClassException; -import java.security.ProtectionDomain; - -public class EclipseParserPatcher { - private static class Patcher implements ClassFileTransformer { - @Override public byte[] transform(ClassLoader loader, String className, - Class<?> classBeingRedefined, - ProtectionDomain protectionDomain, byte[] classfileBuffer) - throws IllegalClassFormatException { - - if ( !ECLIPSE_PARSER_CLASS_NAME.equals(className) ) return null; - EclipseParserTransformer transformer = new EclipseParserTransformer(classfileBuffer); - return transformer.transform(); - } - } - - static final String ECLIPSE_PARSER_CLASS_NAME = "org/eclipse/jdt/internal/compiler/parser/Parser"; - - public static void agentmain(String agentArgs, Instrumentation instrumentation) { - registerPatcher(instrumentation, true); - } - - public static void premain(String agentArgs, Instrumentation instrumentation) { - registerPatcher(instrumentation, false); - } - - private static void registerPatcher(Instrumentation instrumentation, boolean transformExisting) { - instrumentation.addTransformer(new Patcher(), true); - - if ( transformExisting ) for ( Class<?> c : instrumentation.getAllLoadedClasses() ) { - if ( c.getName().equals(ECLIPSE_PARSER_CLASS_NAME) ) { - try { - instrumentation.retransformClasses(c); - } catch ( UnmodifiableClassException ex ) { - throw new UnsupportedOperationException( - "The eclipse parser class is already loaded and cannot be modified. " + - "You'll have to restart eclipse in order to use Lombok in eclipse."); - } - } - } - } -} diff --git a/src/lombok/agent/eclipse/EclipseParserTransformer.java b/src/lombok/agent/eclipse/EclipseParserTransformer.java deleted file mode 100644 index fa549ff8..00000000 --- a/src/lombok/agent/eclipse/EclipseParserTransformer.java +++ /dev/null @@ -1,83 +0,0 @@ -package lombok.agent.eclipse; - -import org.objectweb.asm.ClassAdapter; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.MethodAdapter; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -class EclipseParserTransformer { - private static final String COMPILATION_UNIT_DECLARATION_SIG = - "Lorg/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration;"; - - private static final String TOPATCH_METHOD_NAME = "endParse"; - private static final String TOPATCH_METHOD_DESC = "(I)" + COMPILATION_UNIT_DECLARATION_SIG; - - private final byte[] in; - - EclipseParserTransformer(byte[] classfileBuffer) { - in = classfileBuffer; - } - - byte[] transform() { - ClassReader reader = new ClassReader(in); - ClassWriter writer = new ClassWriter(reader, 0); - ClassAdapter adapter = new ParserPatcherAdapter(writer); - reader.accept(adapter, 0); - return writer.toByteArray(); - } - - private static class ParserPatcherAdapter extends ClassAdapter { - public ParserPatcherAdapter(ClassVisitor cv) { - super(cv); - } - - @Override public MethodVisitor visitMethod(int access, String name, String desc, - String signature, String[] exceptions) { - MethodVisitor writerVisitor = super.visitMethod(access, name, desc, signature, exceptions); - if ( !TOPATCH_METHOD_NAME.equals(name) || !TOPATCH_METHOD_DESC.equals(desc) ) return writerVisitor; - - return new PatcherMethodVisitor(writerVisitor); - } - } - - static class PatcherMethodVisitor extends MethodAdapter { - private static final String TARGET_STATIC_CLASS = "java/lombok/ClassLoaderWorkaround"; - private static final String TARGET_STATIC_METHOD_NAME = "transformCompilationUnitDeclaration"; - private static final String TARGET_STATIC_METHOD_DESC = "(Ljava/lang/Object;)V"; - - private boolean alreadyCalled = false; - - PatcherMethodVisitor(MethodVisitor mv) { - super(mv); - } - - @Override public void visitInsn(int opcode) { - if ( opcode == Opcodes.ARETURN ) insertHookCall(); - - super.visitInsn(opcode); - } - - @Override public void visitMethodInsn(int opcode, String owner, String name, - String desc) { - if ( opcode == Opcodes.INVOKESTATIC && - TARGET_STATIC_CLASS.equals(owner) && TARGET_STATIC_METHOD_NAME.equals(name) ) alreadyCalled = true; - super.visitMethodInsn(opcode, owner, name, desc); - } - - /** When this method is called, the stack should hold the reference to the - * just-parsed CompilationUnitDeclaration object that is about to be returned - * to whomever wants it. We will put a call to a method of our choosing in, - * which will transform the CUD. The stack is not modified (that is, that method - * returns a CUD). - */ - private void insertHookCall() { - if ( alreadyCalled ) return; - super.visitInsn(Opcodes.DUP); - super.visitMethodInsn(Opcodes.INVOKESTATIC, TARGET_STATIC_CLASS, - TARGET_STATIC_METHOD_NAME, TARGET_STATIC_METHOD_DESC); - } - } -} diff --git a/src/lombok/agent/eclipse/TransformCompilationUnitDeclaration.java b/src/lombok/agent/eclipse/TransformCompilationUnitDeclaration.java deleted file mode 100644 index 7c29a795..00000000 --- a/src/lombok/agent/eclipse/TransformCompilationUnitDeclaration.java +++ /dev/null @@ -1,22 +0,0 @@ -package lombok.agent.eclipse; - -import org.eclipse.jdt.internal.compiler.ast.Annotation; -import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; -import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; -import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; - -public class TransformCompilationUnitDeclaration { - /** This is a 'magic' method signature - it is this one that will be called. Don't rename anything! */ - - public static void transform(CompilationUnitDeclaration ast) { - if ( ast.types != null ) for ( TypeDeclaration type : ast.types ) { - if ( type.fields != null ) for ( FieldDeclaration field : type.fields ) { - if ( field.annotations != null ) for ( Annotation annotation : field.annotations ) { - if ( annotation.type.toString().equals("Getter") ) { - new HandleGetter_ecj().apply(type, field); - } - } - } - } - } -} diff --git a/src/lombok/agent/eclipse/HandleGetter_ecj.java b/src/lombok/eclipse/HandleGetter_ecj.java index d43bbbc4..f71376a3 100644 --- a/src/lombok/agent/eclipse/HandleGetter_ecj.java +++ b/src/lombok/eclipse/HandleGetter_ecj.java @@ -1,10 +1,12 @@ -package lombok.agent.eclipse; +package lombok.eclipse; import java.lang.reflect.Modifier; import lombok.transformations.TransformationsUtil; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.Annotation; +import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; @@ -16,7 +18,7 @@ import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; public class HandleGetter_ecj { - public void apply(TypeDeclaration type, FieldDeclaration field) { + public void apply(Annotation annotation, TypeDeclaration type, FieldDeclaration field) { TypeReference fieldType = field.type; String getterName = TransformationsUtil.toGetterName(new String(field.name), nameEquals(fieldType.getTypeName(), "boolean")); @@ -34,8 +36,11 @@ public class HandleGetter_ecj { method.thrownExceptions = null; method.typeParameters = null; method.scope = new MethodScope(type.scope, method, false); + method.bits |= ASTNode.Bit24; Expression fieldExpression = new SingleNameReference(field.name, (field.declarationSourceStart << 32) | field.declarationSourceEnd); Statement returnStatement = new ReturnStatement(fieldExpression, field.sourceStart, field.sourceEnd); + method.bodyStart = method.declarationSourceStart = method.sourceStart = annotation.sourceStart; + method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = annotation.sourceEnd; method.statements = new Statement[] { returnStatement }; AbstractMethodDeclaration[] newArray = new AbstractMethodDeclaration[type.methods.length + 1]; System.arraycopy(type.methods, 0, newArray, 0, type.methods.length); diff --git a/src/lombok/eclipse/TransformEclipseAST.java b/src/lombok/eclipse/TransformEclipseAST.java new file mode 100644 index 00000000..9212a0d4 --- /dev/null +++ b/src/lombok/eclipse/TransformEclipseAST.java @@ -0,0 +1,60 @@ +package lombok.eclipse; + +import org.eclipse.jdt.internal.compiler.ast.Annotation; +import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; +import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; +import org.eclipse.jdt.internal.compiler.ast.Initializer; +import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; +import org.eclipse.jdt.internal.compiler.parser.Parser; + +/** + * Entry point for the Eclipse Parser patch that lets lombok modify the Abstract Syntax Tree as generated by + * eclipse's parser implementations. This class is injected into the appropriate OSGi ClassLoader and can thus + * use any classes that belong to org.eclipse.jdt.(apt.)core. + * + * Note that, for any Method body, if Bit24 is set, the eclipse parser has been patched to never attempt to + * (re)parse it. You should set Bit24 on any MethodDeclaration object you inject into the AST: + * + * <code>methodDeclaration.bits |= 0x80000;</code> + * + * @author rzwitserloot + * @author rspilker + */ +public class TransformEclipseAST { + /** + * This method is called immediately after eclipse finishes building a CompilationUnitDeclaration, which is + * the top-level AST node when eclipse parses a source file. The signature is 'magic' - you should not + * change it! + * + * Eclipse's parsers often operate in diet mode, which means many parts of the AST have been left blank. + * Be ready to deal with just about anything being null, such as the Statement[] arrays of the Method AST nodes. + * + * @param parser The eclipse parser object that generated the AST. + * @param ast The AST node belonging to the compilation unit (java speak for a single source file). + */ + public static void transform(Parser parser, CompilationUnitDeclaration ast) { + if ( ast.types != null ) for ( TypeDeclaration type : ast.types ) { + if ( type.fields != null ) for ( FieldDeclaration field : type.fields ) { + if ( field.annotations != null ) for ( Annotation annotation : field.annotations ) { + if ( annotation.type.toString().equals("Getter") ) { + new HandleGetter_ecj().apply(annotation, type, field); + } + } + } + } + } + + public static void transform(Parser parser, MethodDeclaration ast) { + + } + + public static void transform(Parser parser, ConstructorDeclaration ast) { + + } + + public static void transform(Parser parser, Initializer ast) { + + } +} |