@Override public boolean isUsingGenerics() { lazyInitSupers(); return super.isUsingGenerics(); }
private static boolean usesGenericsInClassSignature(ClassNode node) { if (!node.isUsingGenerics()) return false; if (hasGenerics(node)) return true; ClassNode sclass = node.getUnresolvedSuperClass(false); if (sclass.isUsingGenerics()) return true; ClassNode[] interfaces = node.getInterfaces(); if (interfaces != null) { for (int i = 0; i < interfaces.length; i++) { if (interfaces[i].isUsingGenerics()) return true; } } return false; }
private static ClassNode getComponentTypeForList(ClassNode fType) { if (fType.isUsingGenerics() && fType.getGenericsTypes().length == 1) { return fType.getGenericsTypes()[0].getType(); } else { return ClassHelper.OBJECT_TYPE; } }
private static ClassNode adjustForTargetType(final ClassNode targetType, final ClassNode resultType) { if (targetType.isUsingGenerics() && missesGenericsTypes(resultType)) { // unchecked assignment within ternary/elvis // examples: // List<A> list = existingAs ?: [] // in that case, the inferred type of the RHS is the type of the RHS // "completed" with generics type information available in the LHS return GenericsUtils.parameterizeType(targetType, resultType.getPlainNodeReference()); } return resultType; }
/** * resolves a Field or Property node generics by using the current class and * the declaring class to extract the right meaning of the generics symbols * * @param an a FieldNode or PropertyNode * @param type the origin type * @return the new ClassNode with corrected generics */ private ClassNode getGenericsResolvedTypeOfFieldOrProperty(AnnotatedNode an, ClassNode type) { if (!type.isUsingGenerics()) return type; Map<GenericsTypeName, GenericsType> connections = new HashMap<GenericsTypeName, GenericsType>(); //TODO: inner classes mean a different this-type. This is ignored here! extractGenericsConnections(connections, typeCheckingContext.getEnclosingClassNode(), an.getDeclaringClass()); type = applyGenericsContext(connections, type); return type; }
/** * Iterates over each generics bound of this generics specification, and checks * that the generics defined by the bound are compatible with the generics specified * by the type. * @param classNode the classnode the bounds should be compared with * @return true if generics from bounds are compatible */ private boolean checkGenerics(final ClassNode classNode) { if (upperBounds!=null) { for (ClassNode upperBound : upperBounds) { if (!compareGenericsWithBound(classNode, upperBound)) return false; } } if (lowerBound!=null) { if (!lowerBound.redirect().isUsingGenerics()) { if (!compareGenericsWithBound(classNode, lowerBound)) return false; } } return true; }
/** * Returns true if a class node makes use of generic types. If the class node represents an * array type, then checks if the component type is using generics. * * @param cn a class node for which to check if it is using generics * @return true if the type (or component type) is using generics */ public static boolean isUsingGenericsOrIsArrayUsingGenerics(ClassNode cn) { if (cn.isArray()) { return isUsingGenericsOrIsArrayUsingGenerics(cn.getComponentType()); } return (cn.isUsingGenerics() && cn.getGenericsTypes() != null); }
private static void extractSuperClassGenerics(ClassNode[] usage, ClassNode[] declaration, Map<String, ClassNode> spec) { if (usage == null || declaration == null || declaration.length == 0) return; // both have generics for (int i = 0; i < usage.length; i++) { ClassNode ui = usage[i]; ClassNode di = declaration[i]; if (di.isGenericsPlaceHolder()) { spec.put(di.getGenericsTypes()[0].getName(), di); } else if (di.isUsingGenerics()) { extractSuperClassGenerics(ui.getGenericsTypes(), di.getGenericsTypes(), spec); } } }
/** * Returns true if the class node represents a the class node for the Class class * and if the parametrized type is a neither a placeholder or a wildcard. For example, * the class node Class<Foo> where Foo is a class would return true, but the class * node for Class<?> would return false. * * @param classNode a class node to be tested * @return true if it is the class node for Class and its generic type is a real class */ public static boolean isClassClassNodeWrappingConcreteType(ClassNode classNode) { GenericsType[] genericsTypes = classNode.getGenericsTypes(); return CLASS_Type.equals(classNode) && classNode.isUsingGenerics() && genericsTypes != null && !genericsTypes[0].isPlaceholder() && !genericsTypes[0].isWildcard(); }
public static ClassNode nonGeneric(ClassNode type) { if (type.isUsingGenerics()) { final ClassNode nonGen = ClassHelper.makeWithoutCaching(type.getName()); nonGen.setRedirect(type); nonGen.setGenericsTypes(null); nonGen.setUsingGenerics(false); return nonGen; } if (type.isArray() && type.getComponentType().isUsingGenerics()) { return type.getComponentType().getPlainNodeReference().makeArray(); } return type; }
protected void inferDiamondType(final ConstructorCallExpression cce, final ClassNode lType) { // check if constructor call expression makes use of the diamond operator ClassNode node = cce.getType(); if (node.isUsingGenerics() && node.getGenericsTypes() != null && node.getGenericsTypes().length == 0) { ArgumentListExpression argumentListExpression = InvocationWriter.makeArgumentList(cce.getArguments()); if (argumentListExpression.getExpressions().isEmpty()) { adjustGenerics(lType, node); } else { ClassNode type = getType(argumentListExpression.getExpression(0)); if (type.isUsingGenerics()) { adjustGenerics(type, node); } } // store inferred type on CCE storeType(cce, node); } }
public ClassNode parameterizedType(ClassNode baseType, ClassNode... genericsTypeArguments) { ClassNode result = baseType.getPlainNodeReference(); if (result.isUsingGenerics()) { GenericsType[] gts = new GenericsType[genericsTypeArguments.length]; int expectedLength = result.getGenericsTypes().length; if (expectedLength!=genericsTypeArguments.length) { throw new GroovyBugError("Expected number of generic type arguments for "+baseType.toString(false)+" is "+expectedLength + " but you gave "+genericsTypeArguments.length); } for (int i = 0; i < gts.length; i++) { gts[i] = new GenericsType(genericsTypeArguments[i]); } result.setGenericsTypes(gts); } return result; }
private void checkGenericsUsage(ASTNode ref, ClassNode node) { if (node.isArray()) { checkGenericsUsage(ref, node.getComponentType()); } else if (!node.isRedirectNode() && node.isUsingGenerics()) { addError( "A transform used a generics containing ClassNode "+ node + " " + "for "+getRefDescriptor(ref) + "directly. You are not supposed to do this. " + "Please create a new ClassNode referring to the old ClassNode " + "and use the new ClassNode instead of the old one. Otherwise " + "the compiler will create wrong descriptors and a potential " + "NullPointerException in TypeResolver in the OpenJDK. If this is " + "not your own doing, please report this bug to the writer of the " + "transform.", ref); } }
private static void extractGenericsConnections(Map<GenericsTypeName, GenericsType> connections, ClassNode[] usage, ClassNode[] declaration) { if (usage == null || declaration == null || declaration.length == 0) return; // both have generics for (int i = 0; i < usage.length; i++) { ClassNode ui = usage[i]; ClassNode di = declaration[i]; if (di.isGenericsPlaceHolder()) { GenericsType gt = new GenericsType(di); gt.setPlaceholder(di.isGenericsPlaceHolder()); connections.put(new GenericsTypeName(di.getGenericsTypes()[0].getName()), gt); } else if (di.isUsingGenerics()) { extractGenericsConnections(connections, ui.getGenericsTypes(), di.getGenericsTypes()); } } }
private void checkTypeGenerics(ClassNode leftExpressionType, ClassNode wrappedRHS, Expression rightExpression) { // last, check generic type information to ensure that inferred types are compatible if (!leftExpressionType.isUsingGenerics()) return; // List<Foo> l = new List() is an example for incomplete generics type info // we assume arity related errors are already handled here. if (hasRHSIncompleteGenericTypeInfo(wrappedRHS)) return; GenericsType gt = GenericsUtils.buildWildcardType(leftExpressionType); if (UNKNOWN_PARAMETER_TYPE.equals(wrappedRHS) || gt.isCompatibleWith(wrappedRHS) || isNullConstant(rightExpression)) return; addStaticTypeError("Incompatible generic argument types. Cannot assign " + wrappedRHS.toString(false) + " to: " + leftExpressionType.toString(false), rightExpression); }
private Map<GenericsTypeName, GenericsType> resolvePlaceHoldersFromDeclaration(ClassNode receiver, ClassNode declaration, MethodNode method, boolean isStaticTarget) { Map<GenericsTypeName, GenericsType> resolvedPlaceholders; if (isStaticTarget && CLASS_Type.equals(receiver) && receiver.isUsingGenerics() && receiver.getGenericsTypes().length > 0 && !OBJECT_TYPE.equals(receiver.getGenericsTypes()[0].getType())) { return resolvePlaceHoldersFromDeclaration(receiver.getGenericsTypes()[0].getType(), declaration, method, isStaticTarget); } else { resolvedPlaceholders = extractPlaceHolders(method, receiver, declaration); } return resolvedPlaceholders; }
/** * @param node the node to be tested * @return true if the node is using generics types and one of those types is a gstring or string/gstring lub */ public static boolean isParameterizedWithGStringOrGStringString(ClassNode node) { if (node.isArray()) return isParameterizedWithGStringOrGStringString(node.getComponentType()); if (node.isUsingGenerics()) { GenericsType[] genericsTypes = node.getGenericsTypes(); if (genericsTypes != null) { for (GenericsType genericsType : genericsTypes) { if (isGStringOrGStringStringLUB(genericsType.getType())) return true; } } } return node.getSuperClass() != null && isParameterizedWithGStringOrGStringString(node.getUnresolvedSuperClass()); }
/** * @param node the node to be tested * @return true if the node is using generics types and one of those types is a string */ public static boolean isParameterizedWithString(ClassNode node) { if (node.isArray()) return isParameterizedWithString(node.getComponentType()); if (node.isUsingGenerics()) { GenericsType[] genericsTypes = node.getGenericsTypes(); if (genericsTypes != null) { for (GenericsType genericsType : genericsTypes) { if (STRING_TYPE.equals(genericsType.getType())) return true; } } } return node.getSuperClass() != null && isParameterizedWithString(node.getUnresolvedSuperClass()); }
protected ClassNode makeType(AST typeNode) { ClassNode answer = ClassHelper.DYNAMIC_TYPE; AST node = typeNode.getFirstChild(); if (node != null) { if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) { answer = makeType(node).makeArray(); } else { checkTypeArgs(node, false); answer = ClassHelper.make(qualifiedName(node)); if (answer.isUsingGenerics()) { ClassNode newAnswer = ClassHelper.makeWithoutCaching(answer.getName()); newAnswer.setRedirect(answer); answer = newAnswer; } } configureAST(answer, node); } return answer; }
protected void visitGenerics(ClassNode node) { if (node.isUsingGenerics()) { GenericsType[] generics = node.getGenericsTypes(); if(generics == null) return; for (GenericsType genericType : generics) { visitNode(genericType); visitType(genericType.getType()); if (genericType.getLowerBound() != null) { visitType(genericType.getLowerBound()); } visitTypes(genericType.getUpperBounds()); } } }