aboutsummaryrefslogtreecommitdiff
path: root/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java')
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java115
1 files changed, 111 insertions, 4 deletions
diff --git a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
index ea53835a..f28ba5a1 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker.
+ * Copyright © 2009-2011 Reinier Zwitserloot and Roel Spilker.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -43,9 +43,31 @@ import lombok.patcher.scripts.ScriptBuilder;
* transformed.
*/
public class EclipsePatcher extends Agent {
+ // At some point I'd like the agent to be capable of auto-detecting if its on eclipse or on ecj. This class is a sure sign we're not in ecj but in eclipse. -ReinierZ
+ @SuppressWarnings("unused")
+ private static final String ECLIPSE_SIGNATURE_CLASS = "org/eclipse/core/runtime/adaptor/EclipseStarter";
+
@Override
public void runAgent(String agentArgs, Instrumentation instrumentation, boolean injected) throws Exception {
- registerPatchScripts(instrumentation, injected, injected);
+ String[] args = agentArgs == null ? new String[0] : agentArgs.split(":");
+ boolean forceEcj = false;
+ boolean forceEclipse = false;
+ for (String arg : args) {
+ if (arg.trim().equalsIgnoreCase("ECJ")) forceEcj = true;
+ if (arg.trim().equalsIgnoreCase("ECLIPSE")) forceEclipse = true;
+ }
+ if (forceEcj && forceEclipse) {
+ forceEcj = false;
+ forceEclipse = false;
+ }
+
+ boolean ecj;
+
+ if (forceEcj) ecj = true;
+ else if (forceEclipse) ecj = false;
+ else ecj = injected;
+
+ registerPatchScripts(instrumentation, injected, ecj);
}
private static void registerPatchScripts(Instrumentation instrumentation, boolean reloadExistingClasses, boolean ecjOnly) {
@@ -274,8 +296,93 @@ public class EclipsePatcher extends Agent {
}
private static void patchEcjTransformers(ScriptManager sm, boolean ecj) {
- PatchDelegate.addPatches(sm, ecj);
- PatchVal.addPatches(sm, ecj);
+ addPatchesForDelegate(sm, ecj);
+ addPatchesForVal(sm);
+ if (!ecj) addPatchesForValEclipse(sm);
+ }
+
+ private static void addPatchesForDelegate(ScriptManager sm, boolean ecj) {
+ final String CLASSSCOPE_SIG = "org.eclipse.jdt.internal.compiler.lookup.ClassScope";
+
+ sm.addScript(ScriptBuilder.exitEarly()
+ .target(new MethodTarget(CLASSSCOPE_SIG, "buildFieldsAndMethods", "void"))
+ .request(StackRequest.THIS)
+ .decisionMethod(new Hook(PatchDelegate.class.getName(), "handleDelegateForType", "boolean", CLASSSCOPE_SIG))
+ .build());
+ }
+
+ private static void addPatchesForValEclipse(ScriptManager sm) {
+ final String LOCALDECLARATION_SIG = "org.eclipse.jdt.internal.compiler.ast.LocalDeclaration";
+ final String PARSER_SIG = "org.eclipse.jdt.internal.compiler.parser.Parser";
+ final String VARIABLEDECLARATIONSTATEMENT_SIG = "org.eclipse.jdt.core.dom.VariableDeclarationStatement";
+ final String ASTCONVERTER_SIG = "org.eclipse.jdt.core.dom.ASTConverter";
+
+ sm.addScript(ScriptBuilder.addField()
+ .fieldName("$initCopy")
+ .fieldType("Lorg/eclipse/jdt/internal/compiler/ast/ASTNode;")
+ .setPublic()
+ .setTransient()
+ .targetClass("org.eclipse.jdt.internal.compiler.ast.LocalDeclaration")
+ .build());
+
+ sm.addScript(ScriptBuilder.addField()
+ .fieldName("$iterableCopy")
+ .fieldType("Lorg/eclipse/jdt/internal/compiler/ast/ASTNode;")
+ .setPublic()
+ .setTransient()
+ .targetClass("org.eclipse.jdt.internal.compiler.ast.LocalDeclaration")
+ .build());
+
+ sm.addScript(ScriptBuilder.wrapReturnValue()
+ .target(new MethodTarget(PARSER_SIG, "consumeExitVariableWithInitialization", "void"))
+ .request(StackRequest.THIS)
+ .wrapMethod(new Hook("lombok.eclipse.agent.PatchVal", "copyInitializationOfLocalDeclaration", "void", PARSER_SIG))
+ .build());
+
+ sm.addScript(ScriptBuilder.wrapReturnValue()
+ .target(new MethodTarget(PARSER_SIG, "consumeEnhancedForStatementHeader", "void"))
+ .request(StackRequest.THIS)
+ .wrapMethod(new Hook("lombok.eclipse.agent.PatchVal", "copyInitializationOfForEachIterable", "void", PARSER_SIG))
+ .build());
+
+ sm.addScript(ScriptBuilder.wrapReturnValue()
+ .target(new MethodTarget(ASTCONVERTER_SIG, "setModifiers", "void", VARIABLEDECLARATIONSTATEMENT_SIG, LOCALDECLARATION_SIG))
+ .wrapMethod(new Hook("lombok.eclipse.agent.PatchVal", "addFinalAndValAnnotationToVariableDeclarationStatement",
+ "void", "java.lang.Object", VARIABLEDECLARATIONSTATEMENT_SIG, LOCALDECLARATION_SIG))
+ .transplant().request(StackRequest.THIS, StackRequest.PARAM1, StackRequest.PARAM2).build());
+ }
+
+ private static void addPatchesForVal(ScriptManager sm) {
+ final String LOCALDECLARATION_SIG = "org.eclipse.jdt.internal.compiler.ast.LocalDeclaration";
+ final String FOREACHSTATEMENT_SIG = "org.eclipse.jdt.internal.compiler.ast.ForeachStatement";
+ final String EXPRESSION_SIG = "org.eclipse.jdt.internal.compiler.ast.Expression";
+ final String BLOCKSCOPE_SIG = "org.eclipse.jdt.internal.compiler.lookup.BlockScope";
+ final String TYPEBINDING_SIG = "org.eclipse.jdt.internal.compiler.lookup.TypeBinding";
+
+ sm.addScript(ScriptBuilder.exitEarly()
+ .target(new MethodTarget(LOCALDECLARATION_SIG, "resolve", "void", BLOCKSCOPE_SIG))
+ .request(StackRequest.THIS, StackRequest.PARAM1)
+ .decisionMethod(new Hook("lombok.eclipse.agent.PatchVal", "handleValForLocalDeclaration", "boolean", LOCALDECLARATION_SIG, BLOCKSCOPE_SIG))
+ .build());
+
+ sm.addScript(ScriptBuilder.replaceMethodCall()
+ .target(new MethodTarget(LOCALDECLARATION_SIG, "resolve", "void", BLOCKSCOPE_SIG))
+ .methodToReplace(new Hook(EXPRESSION_SIG, "resolveType", TYPEBINDING_SIG, BLOCKSCOPE_SIG))
+ .requestExtra(StackRequest.THIS)
+ .replacementMethod(new Hook("lombok.eclipse.agent.PatchVal", "skipResolveInitializerIfAlreadyCalled2", TYPEBINDING_SIG, EXPRESSION_SIG, BLOCKSCOPE_SIG, LOCALDECLARATION_SIG))
+ .build());
+
+ sm.addScript(ScriptBuilder.replaceMethodCall()
+ .target(new MethodTarget(FOREACHSTATEMENT_SIG, "resolve", "void", BLOCKSCOPE_SIG))
+ .methodToReplace(new Hook(EXPRESSION_SIG, "resolveType", TYPEBINDING_SIG, BLOCKSCOPE_SIG))
+ .replacementMethod(new Hook("lombok.eclipse.agent.PatchVal", "skipResolveInitializerIfAlreadyCalled", TYPEBINDING_SIG, EXPRESSION_SIG, BLOCKSCOPE_SIG))
+ .build());
+
+ sm.addScript(ScriptBuilder.exitEarly()
+ .target(new MethodTarget(FOREACHSTATEMENT_SIG, "resolve", "void", BLOCKSCOPE_SIG))
+ .request(StackRequest.THIS, StackRequest.PARAM1)
+ .decisionMethod(new Hook("lombok.eclipse.agent.PatchVal", "handleValForForEach", "boolean", FOREACHSTATEMENT_SIG, BLOCKSCOPE_SIG))
+ .build());
}
private static void patchFixSourceTypeConverter(ScriptManager sm) {