aboutsummaryrefslogtreecommitdiff
path: root/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java
diff options
context:
space:
mode:
authorReinier Zwitserloot <reinier@zwitserloot.com>2010-11-08 22:32:22 +0100
committerReinier Zwitserloot <reinier@zwitserloot.com>2010-11-08 22:52:07 +0100
commitcc60afa1eb4b14998e72c4fd5adf9def32e0e0f8 (patch)
treecae9a00aa7e5f8cfa08adfe22f3da98c5e0fcb4a /src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java
parentdee834a39780f61a0357c42f61592cd3c3598bd3 (diff)
downloadlombok-cc60afa1eb4b14998e72c4fd5adf9def32e0e0f8.tar.gz
lombok-cc60afa1eb4b14998e72c4fd5adf9def32e0e0f8.tar.bz2
lombok-cc60afa1eb4b14998e72c4fd5adf9def32e0e0f8.zip
'val' now also works in foreach loops, on both javac and ecj / eclipse.
Diffstat (limited to 'src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java')
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java121
1 files changed, 110 insertions, 11 deletions
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java b/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java
index 14687e32..32335ecc 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java
@@ -38,14 +38,20 @@ import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.parser.Parser;
public class PatchFixes {
@@ -140,18 +146,54 @@ public class PatchFixes {
return new BufferedOutputStream(PostCompiler.wrapOutputStream(out, fileName, DiagnosticsReceiver.CONSOLE));
}
+ private static Field astStackField, astPtrField;
+
+ static {
+ try {
+ astStackField = Parser.class.getDeclaredField("astStack");
+ astStackField.setAccessible(true);
+ astPtrField = Parser.class.getDeclaredField("astPtr");
+ astPtrField.setAccessible(true);
+ } catch (Exception e) {
+ // Most likely we're in ecj or some other plugin usage of the eclipse compiler. No need for this.
+ }
+ }
+
+ public static void copyInitializationOfForEachIterable(Parser parser) {
+ ASTNode[] astStack;
+ int astPtr;
+ try {
+ astStack = (ASTNode[]) astStackField.get(parser);
+ astPtr = (Integer)astPtrField.get(parser);
+ } catch (Exception e) {
+ // Most likely we're in ecj or some other plugin usage of the eclipse compiler. No need for this.
+ return;
+ }
+
+ ForeachStatement foreachDecl = (ForeachStatement) astStack[astPtr];
+ ASTNode init = foreachDecl.collection;
+ if (init == null) return;
+ if (foreachDecl.elementVariable != null && foreachDecl.elementVariable.type instanceof SingleTypeReference) {
+ SingleTypeReference ref = (SingleTypeReference) foreachDecl.elementVariable.type;
+ if (ref.token == null || ref.token.length != 3 || ref.token[0] != 'v' || ref.token[1] != 'a' || ref.token[2] != 'l') return;
+ } else return;
+
+ try {
+ if (iterableCopyField != null) iterableCopyField.set(foreachDecl.elementVariable, init);
+ } catch (Exception e) {
+ // In ecj mode this field isn't there and we don't need the copy anyway, so, we ignore the exception.
+ }
+ }
+
public static void copyInitializationOfLocalDeclarationForVal(Parser parser) {
ASTNode[] astStack;
int astPtr;
try {
- Field astStackF = Parser.class.getDeclaredField("astStack");
- astStackF.setAccessible(true);
- astStack = (ASTNode[]) astStackF.get(parser);
- Field astPtrF = Parser.class.getDeclaredField("astPtr");
- astPtrF.setAccessible(true);
- astPtr = (Integer)astPtrF.get(parser);
+ astStack = (ASTNode[]) astStackField.get(parser);
+ astPtr = (Integer)astPtrField.get(parser);
} catch (Exception e) {
- throw new RuntimeException(e);
+ // Most likely we're in ecj or some other plugin usage of the eclipse compiler. No need for this.
+ return;
}
AbstractVariableDeclaration variableDecl = (AbstractVariableDeclaration) astStack[astPtr];
if (!(variableDecl instanceof LocalDeclaration)) return;
@@ -165,22 +207,69 @@ public class PatchFixes {
try {
if (initCopyField != null) initCopyField.set(variableDecl, init);
} catch (Exception e) {
- e.printStackTrace(System.out);
// In ecj mode this field isn't there and we don't need the copy anyway, so, we ignore the exception.
}
}
- private static Field initCopyField;
+ private static Field initCopyField, iterableCopyField;
static {
try {
initCopyField = LocalDeclaration.class.getDeclaredField("$initCopy");
+ iterableCopyField = LocalDeclaration.class.getDeclaredField("$iterableCopy");
} catch (Throwable t) {
//ignore - no $initCopy exists when running in ecj.
}
}
+ public static boolean handleValForForEach(ForeachStatement forEach, BlockScope scope) {
+ if (forEach.elementVariable != null && forEach.elementVariable.type instanceof SingleTypeReference) {
+ char[] token = ((SingleTypeReference)forEach.elementVariable.type).token;
+ if (token == null || token.length != 3) return false;
+ else if (token[0] != 'v' || token[1] != 'a' || token[2] != 'l') return false;
+ } else return false;
+
+ TypeBinding component = getForEachComponentType(forEach.collection, scope);
+ TypeReference replacement = Eclipse.makeType(component, forEach.elementVariable.type, false);
+
+ forEach.elementVariable.modifiers |= ClassFileConstants.AccFinal;
+ forEach.elementVariable.type = replacement != null ? replacement :
+ new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, Eclipse.poss(forEach.elementVariable.type, 3));
+
+ return false;
+ }
+
+ private static TypeBinding getForEachComponentType(Expression collection, BlockScope scope) {
+ if (collection != null) {
+ TypeBinding resolved = collection.resolveType(scope);
+ if (resolved.isArrayType()) {
+ resolved = ((ArrayBinding) resolved).elementsType();
+ return resolved;
+ } else if (resolved instanceof ReferenceBinding) {
+ ReferenceBinding iterableType = ((ReferenceBinding)resolved).findSuperTypeOriginatingFrom(TypeIds.T_JavaLangIterable, false);
+
+ TypeBinding[] arguments = null;
+ if (iterableType != null) switch (iterableType.kind()) {
+ case Binding.GENERIC_TYPE : // for (T t : Iterable<T>) - in case used inside Iterable itself
+ arguments = iterableType.typeVariables();
+ break;
+ case Binding.PARAMETERIZED_TYPE : // for(E e : Iterable<E>)
+ arguments = ((ParameterizedTypeBinding)iterableType).arguments;
+ break;
+ }
+
+ if (arguments != null && arguments.length == 1) {
+ return arguments[0];
+ }
+ }
+ }
+
+ return null;
+ }
+
public static boolean handleValForLocalDeclaration(LocalDeclaration local, BlockScope scope) {
+ boolean decomponent = false;
+
if (local.type instanceof SingleTypeReference) {
char[] token = ((SingleTypeReference)local.type).token;
if (token == null || token.length != 3) return false;
@@ -192,13 +281,23 @@ public class PatchFixes {
try {
init = (Expression) initCopyField.get(local);
} catch (Exception e) {
- throw new RuntimeException(e);
+ }
+ }
+
+ if (init == null && iterableCopyField != null) {
+ try {
+ init = (Expression) iterableCopyField.get(local);
+ decomponent = true;
+ } catch (Exception e) {
}
}
TypeReference replacement = null;
+ if (init != null && decomponent) {
+ }
+
if (init != null) {
- TypeBinding resolved = init.resolveType(scope);
+ TypeBinding resolved = decomponent ? getForEachComponentType(init, scope) : init.resolveType(scope);
if (resolved != null) {
replacement = Eclipse.makeType(resolved, local.type, false);
}