You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2018/02/05 01:47:12 UTC
groovy git commit: check for known immutables before checking for
handled cases plus minor refactoring
Repository: groovy
Updated Branches:
refs/heads/master 6f73fb997 -> c170300cd
check for known immutables before checking for handled cases plus minor refactoring
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/c170300c
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/c170300c
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/c170300c
Branch: refs/heads/master
Commit: c170300cdc8976ed0fed37bda412c7389e85971d
Parents: 6f73fb9
Author: paulk <pa...@asert.com.au>
Authored: Mon Feb 5 11:47:05 2018 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Mon Feb 5 11:47:05 2018 +1000
----------------------------------------------------------------------
.../transform/ImmutableASTTransformation.java | 116 +++++++++++--------
1 file changed, 70 insertions(+), 46 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/c170300c/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java
index 79c7c46..3e8fd8f 100644
--- a/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java
@@ -167,10 +167,9 @@ public class ImmutableASTTransformation extends AbstractASTTransformation {
"java.time.temporal.ValueRange",
"java.time.temporal.WeekFields"
));
- private static final Class MY_CLASS = ImmutableBase.class;
- private static final Class<? extends Annotation> KNOWN_IMMUTABLE_CLASS = KnownImmutable.class;
- private static final Class<? extends Annotation> IMMUTABLE_BASE_CLASS = ImmutableBase.class;
- private static final ClassNode IMMUTABLE_BASE_TYPE = makeWithoutCaching(IMMUTABLE_BASE_CLASS, false);
+ private static final String KNOWN_IMMUTABLE_NAME = KnownImmutable.class.getName();
+ private static final Class<? extends Annotation> MY_CLASS = ImmutableBase.class;
+ private static final ClassNode IMMUTABLE_BASE_TYPE = makeWithoutCaching(MY_CLASS, false);
public static final ClassNode MY_TYPE = make(MY_CLASS);
static final String MY_TYPE_NAME = "@" + MY_TYPE.getNameWithoutPackage();
private static final String MEMBER_KNOWN_IMMUTABLE_CLASSES = "knownImmutableClasses";
@@ -507,10 +506,10 @@ public class ImmutableASTTransformation extends AbstractASTTransformation {
FieldNode fNode = pNode.getField();
final ClassNode fieldType = fNode.getType();
Statement statement;
- if (fieldType.isArray() || isOrImplements(fieldType, CLONEABLE_TYPE)) {
- statement = createConstructorStatementArrayOrCloneable(fNode, namedArgs);
- } else if (isKnownImmutableClass(fieldType, knownImmutableClasses) || isKnownImmutable(pNode.getName(), knownImmutables)) {
+ if (isKnownImmutableType(fieldType, knownImmutableClasses) || isKnownImmutable(pNode.getName(), knownImmutables)) {
statement = createConstructorStatementDefault(fNode, namedArgs);
+ } else if (fieldType.isArray() || isOrImplements(fieldType, CLONEABLE_TYPE)) {
+ statement = createConstructorStatementArrayOrCloneable(fNode, namedArgs);
} else if (fieldType.isDerivedFrom(DATE_TYPE)) {
statement = createConstructorStatementDate(fNode, namedArgs);
} else if (isOrImplements(fieldType, COLLECTION_TYPE) || fieldType.isDerivedFrom(COLLECTION_TYPE) || isOrImplements(fieldType, MAP_TYPE) || fieldType.isDerivedFrom(MAP_TYPE)) {
@@ -588,33 +587,6 @@ public class ImmutableASTTransformation extends AbstractASTTransformation {
return assignWithDefault(namedArgs, assignInit, param, assignStmt);
}
- private static boolean isKnownImmutableClass(ClassNode fieldType, List<String> knownImmutableClasses) {
- if (inImmutableList(fieldType.getName()) || knownImmutableClasses.contains(fieldType.getName()))
- return true;
- if (!fieldType.isResolved())
- return false;
- if ("java.util.Optional".equals(fieldType.getName()) && fieldType.getGenericsTypes() != null && fieldType.getGenericsTypes().length == 1) {
- GenericsType optionalType = fieldType.getGenericsTypes()[0];
- if (optionalType.isResolved() && !optionalType.isPlaceholder() && !optionalType.isWildcard()) {
- String name = optionalType.getType().getName();
- if (inImmutableList(name) || knownImmutableClasses.contains(name)) return true;
- if (optionalType.getType().isEnum() || !optionalType.getType().getAnnotations(MY_TYPE).isEmpty())
- return true;
- }
- }
- return fieldType.isEnum() ||
- ClassHelper.isPrimitiveType(fieldType) ||
- !fieldType.getAnnotations(MY_TYPE).isEmpty();
- }
-
- private static boolean isKnownImmutable(String fieldName, List<String> knownImmutables) {
- return knownImmutables.contains(fieldName);
- }
-
- private static boolean inImmutableList(String typeName) {
- return builtinImmutables.contains(typeName);
- }
-
private static Statement createConstructorStatementArrayOrCloneable(FieldNode fNode, boolean namedArgs) {
final Expression fieldExpr = propX(varX("this"), fNode.getName());
final Expression initExpr = fNode.getInitialValueExpression();
@@ -805,7 +777,7 @@ public class ImmutableASTTransformation extends AbstractASTTransformation {
*/
@SuppressWarnings("Unchecked")
public static Object checkImmutable(String className, String fieldName, Object field) {
- if (field == null || field instanceof Enum || inImmutableList(field.getClass().getName())) return field;
+ if (field == null || field instanceof Enum || isBuiltinImmutable(field.getClass().getName())) return field;
if (field instanceof Collection) return DefaultGroovyMethods.asImmutable((Collection) field);
if (getAnnotationByName(field, "groovy.transform.Immutable") != null) return field;
@@ -823,9 +795,12 @@ public class ImmutableASTTransformation extends AbstractASTTransformation {
return null;
}
+ /**
+ * For compatibility with pre 2.5 compiled classes
+ */
@SuppressWarnings("Unchecked")
- public static Object checkImmutable(Class<?> clazz, String fieldName, Object field, List<String> knownImmutableFieldNames, List<Class> knownImmutableClasses) {
- if (field == null || field instanceof Enum || knownImmutable(field.getClass()) || knownImmutableFieldNames.contains(fieldName) || knownImmutableClasses.contains(field.getClass())) {
+ public static Object checkImmutable(Class<?> clazz, String fieldName, Object field) {
+ if (field == null || field instanceof Enum || builtinOrMarkedImmutableClass(field.getClass())) {
return field;
}
@@ -847,7 +822,7 @@ public class ImmutableASTTransformation extends AbstractASTTransformation {
return DefaultGroovyMethods.asImmutable((Collection) field);
}
// potentially allow Collection coercion for a constructor
- if (knownImmutable(fieldType)) {
+ if (builtinOrMarkedImmutableClass(fieldType)) {
return field;
}
} catch (NoSuchFieldException ignore) {
@@ -858,12 +833,9 @@ public class ImmutableASTTransformation extends AbstractASTTransformation {
throw new RuntimeException(createErrorMessage(clazz.getName(), fieldName, typeName, "constructing"));
}
- /*
- * For compatibility with pre 2.5 compiled classes
- */
@SuppressWarnings("Unchecked")
- public static Object checkImmutable(Class<?> clazz, String fieldName, Object field) {
- if (field == null || field instanceof Enum || knownImmutable(field.getClass())) {
+ public static Object checkImmutable(Class<?> clazz, String fieldName, Object field, List<String> knownImmutableFieldNames, List<Class> knownImmutableClasses) {
+ if (field == null || field instanceof Enum || builtinOrMarkedImmutableClass(field.getClass()) || knownImmutableFieldNames.contains(fieldName) || knownImmutableClasses.contains(field.getClass())) {
return field;
}
@@ -885,7 +857,7 @@ public class ImmutableASTTransformation extends AbstractASTTransformation {
return DefaultGroovyMethods.asImmutable((Collection) field);
}
// potentially allow Collection coercion for a constructor
- if (knownImmutable(fieldType)) {
+ if (builtinOrMarkedImmutableClass(fieldType) || knownImmutableClasses.contains(fieldType)) {
return field;
}
} catch (NoSuchFieldException ignore) {
@@ -896,8 +868,60 @@ public class ImmutableASTTransformation extends AbstractASTTransformation {
throw new RuntimeException(createErrorMessage(clazz.getName(), fieldName, typeName, "constructing"));
}
- private static boolean knownImmutable(Class<?> clazz) {
- return inImmutableList(clazz.getName()) || clazz.getAnnotation(KNOWN_IMMUTABLE_CLASS) != null;
+ private static boolean isKnownImmutableType(ClassNode fieldType, List<String> knownImmutableClasses) {
+ if (builtinOrDeemedType(fieldType, knownImmutableClasses))
+ return true;
+ if (!fieldType.isResolved())
+ return false;
+ if ("java.util.Optional".equals(fieldType.getName()) && fieldType.getGenericsTypes() != null && fieldType.getGenericsTypes().length == 1) {
+ GenericsType optionalType = fieldType.getGenericsTypes()[0];
+ if (optionalType.isResolved() && !optionalType.isPlaceholder() && !optionalType.isWildcard()) {
+ ClassNode valueType = optionalType.getType();
+ if (builtinOrDeemedType(valueType, knownImmutableClasses)) return true;
+ if (valueType.isEnum()) return true;
+ }
+ }
+ return fieldType.isEnum() ||
+ ClassHelper.isPrimitiveType(fieldType) ||
+ hasImmutableAnnotation(fieldType);
+ }
+
+ private static boolean builtinOrDeemedType(ClassNode fieldType, List<String> knownImmutableClasses) {
+ return isBuiltinImmutable(fieldType.getName()) || knownImmutableClasses.contains(fieldType.getName()) || hasImmutableAnnotation(fieldType);
+ }
+
+ private static boolean hasImmutableAnnotation(ClassNode type) {
+ List<AnnotationNode> annotations = type.getAnnotations();
+ for (AnnotationNode next : annotations) {
+ String name = next.getClassNode().getName();
+ if (matchingMarkerName(name)) return true;
+ }
+ return false;
+ }
+
+ private static boolean hasImmutableAnnotation(Class clazz) {
+ Annotation[] annotations = clazz.getAnnotations();
+ for (Annotation next : annotations) {
+ String name = next.annotationType().getName();
+ if (matchingMarkerName(name)) return true;
+ }
+ return false;
+ }
+
+ private static boolean matchingMarkerName(String name) {
+ return name.equals("groovy.transform.Immutable") || name.equals(KNOWN_IMMUTABLE_NAME);
+ }
+
+ private static boolean isKnownImmutable(String fieldName, List<String> knownImmutables) {
+ return knownImmutables.contains(fieldName);
+ }
+
+ private static boolean isBuiltinImmutable(String typeName) {
+ return builtinImmutables.contains(typeName);
+ }
+
+ private static boolean builtinOrMarkedImmutableClass(Class<?> clazz) {
+ return isBuiltinImmutable(clazz.getName()) || hasImmutableAnnotation(clazz);
}
public static void checkPropNames(Object instance, Map<String, Object> args) {