diff options
-rw-r--r-- | src/core/lombok/eclipse/EclipseNode.java | 2 | ||||
-rw-r--r-- | src/core/lombok/eclipse/HandlerLibrary.java | 23 | ||||
-rw-r--r-- | src/core/lombok/eclipse/TransformEclipseAST.java | 22 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java | 23 | ||||
-rw-r--r-- | src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java | 13 | ||||
-rw-r--r-- | src/eclipseAgent/lombok/eclipse/agent/Issue164Fixer.java | 93 |
6 files changed, 17 insertions, 159 deletions
diff --git a/src/core/lombok/eclipse/EclipseNode.java b/src/core/lombok/eclipse/EclipseNode.java index 62238a1c..d281b515 100644 --- a/src/core/lombok/eclipse/EclipseNode.java +++ b/src/core/lombok/eclipse/EclipseNode.java @@ -111,7 +111,7 @@ public class EclipseNode extends lombok.core.LombokNode<EclipseAST, EclipseNode, visitor.visitAnnotationOnLocal((LocalDeclaration)parent.get(), this, (Annotation)get()); break; default: - throw new AssertionError("Annotion not expected as child of a " + up().getKind()); + throw new AssertionError("Annotation not expected as child of a " + up().getKind()); } break; case STATEMENT: diff --git a/src/core/lombok/eclipse/HandlerLibrary.java b/src/core/lombok/eclipse/HandlerLibrary.java index dc082a8d..b6684c2f 100644 --- a/src/core/lombok/eclipse/HandlerLibrary.java +++ b/src/core/lombok/eclipse/HandlerLibrary.java @@ -89,8 +89,6 @@ public class HandlerLibrary { private Collection<EclipseASTVisitor> visitorHandlers = new ArrayList<EclipseASTVisitor>(); - private boolean skipPrintAST; - /** * Creates a new HandlerLibrary. Errors will be reported to the Eclipse Error log. * then uses SPI discovery to load all annotation and visitor based handlers so that future calls @@ -170,16 +168,17 @@ public class HandlerLibrary { * @param annotationNode The Lombok AST Node representing the Annotation AST Node. * @param annotation 'node.get()' - convenience parameter. */ - public void handleAnnotation(CompilationUnitDeclaration ast, EclipseNode annotationNode, org.eclipse.jdt.internal.compiler.ast.Annotation annotation) { + public void handleAnnotation(CompilationUnitDeclaration ast, EclipseNode annotationNode, org.eclipse.jdt.internal.compiler.ast.Annotation annotation, boolean skipPrintAst) { String pkgName = annotationNode.getPackageDeclaration(); Collection<String> imports = annotationNode.getImportStatements(); TypeResolver resolver = new TypeResolver(typeLibrary, pkgName, imports); TypeReference rawType = annotation.type; if (rawType == null) return; + for (String fqn : resolver.findTypeMatches(annotationNode, toQualifiedName(annotation.type.getTypeName()))) { boolean isPrintAST = fqn.equals(PrintAST.class.getName()); - if (isPrintAST == skipPrintAST) continue; + if (isPrintAST == skipPrintAst) continue; AnnotationHandlerContainer<?> container = annotationHandlers.get(fqn); if (container == null) continue; @@ -209,20 +208,4 @@ public class HandlerLibrary { String.format("Lombok visitor handler %s failed", visitor.getClass()), t); } } - - /** - * Lombok does not currently support triggering annotations in a specified order; the order is essentially - * random right now. This lack of order is particularly annoying for the {@code PrintAST} annotation, - * which is almost always intended to run last. Hence, this hack, which lets it in fact run last. - * - * @see #skipAllButPrintAST() - */ - public void skipPrintAST() { - skipPrintAST = true; - } - - /** @see #skipPrintAST() */ - public void skipAllButPrintAST() { - skipPrintAST = false; - } } diff --git a/src/core/lombok/eclipse/TransformEclipseAST.java b/src/core/lombok/eclipse/TransformEclipseAST.java index b362f399..c91299bb 100644 --- a/src/core/lombok/eclipse/TransformEclipseAST.java +++ b/src/core/lombok/eclipse/TransformEclipseAST.java @@ -163,41 +163,45 @@ public class TransformEclipseAST { * then handles any PrintASTs. */ public void go() { - handlers.skipPrintAST(); - ast.traverse(new AnnotationVisitor()); + ast.traverse(new AnnotationVisitor(true)); handlers.callASTVisitors(ast); - handlers.skipAllButPrintAST(); - ast.traverse(new AnnotationVisitor()); + ast.traverse(new AnnotationVisitor(false)); } private static class AnnotationVisitor extends EclipseASTAdapter { + private final boolean skipPrintAst; + + public AnnotationVisitor(boolean skipAllButPrintAST) { + this.skipPrintAst = skipAllButPrintAST; + } + public boolean deferUntilPostDiet() { return false; } @Override public void visitAnnotationOnField(FieldDeclaration field, EclipseNode annotationNode, Annotation annotation) { CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get(); - handlers.handleAnnotation(top, annotationNode, annotation); + handlers.handleAnnotation(top, annotationNode, annotation, skipPrintAst); } @Override public void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, EclipseNode annotationNode, Annotation annotation) { CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get(); - handlers.handleAnnotation(top, annotationNode, annotation); + handlers.handleAnnotation(top, annotationNode, annotation, skipPrintAst); } @Override public void visitAnnotationOnLocal(LocalDeclaration local, EclipseNode annotationNode, Annotation annotation) { CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get(); - handlers.handleAnnotation(top, annotationNode, annotation); + handlers.handleAnnotation(top, annotationNode, annotation, skipPrintAst); } @Override public void visitAnnotationOnMethod(AbstractMethodDeclaration method, EclipseNode annotationNode, Annotation annotation) { CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get(); - handlers.handleAnnotation(top, annotationNode, annotation); + handlers.handleAnnotation(top, annotationNode, annotation, skipPrintAst); } @Override public void visitAnnotationOnType(TypeDeclaration type, EclipseNode annotationNode, Annotation annotation) { CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get(); - handlers.handleAnnotation(top, annotationNode, annotation); + handlers.handleAnnotation(top, annotationNode, annotation, skipPrintAst); } } } diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 45d58df3..6dbdfb18 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -25,7 +25,6 @@ import static lombok.eclipse.Eclipse.*; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; @@ -38,7 +37,6 @@ import lombok.Getter; import lombok.Lombok; import lombok.core.AnnotationValues; import lombok.core.AST.Kind; -import lombok.core.debug.DebugSnapshotStore; import lombok.core.handlers.TransformationsUtil; import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseNode; @@ -451,27 +449,6 @@ public class EclipseHandlerUtil { method.annotations = createSuppressWarningsAll(method, method.annotations); TypeDeclaration parent = (TypeDeclaration) type.get(); - if (parent.scope != null && method.scope == null) { - // We think this means heisenbug #164 is about to happen later in some other worker thread. - // To improve our ability to figure out what the heck is going on, let's generate a log so we can ask those who stumble on this about it, - // and thus see a far more useful stack trace. - boolean report = true; - for (StackTraceElement elem : Thread.currentThread().getStackTrace()) { - // We intentionally hook into the middle of ClassScope filling in BlockScopes for PatchDelegate, - // meaning that will trigger a false positive. Detect it and do not report the occurence of #164 if so. - if ("lombok.eclipse.agent.PatchDelegate".equals(elem.getClassName())) { - report = false; - break; - } - } - - if (report) { - CompilationUnitDeclaration cud = (CompilationUnitDeclaration) type.top().get(); - String logFileLocation = DebugSnapshotStore.INSTANCE.print(cud, "Printing: injecting whilst scope is already built."); - Eclipse.warning("We believe you may have stumbled on issue 164. Please upload file " + logFileLocation + " to: http://code.google.com/p/projectlombok/issues/detail?id=164", new Throwable()); - } - } - if (parent.methods == null) { parent.methods = new AbstractMethodDeclaration[1]; parent.methods[0] = method; diff --git a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java index f67bd4e3..c49346bc 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java +++ b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java @@ -21,15 +21,11 @@ */ package lombok.eclipse.agent; -import java.lang.instrument.ClassFileTransformer; -import java.lang.instrument.IllegalClassFormatException; import java.lang.instrument.Instrumentation; -import java.security.ProtectionDomain; import java.util.Collection; import java.util.Collections; import java.util.List; -import lombok.bytecode.ClassFileMetaData; import lombok.core.Agent; import lombok.patcher.Hook; import lombok.patcher.MethodTarget; @@ -72,15 +68,6 @@ public class EclipsePatcher extends Agent { else ecj = injected; registerPatchScripts(instrumentation, injected, ecj); - instrumentation.addTransformer(new ClassFileTransformer() { - @Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { - ClassFileMetaData meta = new ClassFileMetaData(classfileBuffer); - if (meta.usesField("org/eclipse/jdt/internal/compiler/ast/TypeDeclaration", "scope")) { - return Issue164Fixer.fix(classfileBuffer); - } - return null; - } - }, true); } private static void registerPatchScripts(Instrumentation instrumentation, boolean reloadExistingClasses, boolean ecjOnly) { diff --git a/src/eclipseAgent/lombok/eclipse/agent/Issue164Fixer.java b/src/eclipseAgent/lombok/eclipse/agent/Issue164Fixer.java deleted file mode 100644 index 65e04e44..00000000 --- a/src/eclipseAgent/lombok/eclipse/agent/Issue164Fixer.java +++ /dev/null @@ -1,93 +0,0 @@ -package lombok.eclipse.agent; - -import lombok.core.debug.DebugSnapshotStore; - -import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; -import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; -import org.eclipse.jdt.internal.compiler.lookup.ClassScope; -import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope; -import org.eclipse.jdt.internal.compiler.lookup.Scope; -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; -import org.objectweb.asm.commons.JSRInlinerAdapter; - -public class Issue164Fixer { - public static byte[] fix(byte[] classfileBuffer) { - return runAsm(classfileBuffer, true); - } - - static class FixedClassWriter extends ClassWriter { - FixedClassWriter(ClassReader classReader, int flags) { - super(classReader, flags); - } - - @Override protected String getCommonSuperClass(String type1, String type2) { - //By default, ASM will attempt to live-load the class types, which will fail if meddling with classes in an - //environment with custom classloaders, such as Equinox. It's just an optimization; returning Object is always legal. - try { - return super.getCommonSuperClass(type1, type2); - } catch (Exception e) { - return "java/lang/Object"; - } - } - } - - public static void catchScopeSet(TypeDeclaration typeDeclaration, ClassScope scope) { - typeDeclaration.scope = scope; - Scope sc = scope; - while (sc != null && !(sc instanceof CompilationUnitScope)) { - sc = sc.parent; - } - - if (sc instanceof CompilationUnitScope) { - CompilationUnitDeclaration cud = ((CompilationUnitScope) sc).referenceContext; - DebugSnapshotStore.INSTANCE.snapshot(cud, "Scope is being set"); - } - } - - /** - * Runs ASM on the provider byteCode, chaining a reader to a writer and using the {@code ClassVisitor} you yourself provide - * via the {@see #createClassVisitor(ClassWriter)} method as the filter. - */ - protected static byte[] runAsm(byte[] byteCode, boolean computeFrames) { - byte[] fixedByteCode = fixJSRInlining(byteCode); - - ClassReader reader = new ClassReader(fixedByteCode); - ClassWriter writer = new FixedClassWriter(reader, computeFrames ? ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES : 0); - - ClassVisitor visitor = new ClassAdapter(writer) { - @Override public MethodVisitor visitMethod(int access, final String mName, String desc, String signature, String[] exceptions) { - return new MethodAdapter(super.visitMethod(access, mName, desc, signature, exceptions)) { - @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { - if (opcode == Opcodes.PUTFIELD && "org/eclipse/jdt/internal/compiler/ast/TypeDeclaration".equals(owner) && "scope".equals(name) && !"catchScopeSet".equals(mName)) { - super.visitMethodInsn(Opcodes.INVOKESTATIC, "lombok/eclipse/agent/Issue164Fixer", "catchScopeSet", "(Lorg/eclipse/jdt/internal/compiler/ast/TypeDeclaration;Lorg/eclipse/jdt/internal/compiler/lookup/ClassScope;)V"); - } else { - super.visitFieldInsn(opcode, owner, name, desc); - } - } - }; - } - }; - reader.accept(visitor, 0); - return writer.toByteArray(); - } - - protected static byte[] fixJSRInlining(byte[] byteCode) { - ClassReader reader = new ClassReader(byteCode); - ClassWriter writer = new FixedClassWriter(reader, 0); - - ClassVisitor visitor = new ClassAdapter(writer) { - @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - return new JSRInlinerAdapter(super.visitMethod(access, name, desc, signature, exceptions), access, name, desc, signature, exceptions); - } - }; - - reader.accept(visitor, 0); - return writer.toByteArray(); - } -} |