aboutsummaryrefslogtreecommitdiff
path: root/src/lombok
diff options
context:
space:
mode:
Diffstat (limited to 'src/lombok')
-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/TransformCompilationUnitDeclaration.java22
-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.java60
5 files changed, 67 insertions, 154 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/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) {
+
+ }
+}