aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.classpath1
-rw-r--r--src/java/lombok/ClassLoaderWorkaround.java74
-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
-rw-r--r--src_eclipseagent/java/lombok/ClassLoaderWorkaround.java104
-rw-r--r--src_eclipseagent/lombok/agent/eclipse/EclipseParserPatcher.java (renamed from src/lombok/agent/eclipse/EclipseParserPatcher.java)0
-rw-r--r--src_eclipseagent/lombok/agent/eclipse/EclipseParserTransformer.java157
9 files changed, 329 insertions, 181 deletions
diff --git a/.classpath b/.classpath
index f54ce91b..3db29c3e 100644
--- a/.classpath
+++ b/.classpath
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="src_eclipseagent"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/asm-3.1.jar" sourcepath="contrib/asm-3.1-src.zip">
<attributes>
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/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) {
+
+ }
+}
diff --git a/src_eclipseagent/java/lombok/ClassLoaderWorkaround.java b/src_eclipseagent/java/lombok/ClassLoaderWorkaround.java
new file mode 100644
index 00000000..0238b592
--- /dev/null
+++ b/src_eclipseagent/java/lombok/ClassLoaderWorkaround.java
@@ -0,0 +1,104 @@
+package java.lombok;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+
+/**
+ * Allows you to inject the lombok classes into any classloader, even if that classloader does not
+ * know how to find the lombok classes.
+ *
+ * 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 transformCompilationUnitDeclaration;
+ private static Method transformMethodDeclaration;
+ private static Method transformConstructorDeclaration;
+ private static Method transformInitializer;
+
+ public static void transformCompilationUnitDeclaration(Object parser, Object cud) throws Exception {
+ initialize(cud);
+ transformCompilationUnitDeclaration.invoke(null, parser, cud);
+ }
+
+ public static void transformMethodDeclaration(Object parser, Object methodDeclaration) throws Exception {
+ initialize(methodDeclaration);
+ transformMethodDeclaration.invoke(null, parser, methodDeclaration);
+ }
+
+ public static void transformConstructorDeclaration(Object parser, Object constructorDeclaration) throws Exception {
+ initialize(constructorDeclaration);
+ transformConstructorDeclaration.invoke(null, parser, constructorDeclaration);
+ }
+
+ public static void transformInitializer(Object parser, Object initializer) throws Exception {
+ initialize(initializer);
+ transformInitializer.invoke(null, parser, initializer);
+ }
+
+ private static void initialize(Object cud) throws ClassNotFoundException {
+ if ( initialized ) {
+ if ( transformInitializer == null ) throw new ClassNotFoundException("lombok.eclipse.TransformEclipseAST");
+ return;
+ }
+
+ 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.eclipse.TransformEclipseAST");
+ for ( Method m : c.getMethods() ) {
+ if ( m.getName().equals("transform") ) {
+ if ( m.getParameterTypes().length >= 2 ) {
+ Class<?> astType = m.getParameterTypes()[1];
+ String astName = astType.getName();
+ astName = astName.substring(astName.lastIndexOf('.') + 1);
+ if ( astName.equals("CompilationUnitDeclaration") ) transformCompilationUnitDeclaration = m;
+ else if ( astName.equals("MethodDeclaration") ) transformMethodDeclaration = m;
+ else if ( astName.equals("ConstructorDeclaration") ) transformConstructorDeclaration = m;
+ else if ( astName.equals("Initializer") ) transformInitializer = m;
+ }
+ }
+ }
+ } catch ( ClassNotFoundException ignore ) {}
+ initialized = true;
+ }
+}
diff --git a/src/lombok/agent/eclipse/EclipseParserPatcher.java b/src_eclipseagent/lombok/agent/eclipse/EclipseParserPatcher.java
index abe26683..abe26683 100644
--- a/src/lombok/agent/eclipse/EclipseParserPatcher.java
+++ b/src_eclipseagent/lombok/agent/eclipse/EclipseParserPatcher.java
diff --git a/src_eclipseagent/lombok/agent/eclipse/EclipseParserTransformer.java b/src_eclipseagent/lombok/agent/eclipse/EclipseParserTransformer.java
new file mode 100644
index 00000000..803d5d66
--- /dev/null
+++ b/src_eclipseagent/lombok/agent/eclipse/EclipseParserTransformer.java
@@ -0,0 +1,157 @@
+package lombok.agent.eclipse;
+
+import java.lang.reflect.Constructor;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.objectweb.asm.ClassAdapter;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodAdapter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+class EclipseParserTransformer {
+ private static final String COMPILER_PKG =
+ "Lorg/eclipse/jdt/internal/compiler/ast/";
+ private static final String TARGET_STATIC_CLASS = "java/lombok/ClassLoaderWorkaround";
+ private static final String TARGET_STATIC_METHOD_DESC = "(Ljava/lang/Object;Ljava/lang/Object;)V";
+
+ private static final Map<String, Class<? extends MethodVisitor>> rewriters;
+
+ static {
+ Map<String, Class<? extends MethodVisitor>> map = new HashMap<String, Class<? extends MethodVisitor>>();
+ map.put(String.format("endParse(I)%sCompilationUnitDeclaration;", COMPILER_PKG), EndParsePatcher.class);
+ map.put(String.format("parse(%1$sMethodDeclaration;%1$sCompilationUnitDeclaration;)V", COMPILER_PKG), ParseMethodPatcher.class);
+ map.put(String.format("parse(%1$sConstructorDeclaration;%1$sCompilationUnitDeclaration;Z)V", COMPILER_PKG), ParseConstructorPatcher.class);
+ map.put(String.format("parse(%1$sInitializer;%1$sTypeDeclaration;%1$sCompilationUnitDeclaration;)V", COMPILER_PKG), ParseInitializerPatcher.class);
+ rewriters = Collections.unmodifiableMap(map);
+ }
+
+ 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();
+ }
+
+ public static RuntimeException sneakyThrow(Throwable t) {
+ if ( t == null ) throw new NullPointerException("t");
+ EclipseParserTransformer.<RuntimeException>sneakyThrow0(t);
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T extends Throwable> void sneakyThrow0(Throwable t) throws T {
+ throw (T)t;
+ }
+
+ 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);
+ Class<? extends MethodVisitor> targetVisitorClass = rewriters.get(name+desc);
+ if ( targetVisitorClass == null ) return writerVisitor;
+
+ try {
+ Constructor<? extends MethodVisitor> c = targetVisitorClass.getDeclaredConstructor(MethodVisitor.class);
+ c.setAccessible(true);
+ return c.newInstance(writerVisitor);
+ } catch ( Exception e ) {
+ //NoSuchMethodException: We know they exist.
+ //InvocationTargetException: No checked exceptions thrown by any compilers.
+ //IllegalAccessException: We called setAccessible.
+ //InstantiationException: None of these classes are abstract.
+ throw sneakyThrow(e);
+ }
+ }
+ }
+
+ private static final int BIT24 = 0x800000;
+
+ static class ParseBlockContainerPatcher extends MethodAdapter {
+ private final String staticMethodName;
+
+ ParseBlockContainerPatcher(MethodVisitor mv, String staticMethodName) {
+ super(mv);
+ this.staticMethodName = staticMethodName;
+ }
+
+ @Override public void visitCode() {
+ //injects: if ( constructorDeclaration.bits & BIT24 > 0 ) return;
+ mv.visitVarInsn(Opcodes.ALOAD, 1);
+ mv.visitFieldInsn(Opcodes.GETFIELD, "org/eclipse/jdt/internal/compiler/ast/ASTNode", "bits", "I");
+ mv.visitLdcInsn(Integer.valueOf(BIT24));
+ mv.visitInsn(Opcodes.IAND);
+ Label l0 = new Label();
+ mv.visitJumpInsn(Opcodes.IFLE, l0);
+ mv.visitInsn(Opcodes.RETURN);
+ mv.visitLabel(l0);
+ mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+ super.visitCode();
+ }
+
+ @Override public void visitInsn(int opcode) {
+ if ( opcode == Opcodes.RETURN ) {
+ //injects: ClassLoaderWorkaround.transformConstructorDeclaration(parser, constructorDeclaration);
+ super.visitVarInsn(Opcodes.ALOAD, 0);
+ super.visitVarInsn(Opcodes.ALOAD, 1);
+ super.visitMethodInsn(Opcodes.INVOKESTATIC, TARGET_STATIC_CLASS,
+ staticMethodName, TARGET_STATIC_METHOD_DESC);
+ }
+ }
+ }
+
+ static class ParseConstructorPatcher extends ParseBlockContainerPatcher {
+ public ParseConstructorPatcher(MethodVisitor mv) {
+ super(mv, "transformConstructorDeclaration");
+ }
+ }
+
+ static class ParseMethodPatcher extends ParseBlockContainerPatcher {
+ public ParseMethodPatcher(MethodVisitor mv) {
+ super(mv, "transformMethodDeclaration");
+ }
+ }
+
+ static class ParseInitializerPatcher extends ParseBlockContainerPatcher {
+ public ParseInitializerPatcher(MethodVisitor mv) {
+ super(mv, "transformInitializer");
+ }
+ }
+
+ static class EndParsePatcher extends MethodAdapter {
+ private static final String TARGET_STATIC_METHOD_NAME = "transformCompilationUnitDeclaration";
+
+ EndParsePatcher(MethodVisitor mv) {
+ super(mv);
+ }
+
+ @Override public void visitInsn(int opcode) {
+ if ( opcode == Opcodes.ARETURN ) {
+ //injects: ClassLoaderWorkaround.transformCUD(parser, compilationUnitDeclaration);
+ super.visitInsn(Opcodes.DUP);
+ super.visitVarInsn(Opcodes.ALOAD, 0);
+ super.visitInsn(Opcodes.SWAP);
+ super.visitMethodInsn(Opcodes.INVOKESTATIC, TARGET_STATIC_CLASS,
+ TARGET_STATIC_METHOD_NAME, TARGET_STATIC_METHOD_DESC);
+ }
+
+ super.visitInsn(opcode);
+ }
+ }
+}