diff options
-rw-r--r-- | src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java | 12 | ||||
-rw-r--r-- | src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java | 71 |
2 files changed, 66 insertions, 17 deletions
diff --git a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java index 21bf23f3..538fb564 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java +++ b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java @@ -123,9 +123,9 @@ public class EclipsePatcher extends Agent { "org.eclipse.jdt.core.dom.MethodDeclaration" )) .methodToWrap(new Hook("org.eclipse.jface.text.IDocument", "get", "java.lang.String", "int", "int")) - .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "getRealMethodDeclarationSource", "java.lang.String", "java.lang.String", "org.eclipse.jdt.core.dom.MethodDeclaration")) - .requestExtra(StackRequest.PARAM4) - .build()); + .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "getRealMethodDeclarationSource", "java.lang.String", "java.lang.String", "java.lang.Object", "org.eclipse.jdt.core.dom.MethodDeclaration")) + .requestExtra(StackRequest.THIS, StackRequest.PARAM4) + .transplant().build()); /* get real generated node in stead of a random one generated by the annotation */ sm.addScript(ScriptBuilder.replaceMethodCall() @@ -133,21 +133,21 @@ public class EclipsePatcher extends Agent { .target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.ExtractInterfaceProcessor", "createMethodComments")) .methodToReplace(new Hook("org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil", "getMethodDeclarationNode", "org.eclipse.jdt.core.dom.MethodDeclaration", "org.eclipse.jdt.core.IMethod", "org.eclipse.jdt.core.dom.CompilationUnit")) .replacementMethod(new Hook("lombok.eclipse.agent.PatchFixes", "getRealMethodDeclarationNode", "org.eclipse.jdt.core.dom.MethodDeclaration", "org.eclipse.jdt.core.IMethod", "org.eclipse.jdt.core.dom.CompilationUnit")) - .build()); + .transplant().build()); /* Do not add @Override's for generated methods */ sm.addScript(ScriptBuilder.exitEarly() .target(new MethodTarget("org.eclipse.jdt.core.dom.rewrite.ListRewrite", "insertFirst")) .decisionMethod(new Hook("lombok.eclipse.agent.PatchFixes", "isListRewriteOnGeneratedNode", "boolean", "org.eclipse.jdt.core.dom.rewrite.ListRewrite")) .request(StackRequest.THIS) - .build()); + .transplant().build()); /* Do not add comments for generated methods */ sm.addScript(ScriptBuilder.exitEarly() .target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.ExtractInterfaceProcessor", "createMethodComment")) .decisionMethod(new Hook("lombok.eclipse.agent.PatchFixes", "isGenerated", "boolean", "org.eclipse.jdt.core.dom.ASTNode")) .request(StackRequest.PARAM2) - .build()); + .transplant().build()); } private static void patchAboutDialog(ScriptManager sm) { diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java b/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java index c2ab45e0..65852687 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java @@ -27,6 +27,7 @@ import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Stack; @@ -41,7 +42,9 @@ import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.MethodDeclaration; +import org.eclipse.jdt.core.dom.Modifier; import org.eclipse.jdt.core.dom.SimpleName; +import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.core.dom.rewrite.NodeRewriteEvent; import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent; @@ -91,17 +94,23 @@ public class PatchFixes { return list; } - /* Very practical implementation, but works for getter and setter even with type parameters */ - public static java.lang.String getRealMethodDeclarationSource(java.lang.String original, org.eclipse.jdt.core.dom.MethodDeclaration declaration) { + public static java.lang.String getRealMethodDeclarationSource(java.lang.String original, Object processor, org.eclipse.jdt.core.dom.MethodDeclaration declaration) throws Exception { if (!isGenerated(declaration)) return original; - StringBuilder signature = new StringBuilder(); + List<org.eclipse.jdt.core.dom.Annotation> annotations = new ArrayList<org.eclipse.jdt.core.dom.Annotation>(); + for (Object modifier : declaration.modifiers()) { + if (modifier instanceof org.eclipse.jdt.core.dom.Annotation) { + org.eclipse.jdt.core.dom.Annotation annotation = (org.eclipse.jdt.core.dom.Annotation)modifier; + String qualifiedAnnotationName = annotation.resolveTypeBinding().getQualifiedName(); + if (!"java.lang.Override".equals(qualifiedAnnotationName) && !"java.lang.SuppressWarnings".equals(qualifiedAnnotationName)) annotations.add(annotation); + } + } - // We should get these from the refactor action - boolean needsPublic = true, needsAbstract = true; + StringBuilder signature = new StringBuilder(); + addAnnotations(annotations, signature); - if (needsPublic) signature.append("public "); - if (needsAbstract) signature.append("abstract "); + if ((Boolean)processor.getClass().getDeclaredField("fPublic").get(processor)) signature.append("public "); + if ((Boolean)processor.getClass().getDeclaredField("fAbstract").get(processor)) signature.append("abstract "); signature .append(declaration.getReturnType2().toString()) @@ -112,9 +121,7 @@ public class PatchFixes { for (Object parameter : declaration.parameters()) { if (!first) signature.append(", "); first = false; - // The annotations are still missing - // Note: what happens to imports for the annotations? - // I assume they have been taken care of by the default extraction system + // We should also add the annotations of the parameters signature.append(parameter); } @@ -122,6 +129,47 @@ public class PatchFixes { return signature.toString(); } + // part of getRealMethodDeclarationSource(...) + public static void addAnnotations(List<org.eclipse.jdt.core.dom.Annotation> annotations, StringBuilder signature) { + /* + * We SHOULD be able to handle the following cases: + * @Override + * @Override() + * @SuppressWarnings("all") + * @SuppressWarnings({"all", "unused"}) + * @SuppressWarnings(value = "all") + * @SuppressWarnings(value = {"all", "unused"}) + * @EqualsAndHashCode(callSuper=true, of="id") + * + * Currently, we only seem to correctly support: + * @Override + * @Override() N.B. We lose the parentheses here, since there are no values. No big deal. + * @SuppressWarnings("all") + */ + for (org.eclipse.jdt.core.dom.Annotation annotation : annotations) { + List<String> values = new ArrayList<String>(); + if (annotation.isSingleMemberAnnotation()) { + org.eclipse.jdt.core.dom.SingleMemberAnnotation smAnn = (org.eclipse.jdt.core.dom.SingleMemberAnnotation) annotation; + values.add(smAnn.getValue().toString()); + } else if (annotation.isNormalAnnotation()) { + org.eclipse.jdt.core.dom.NormalAnnotation normalAnn = (org.eclipse.jdt.core.dom.NormalAnnotation) annotation; + for (Object value : normalAnn.values()) values.add(value.toString()); + } + + signature.append("@").append(annotation.resolveTypeBinding().getQualifiedName()); + if (!values.isEmpty()) { + signature.append("("); + boolean first = true; + for (String string : values) { + if (!first) signature.append(", "); + first = false; + signature.append('"').append(string).append('"'); + } + signature.append(")"); + } + signature.append(" "); + } + } public static org.eclipse.jdt.core.dom.MethodDeclaration getRealMethodDeclarationNode(org.eclipse.jdt.core.IMethod sourceMethod, org.eclipse.jdt.core.dom.CompilationUnit cuUnit) throws JavaModelException { MethodDeclaration methodDeclarationNode = ASTNodeSearchUtil.getMethodDeclarationNode(sourceMethod, cuUnit); @@ -154,7 +202,8 @@ public class PatchFixes { return methodDeclarationNode; } - private static org.eclipse.jdt.core.dom.AbstractTypeDeclaration findTypeDeclaration(IType searchType, List<?> nodes) { + // part of getRealMethodDeclarationNode + public static org.eclipse.jdt.core.dom.AbstractTypeDeclaration findTypeDeclaration(IType searchType, List<?> nodes) { for (Object object : nodes) { if (object instanceof org.eclipse.jdt.core.dom.AbstractTypeDeclaration) { org.eclipse.jdt.core.dom.AbstractTypeDeclaration typeDeclaration = (org.eclipse.jdt.core.dom.AbstractTypeDeclaration) object; |