aboutsummaryrefslogtreecommitdiff
path: root/src/lombok/agent
diff options
context:
space:
mode:
authorReinier Zwitserloot <reinier@tipit.to>2009-06-09 18:27:10 +0200
committerReinier Zwitserloot <reinier@tipit.to>2009-06-09 18:27:10 +0200
commit41fb7cba62b543243c784757d1af4e05824ddc4e (patch)
treeb910a78f31576d08f7a95440edb8f630cf4164eb /src/lombok/agent
parent525211b872b982b880aa2bed5e263ec582593f0d (diff)
downloadlombok-41fb7cba62b543243c784757d1af4e05824ddc4e.tar.gz
lombok-41fb7cba62b543243c784757d1af4e05824ddc4e.tar.bz2
lombok-41fb7cba62b543243c784757d1af4e05824ddc4e.zip
Many changes:
- Split off the actual agent work into a separate src package in preparation for creating separate jars. Involved a lot of renaming - Renamed TransformCompilationUnitDeclaration to TransformEclipseAST, as this class will also be transforming e.g. MethodDeclaration objects. - Expanded the patching to also patch in transform calls when the parser fills in the Statement array for existing constructors, methods, and initializers. - Redesigned the ClassLoaderWorkaround class quite a bit. - Positioning should not work correctly ('jump to method' should jump to the getter annotation). (Apparently, Clinit objects are always fully parsed in the original run, so no need to patch anything there).
Diffstat (limited to 'src/lombok/agent')
-rw-r--r--src/lombok/agent/eclipse/EclipseParserPatcher.java47
-rw-r--r--src/lombok/agent/eclipse/EclipseParserTransformer.java83
-rw-r--r--src/lombok/agent/eclipse/HandleGetter_ecj.java57
-rw-r--r--src/lombok/agent/eclipse/TransformCompilationUnitDeclaration.java22
4 files changed, 0 insertions, 209 deletions
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/HandleGetter_ecj.java b/src/lombok/agent/eclipse/HandleGetter_ecj.java
deleted file mode 100644
index d43bbbc4..00000000
--- a/src/lombok/agent/eclipse/HandleGetter_ecj.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package lombok.agent.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.Expression;
-import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
-import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
-import org.eclipse.jdt.internal.compiler.ast.Statement;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-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) {
- TypeReference fieldType = field.type;
- String getterName = TransformationsUtil.toGetterName(new String(field.name), nameEquals(fieldType.getTypeName(), "boolean"));
-
- for ( AbstractMethodDeclaration method : type.methods ) {
- if ( method.selector != null && new String(method.selector).equals(getterName) ) return;
- }
-
- MethodDeclaration method = new MethodDeclaration(type.compilationResult);
- method.modifiers = Modifier.PUBLIC;
- method.returnType = field.type;
- method.annotations = null;
- method.arguments = null;
- method.selector = getterName.toCharArray();
- method.binding = null;
- method.thrownExceptions = null;
- method.typeParameters = null;
- method.scope = new MethodScope(type.scope, method, false);
- Expression fieldExpression = new SingleNameReference(field.name, (field.declarationSourceStart << 32) | field.declarationSourceEnd);
- Statement returnStatement = new ReturnStatement(fieldExpression, field.sourceStart, field.sourceEnd);
- method.statements = new Statement[] { returnStatement };
- AbstractMethodDeclaration[] newArray = new AbstractMethodDeclaration[type.methods.length + 1];
- System.arraycopy(type.methods, 0, newArray, 0, type.methods.length);
- newArray[type.methods.length] = method;
- type.methods = newArray;
- }
-
- private boolean nameEquals(char[][] typeName, String string) {
- StringBuilder sb = new StringBuilder();
- boolean first = true;
- for ( char[] elem : typeName ) {
- if ( first ) first = false;
- else sb.append('.');
- sb.append(elem);
- }
-
- return string.contentEquals(sb);
- }
-}
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);
- }
- }
- }
- }
- }
-}