Search in sources :

Example 86 with GenericsType

use of org.codehaus.groovy.ast.GenericsType in project groovy-core by groovy.

the class StaticTypeCheckingVisitor method makeThis.

private ClassNode makeThis() {
    ClassNode ret = typeCheckingContext.getEnclosingClassNode();
    if (typeCheckingContext.isInStaticContext) {
        ClassNode staticRet = CLASS_Type.getPlainNodeReference();
        GenericsType gt = new GenericsType(ret);
        staticRet.setGenericsTypes(new GenericsType[] { gt });
        ret = staticRet;
    }
    return ret;
}
Also used : LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) GenericsType(org.codehaus.groovy.ast.GenericsType)

Example 87 with GenericsType

use of org.codehaus.groovy.ast.GenericsType in project groovy-core by groovy.

the class StaticTypeCheckingVisitor method resolvePlaceholdersFromExplicitTypeHints.

private void resolvePlaceholdersFromExplicitTypeHints(final MethodNode method, final GenericsType[] explicitTypeHints, final Map<String, GenericsType> resolvedPlaceholders) {
    if (explicitTypeHints != null) {
        GenericsType[] methodGenericTypes = method.getGenericsTypes();
        if (methodGenericTypes != null && methodGenericTypes.length == explicitTypeHints.length) {
            for (int i = 0; i < explicitTypeHints.length; i++) {
                GenericsType methodGenericType = methodGenericTypes[i];
                GenericsType explicitTypeHint = explicitTypeHints[i];
                resolvedPlaceholders.put(methodGenericType.getName(), explicitTypeHint);
            }
            for (GenericsType typeHint : explicitTypeHints) {
                System.err.println("Type hint = " + typeHint);
            }
        }
    }
}
Also used : GenericsType(org.codehaus.groovy.ast.GenericsType) ClosureSignatureHint(groovy.transform.stc.ClosureSignatureHint)

Example 88 with GenericsType

use of org.codehaus.groovy.ast.GenericsType in project groovy-core by groovy.

the class StaticTypeCheckingVisitor method extractPlaceHolders.

private static Map<String, GenericsType> extractPlaceHolders(MethodNode method, ClassNode receiver, ClassNode declaringClass) {
    if (declaringClass.equals(OBJECT_TYPE)) {
        Map<String, GenericsType> resolvedPlaceholders = new HashMap<String, GenericsType>();
        if (method != null)
            addMethodLevelDeclaredGenerics(method, resolvedPlaceholders);
        return resolvedPlaceholders;
    }
    Map<String, GenericsType> resolvedPlaceholders = null;
    if (isPrimitiveType(receiver) && !isPrimitiveType(declaringClass)) {
        receiver = getWrapper(receiver);
    }
    final List<ClassNode> queue;
    if (receiver instanceof UnionTypeClassNode) {
        queue = Arrays.asList(((UnionTypeClassNode) receiver).getDelegates());
    } else {
        queue = Collections.singletonList(receiver);
    }
    for (ClassNode item : queue) {
        ClassNode current = item;
        while (current != null) {
            boolean continueLoop = true;
            //extract the place holders
            Map<String, GenericsType> currentPlaceHolders = new HashMap<String, GenericsType>();
            if (isGenericsPlaceHolderOrArrayOf(declaringClass) || declaringClass.equals(current)) {
                extractGenericsConnections(currentPlaceHolders, current, declaringClass);
                if (method != null)
                    addMethodLevelDeclaredGenerics(method, currentPlaceHolders);
                continueLoop = false;
            } else {
                GenericsUtils.extractPlaceholders(current, currentPlaceHolders);
            }
            if (resolvedPlaceholders != null) {
                // merge maps
                Set<Map.Entry<String, GenericsType>> entries = currentPlaceHolders.entrySet();
                for (Map.Entry<String, GenericsType> entry : entries) {
                    GenericsType gt = entry.getValue();
                    if (!gt.isPlaceholder())
                        continue;
                    GenericsType referenced = resolvedPlaceholders.get(gt.getName());
                    if (referenced == null)
                        continue;
                    entry.setValue(referenced);
                }
            }
            resolvedPlaceholders = currentPlaceHolders;
            // we are done if we are now in the declaring class
            if (!continueLoop)
                break;
            current = getNextSuperClass(current, declaringClass);
            if (current == null && CLASS_Type.equals(declaringClass)) {
                // this can happen if the receiver is Class<Foo>, then
                // the actual receiver is Foo and declaringClass is Class
                current = declaringClass;
            }
        }
    }
    if (resolvedPlaceholders == null) {
        String descriptor = "<>";
        if (method != null)
            descriptor = method.getTypeDescriptor();
        throw new GroovyBugError("Declaring class for method call to '" + descriptor + "' declared in " + declaringClass.getName() + " was not matched with found receiver " + receiver.getName() + "." + " This should not have happened!");
    }
    return resolvedPlaceholders;
}
Also used : LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) LinkedHashMap(java.util.LinkedHashMap) ListHashMap(org.codehaus.groovy.util.ListHashMap) HashMap(java.util.HashMap) GroovyBugError(org.codehaus.groovy.GroovyBugError) GenericsType(org.codehaus.groovy.ast.GenericsType) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) ListHashMap(org.codehaus.groovy.util.ListHashMap) HashMap(java.util.HashMap)

Example 89 with GenericsType

use of org.codehaus.groovy.ast.GenericsType in project groovy-core by groovy.

the class StaticTypeCheckingVisitor method checkClosureWithDelegatesTo.

private void checkClosureWithDelegatesTo(final ClassNode receiver, final MethodNode mn, final ArgumentListExpression arguments, final Parameter[] params, final Expression expression, final Parameter param) {
    List<AnnotationNode> annotations = param.getAnnotations(DELEGATES_TO);
    if (annotations != null && !annotations.isEmpty()) {
        for (AnnotationNode annotation : annotations) {
            // in theory, there can only be one annotation of that type
            Expression value = annotation.getMember("value");
            Expression strategy = annotation.getMember("strategy");
            Expression genericTypeIndex = annotation.getMember("genericTypeIndex");
            Expression type = annotation.getMember("type");
            Integer stInt = Closure.OWNER_FIRST;
            if (strategy != null) {
                stInt = (Integer) evaluateExpression(new CastExpression(ClassHelper.Integer_TYPE, strategy), typeCheckingContext.source.getConfiguration());
            }
            if (value instanceof ClassExpression && !value.getType().equals(DELEGATES_TO_TARGET)) {
                if (genericTypeIndex != null) {
                    addStaticTypeError("Cannot use @DelegatesTo(genericTypeIndex=" + genericTypeIndex.getText() + ") without @DelegatesTo.Target because generic argument types are not available at runtime", value);
                }
                // temporarily store the delegation strategy and the delegate type
                expression.putNodeMetaData(StaticTypesMarker.DELEGATION_METADATA, new DelegationMetadata(value.getType(), stInt, typeCheckingContext.delegationMetadata));
            } else if (type != null && !"".equals(type.getText()) && type instanceof ConstantExpression) {
                String typeString = type.getText();
                ClassNode[] resolved = GenericsUtils.parseClassNodesFromString(typeString, getSourceUnit(), typeCheckingContext.compilationUnit, mn, type);
                if (resolved != null) {
                    if (resolved.length == 1) {
                        resolved = resolveGenericsFromTypeHint(receiver, arguments, mn, resolved);
                        expression.putNodeMetaData(StaticTypesMarker.DELEGATION_METADATA, new DelegationMetadata(resolved[0], stInt, typeCheckingContext.delegationMetadata));
                    } else {
                        addStaticTypeError("Incorrect type hint found in method " + (mn), type);
                    }
                }
            } else {
                final List<Expression> expressions = arguments.getExpressions();
                final int expressionsSize = expressions.size();
                Expression parameter = annotation.getMember("target");
                String parameterName = parameter != null && parameter instanceof ConstantExpression ? parameter.getText() : "";
                // todo: handle vargs!
                for (int j = 0, paramsLength = params.length; j < paramsLength; j++) {
                    final Parameter methodParam = params[j];
                    List<AnnotationNode> targets = methodParam.getAnnotations(DELEGATES_TO_TARGET);
                    if (targets != null && targets.size() == 1) {
                        // @DelegatesTo.Target Obj foo
                        AnnotationNode targetAnnotation = targets.get(0);
                        Expression idMember = targetAnnotation.getMember("value");
                        String id = idMember != null && idMember instanceof ConstantExpression ? idMember.getText() : "";
                        if (id.equals(parameterName)) {
                            if (j < expressionsSize) {
                                Expression actualArgument = expressions.get(j);
                                ClassNode actualType = getType(actualArgument);
                                if (genericTypeIndex != null && genericTypeIndex instanceof ConstantExpression) {
                                    int gti = Integer.parseInt(genericTypeIndex.getText());
                                    // type annotated with @DelegatesTo.Target
                                    ClassNode paramType = methodParam.getType();
                                    GenericsType[] genericsTypes = paramType.getGenericsTypes();
                                    if (genericsTypes == null) {
                                        addStaticTypeError("Cannot use @DelegatesTo(genericTypeIndex=" + genericTypeIndex.getText() + ") with a type that doesn't use generics", methodParam);
                                    } else if (gti < 0 || gti >= genericsTypes.length) {
                                        addStaticTypeError("Index of generic type @DelegatesTo(genericTypeIndex=" + genericTypeIndex.getText() + ") " + (gti < 0 ? "lower" : "greater") + " than those of the selected type", methodParam);
                                    } else {
                                        ClassNode pType = GenericsUtils.parameterizeType(actualType, paramType);
                                        GenericsType[] pTypeGenerics = pType.getGenericsTypes();
                                        if (pTypeGenerics != null && pTypeGenerics.length > gti) {
                                            actualType = pTypeGenerics[gti].getType();
                                        } else {
                                            addStaticTypeError("Unable to map actual type [" + actualType.toString(false) + "] onto " + paramType.toString(false), methodParam);
                                        }
                                    }
                                }
                                expression.putNodeMetaData(StaticTypesMarker.DELEGATION_METADATA, new DelegationMetadata(actualType, stInt, typeCheckingContext.delegationMetadata));
                                break;
                            }
                        }
                    }
                }
                if (expression.getNodeMetaData(StaticTypesMarker.DELEGATION_METADATA) == null) {
                    addError("Not enough arguments found for a @DelegatesTo method call. Please check that you either use an explicit class or @DelegatesTo.Target with a correct id", arguments);
                }
            }
        }
    }
}
Also used : LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) GenericsType(org.codehaus.groovy.ast.GenericsType) Parameter(org.codehaus.groovy.ast.Parameter) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList)

Example 90 with GenericsType

use of org.codehaus.groovy.ast.GenericsType in project groovy-core by groovy.

the class StaticTypeCheckingVisitor method toMethodGenericTypesString.

private String toMethodGenericTypesString(MethodNode node) {
    GenericsType[] genericsTypes = node.getGenericsTypes();
    if (genericsTypes == null)
        return "";
    StringBuilder sb = new StringBuilder("<");
    for (int i = 0; i < genericsTypes.length; i++) {
        final GenericsType genericsType = genericsTypes[i];
        sb.append(genericsType.toString());
        if (i < genericsTypes.length - 1) {
            sb.append(",");
        }
    }
    sb.append("> ");
    return sb.toString();
}
Also used : GenericsType(org.codehaus.groovy.ast.GenericsType) ClosureSignatureHint(groovy.transform.stc.ClosureSignatureHint)

Aggregations

GenericsType (org.codehaus.groovy.ast.GenericsType)171 ClassNode (org.codehaus.groovy.ast.ClassNode)148 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)76 LowestUpperBoundClassNode (org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode)52 Parameter (org.codehaus.groovy.ast.Parameter)21 MethodNode (org.codehaus.groovy.ast.MethodNode)20 ClosureSignatureHint (groovy.transform.stc.ClosureSignatureHint)19 LinkedList (java.util.LinkedList)18 HashMap (java.util.HashMap)17 ArrayList (java.util.ArrayList)15 LinkedHashMap (java.util.LinkedHashMap)9 AST (antlr.collections.AST)8 AnnotationNode (org.codehaus.groovy.ast.AnnotationNode)8 ListHashMap (org.codehaus.groovy.util.ListHashMap)8 Map (java.util.Map)6 AtomicReference (java.util.concurrent.atomic.AtomicReference)6 EnumConstantClassNode (org.codehaus.groovy.ast.EnumConstantClassNode)6 FieldNode (org.codehaus.groovy.ast.FieldNode)6 GroovyBugError (org.codehaus.groovy.GroovyBugError)5 DynamicVariable (org.codehaus.groovy.ast.DynamicVariable)4