diff options
Diffstat (limited to 'src/eclipseAgent/lombok/eclipse/agent/PatchVal.java')
| -rw-r--r-- | src/eclipseAgent/lombok/eclipse/agent/PatchVal.java | 88 | 
1 files changed, 65 insertions, 23 deletions
| diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java index 30574ea6..3da37869 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java @@ -1,5 +1,5 @@  /* - * Copyright (C) 2010-2011 The Project Lombok Authors. + * Copyright (C) 2010-2018 The Project Lombok Authors.   *    * Permission is hereby granted, free of charge, to any person obtaining a copy   * of this software and associated documentation files (the "Software"), to deal @@ -21,11 +21,6 @@   */  package lombok.eclipse.agent; -import static lombok.eclipse.handlers.EclipseHandlerUtil.*; -import static lombok.eclipse.Eclipse.*; - -import java.lang.reflect.Field; -  import org.eclipse.jdt.internal.compiler.ast.Annotation;  import org.eclipse.jdt.internal.compiler.ast.Expression;  import org.eclipse.jdt.internal.compiler.ast.ForeachStatement; @@ -43,6 +38,11 @@ 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 java.lang.reflect.Field; + +import static lombok.eclipse.Eclipse.poss; +import static lombok.eclipse.handlers.EclipseHandlerUtil.makeType; +  public class PatchVal {  	// This is half of the work for 'val' support - the other half is in PatchValEclipse. This half is enough for ecj. @@ -57,6 +57,9 @@ public class PatchVal {  			return expr.resolveType(scope);  		} catch (NullPointerException e) {  			return null; +		} catch (ArrayIndexOutOfBoundsException e) { +			// This will occur internally due to for example 'val x = mth("X");', where mth takes 2 arguments. +			return null;  		}  	} @@ -66,6 +69,9 @@ public class PatchVal {  			return expr.resolveType(scope);  		} catch (NullPointerException e) {  			return null; +		} catch (ArrayIndexOutOfBoundsException e) { +			// This will occur internally due to for example 'val x = mth("X");', where mth takes 2 arguments. +			return null;  		}  	} @@ -78,31 +84,44 @@ public class PatchVal {  		return true;  	} -	public static boolean couldBeVal(TypeReference ref) { +	public static boolean couldBe(String key, TypeReference ref) { +		String[] keyParts = key.split("\\.");  		if (ref instanceof SingleTypeReference) {  			char[] token = ((SingleTypeReference)ref).token; -			return matches("val", token); +			return matches(keyParts[keyParts.length - 1], token);  		}  		if (ref instanceof QualifiedTypeReference) {  			char[][] tokens = ((QualifiedTypeReference)ref).tokens; -			if (tokens == null || tokens.length != 2) return false; -			return matches("lombok", tokens[0]) && matches("val", tokens[1]); +			if (keyParts.length != tokens.length) return false; +			for(int i = 0; i < tokens.length; ++i) { +				String part = keyParts[i]; +				char[] token = tokens[i]; +				if (!matches(part, token)) return false; +			} +			return true;  		}  		return false;  	} -	 -	private static boolean isVal(TypeReference ref, BlockScope scope) { -		if (!couldBeVal(ref)) return false; -		 + +	private static boolean is(TypeReference ref, BlockScope scope, String key) { +		if (!couldBe(key, ref)) return false; +  		TypeBinding resolvedType = ref.resolvedType;  		if (resolvedType == null) resolvedType = ref.resolveType(scope, false);  		if (resolvedType == null) return false;  		char[] pkg = resolvedType.qualifiedPackageName();  		char[] nm = resolvedType.qualifiedSourceName(); -		return matches("lombok", pkg) && matches("val", nm); +		int pkgFullLength = pkg.length > 0 ? pkg.length + 1: 0; +		char[] fullName = new char[pkgFullLength + nm.length]; +		if(pkg.length > 0) { +			System.arraycopy(pkg, 0, fullName, 0, pkg.length); +			fullName[pkg.length] = '.'; +		} +		System.arraycopy(nm, 0, fullName, pkgFullLength, nm.length); +		return matches(key, fullName);  	}  	public static final class Reflection { @@ -126,13 +145,17 @@ public class PatchVal {  		if (local == null || !LocalDeclaration.class.equals(local.getClass())) return false;  		boolean decomponent = false; -		if (!isVal(local.type, scope)) return false; +        boolean val = isVal(local, scope); +        boolean var = isVar(local, scope); +        if (!(val || var)) return false;  		StackTraceElement[] st = new Throwable().getStackTrace();  		for (int i = 0; i < st.length - 2 && i < 10; i++) {  			if (st[i].getClassName().equals("lombok.launch.PatchFixesHider$Val")) { -				if (st[i + 1].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.LocalDeclaration") && -					st[i + 2].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.ForStatement")) return false; +				boolean valInForStatement = val && +						st[i + 1].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.LocalDeclaration") && +						st[i + 2].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.ForStatement"); +				if (valInForStatement) return false;  				break;  			}  		} @@ -164,7 +187,7 @@ public class PatchVal {  			TypeBinding resolved = null;  			try { -				resolved = decomponent ? getForEachComponentType(init, scope) : init.resolveType(scope); +				resolved = decomponent ? getForEachComponentType(init, scope) : resolveForExpression(init, scope);  			} catch (NullPointerException e) {  				// This definitely occurs if as part of resolving the initializer expression, a  				// lambda expression in it must also be resolved (such as when lambdas are part of @@ -181,23 +204,33 @@ public class PatchVal {  			}  		} -		local.modifiers |= ClassFileConstants.AccFinal; +		if(val) local.modifiers |= ClassFileConstants.AccFinal;  		local.annotations = addValAnnotation(local.annotations, local.type, scope);  		local.type = replacement != null ? replacement : new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, poss(local.type, 3));  		return false;  	} +	private static boolean isVar(LocalDeclaration local, BlockScope scope) { +		return is(local.type, scope, "lombok.experimental.var") || is(local.type, scope, "lombok.var"); +	} +	 +	private static boolean isVal(LocalDeclaration local, BlockScope scope) { +		return is(local.type, scope, "lombok.val"); +	} +	  	public static boolean handleValForForEach(ForeachStatement forEach, BlockScope scope) {  		if (forEach.elementVariable == null) return false; -		if (!isVal(forEach.elementVariable.type, scope)) return false; +		boolean val = isVal(forEach.elementVariable, scope); +		boolean var = isVar(forEach.elementVariable, scope); +        if (!(val || var)) return false;  		TypeBinding component = getForEachComponentType(forEach.collection, scope);  		if (component == null) return false;  		TypeReference replacement = makeType(component, forEach.elementVariable.type, false); -		forEach.elementVariable.modifiers |= ClassFileConstants.AccFinal; +		if (val) forEach.elementVariable.modifiers |= ClassFileConstants.AccFinal;  		forEach.elementVariable.annotations = addValAnnotation(forEach.elementVariable.annotations, forEach.elementVariable.type, scope);  		forEach.elementVariable.type = replacement != null ? replacement :  				new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, poss(forEach.elementVariable.type, 3)); @@ -222,7 +255,7 @@ public class PatchVal {  	private static TypeBinding getForEachComponentType(Expression collection, BlockScope scope) {  		if (collection != null) {  			TypeBinding resolved = collection.resolvedType; -			if (resolved == null) resolved = collection.resolveType(scope); +			if (resolved == null) resolved = resolveForExpression(collection, scope);  			if (resolved == null) return null;  			if (resolved.isArrayType()) {  				resolved = ((ArrayBinding) resolved).elementsType(); @@ -250,4 +283,13 @@ public class PatchVal {  		return null;  	} +	 +	private static TypeBinding resolveForExpression(Expression collection, BlockScope scope) { +		try { +			return collection.resolveType(scope); +		} catch (ArrayIndexOutOfBoundsException e) { +			// Known cause of issues; for example: val e = mth("X"), where mth takes 2 arguments. +			return null; +		} +	}  } | 
