Search in sources :

Example 6 with Parameter

use of com.google.javascript.rhino.jstype.FunctionType.Parameter in project closure-compiler by google.

the class FunctionTypeBuilder method inferFromOverriddenFunction.

/**
 * Infer the parameter and return types of a function from
 * the parameter and return types of the function it is overriding.
 *
 * @param oldType The function being overridden. Does nothing if this is null.
 * @param paramsParent The PARAM_LIST node of the function that we're assigning to.
 *     If null, that just means we're not initializing this to a function
 *     literal.
 */
FunctionTypeBuilder inferFromOverriddenFunction(@Nullable FunctionType oldType, @Nullable Node paramsParent) {
    if (oldType == null) {
        return this;
    }
    // Propagate the template types, if they exist.
    this.templateTypeNames = oldType.getTemplateTypeMap().getTemplateKeys();
    returnType = oldType.getReturnType();
    returnTypeInferred = oldType.isReturnTypeInferred();
    if (paramsParent == null) {
        // Not a function literal.
        parameters = oldType.getParameters();
        if (parameters == null) {
            parameters = new FunctionParamBuilder(typeRegistry).build();
        }
    } else {
        // We're overriding with a function literal. Apply type information
        // to each parameter of the literal.
        FunctionParamBuilder paramBuilder = new FunctionParamBuilder(typeRegistry);
        Iterator<Parameter> oldParams = oldType.getParameters().iterator();
        boolean warnedAboutArgList = false;
        boolean oldParamsListHitOptArgs = false;
        for (Node currentParam = paramsParent.getFirstChild(); currentParam != null; currentParam = currentParam.getNext()) {
            if (oldParams.hasNext()) {
                Parameter oldParam = oldParams.next();
                oldParamsListHitOptArgs = oldParamsListHitOptArgs || oldParam.isVariadic() || oldParam.isOptional();
                // The subclass method might write its var_args as individual arguments.
                boolean isOptionalArg = oldParam.isOptional();
                boolean isVarArgs = oldParam.isVariadic();
                if (currentParam.getNext() != null && isVarArgs) {
                    isVarArgs = false;
                    isOptionalArg = true;
                }
                // with a default value
                if (currentParam.isDefaultValue()) {
                    isOptionalArg = true;
                }
                paramBuilder.newParameterFrom(Parameter.create(oldParam.getJSType(), isOptionalArg, isVarArgs));
            } else {
                warnedAboutArgList |= addParameter(paramBuilder, typeRegistry.getNativeType(UNKNOWN_TYPE), warnedAboutArgList, codingConvention.isOptionalParameter(currentParam) || oldParamsListHitOptArgs || currentParam.isDefaultValue(), codingConvention.isVarArgsParameter(currentParam));
            }
        }
        // but make them optional.
        while (oldParams.hasNext()) {
            paramBuilder.newOptionalParameterFrom(oldParams.next());
        }
        parameters = paramBuilder.build();
    }
    return this;
}
Also used : Node(com.google.javascript.rhino.Node) Parameter(com.google.javascript.rhino.jstype.FunctionType.Parameter) FunctionParamBuilder(com.google.javascript.rhino.jstype.FunctionParamBuilder)

Example 7 with Parameter

use of com.google.javascript.rhino.jstype.FunctionType.Parameter in project closure-compiler by google.

the class InvocationTemplateTypeMatcher method match.

ImmutableMap<TemplateType, JSType> match() {
    if (this.calleeType.getTemplateTypeMap().isEmpty()) {
        return ImmutableMap.of();
    }
    Node target = this.invocation.getFirstChild();
    if (NodeUtil.isNormalGet(target)) {
        Node obj = target.getFirstChild();
        JSType typeOfThisRequiredByTheFunction = this.calleeType.getTypeOfThis();
        // The type placed on a SUPER node is the superclass type, which allows us to infer the right
        // property types for the GETPROP or GETELEM nodes built on it.
        // However, the type actually passed as `this` when making calls this way is the `this`
        // of the scope where the `super` appears.
        JSType typeOfThisProvidedByTheCall = obj.isSuper() ? this.localThisType : this.getTypeOrUnknown(obj);
        // We're looking at a call made as `obj['method']()` or `obj.method()` (see enclosing if),
        // so if the call is successfully made, then the object through which it is made isn't null
        // or undefined.
        typeOfThisProvidedByTheCall = typeOfThisProvidedByTheCall.restrictByNotNullOrUndefined();
        this.matchTemplateTypesRecursive(typeOfThisRequiredByTheFunction, typeOfThisProvidedByTheCall);
    }
    if (this.invocation.isTaggedTemplateLit()) {
        Iterator<Parameter> calleeParameters = this.calleeType.getParameters().iterator();
        if (!calleeParameters.hasNext()) {
            // TypeCheck will warn if there are too few function parameters
            return ImmutableMap.copyOf(this.matchedTypes);
        }
        // The first argument to the tag function is an array of strings (typed as ITemplateArray)
        // but not an actual AST node
        this.matchTemplateTypesRecursive(calleeParameters.next().getJSType(), this.registry.getNativeType(I_TEMPLATE_ARRAY_TYPE));
        // Resolve the remaining template types from the template literal substitutions.
        this.matchTemplateTypesFromNodes(Iterables.skip(this.calleeType.getParameters(), 1), NodeUtil.getInvocationArgsAsIterable(this.invocation));
    } else if (this.invocation.hasMoreThanOneChild()) {
        this.matchTemplateTypesFromNodes(this.calleeType.getParameters(), NodeUtil.getInvocationArgsAsIterable(this.invocation));
    }
    return ImmutableMap.copyOf(this.matchedTypes);
}
Also used : JSType(com.google.javascript.rhino.jstype.JSType) Node(com.google.javascript.rhino.Node) Parameter(com.google.javascript.rhino.jstype.FunctionType.Parameter)

Example 8 with Parameter

use of com.google.javascript.rhino.jstype.FunctionType.Parameter in project closure-compiler by google.

the class InvocationTemplateTypeMatcher method matchTemplateTypesFromParameters.

private void matchTemplateTypesFromParameters(Iterator<Parameter> declParams, Iterator<Parameter> callParams) {
    while (declParams.hasNext() && callParams.hasNext()) {
        Parameter declParam = declParams.next();
        this.matchTemplateTypesRecursive(declParam.getJSType(), callParams.next().getJSType());
        if (declParam.isVariadic()) {
            while (callParams.hasNext()) {
                this.matchTemplateTypesRecursive(declParam.getJSType(), callParams.next().getJSType());
            }
        }
    }
}
Also used : Parameter(com.google.javascript.rhino.jstype.FunctionType.Parameter)

Example 9 with Parameter

use of com.google.javascript.rhino.jstype.FunctionType.Parameter in project closure-compiler by google.

the class InvocationTemplateTypeMatcher method matchTemplateTypesFromNodes.

private void matchTemplateTypesFromNodes(Iterator<Parameter> declParams, Iterator<Node> callParams) {
    while (declParams.hasNext() && callParams.hasNext()) {
        Parameter declParam = declParams.next();
        this.matchTemplateTypesRecursive(declParam.getJSType(), this.getTypeOrUnknown(callParams.next()));
        if (declParam.isVariadic()) {
            while (callParams.hasNext()) {
                this.matchTemplateTypesRecursive(declParam.getJSType(), this.getTypeOrUnknown(callParams.next()));
            }
        }
    }
}
Also used : Parameter(com.google.javascript.rhino.jstype.FunctionType.Parameter)

Example 10 with Parameter

use of com.google.javascript.rhino.jstype.FunctionType.Parameter in project closure-compiler by google.

the class TypeCheck method checkArgumentsMatchParameters.

/**
 * Checks that a list of arguments match a list of formal parameters
 *
 * <p>If given a TAGGED_TEMPLATE_LIT, the given Iterator should only contain the parameters
 * corresponding to the actual template lit sub arguments, skipping over the first parameter.
 *
 * @param firstParameterIndex The index of the first parameter in the given Iterator in the
 *     function type's parameter list.
 */
private void checkArgumentsMatchParameters(Node call, FunctionType functionType, Iterator<Node> arguments, Iterator<Parameter> parameters, int firstParameterIndex) {
    int spreadArgumentCount = 0;
    int normalArgumentCount = firstParameterIndex;
    boolean checkArgumentTypeAgainstParameter = true;
    Parameter parameter = null;
    Node argument = null;
    while (arguments.hasNext()) {
        // get the next argument
        argument = arguments.next();
        // Count normal & spread arguments.
        if (argument.isSpread()) {
            // we have some form of this case
            // someCall(arg1, arg2, ...firstSpreadExpression, argN, ...secondSpreadExpression)
            spreadArgumentCount++;
            // Once we see a spread parameter, we can no longer match up arguments with parameters.
            checkArgumentTypeAgainstParameter = false;
        } else {
            normalArgumentCount++;
        }
        // Get the next parameter, if we're still matching parameters and arguments.
        if (checkArgumentTypeAgainstParameter) {
            if (parameters.hasNext()) {
                parameter = parameters.next();
            } else if (parameter != null && parameter.isVariadic()) {
            // use varargs for all remaining parameters
            } else {
                // else we ran out of parameters and will report that after this loop
                parameter = null;
                checkArgumentTypeAgainstParameter = false;
            }
        }
        if (checkArgumentTypeAgainstParameter) {
            validator.expectArgumentMatchesParameter(argument, getJSType(argument), parameter.getJSType(), call, normalArgumentCount);
        }
    }
    int minArity = functionType.getMinArity();
    int maxArity = functionType.getMaxArity();
    if (spreadArgumentCount > 0) {
        if (normalArgumentCount > maxArity) {
            // We cannot reliably check whether the total argument count is wrong, but we can at
            // least tell if there are more arguments than the function can handle even ignoring the
            // spreads.
            report(call, WRONG_ARGUMENT_COUNT, typeRegistry.getReadableTypeNameNoDeref(call.getFirstChild()), "at least " + normalArgumentCount, String.valueOf(minArity), maxArity == Integer.MAX_VALUE ? "" : " and no more than " + maxArity + " argument(s)");
        }
    } else {
        if (minArity > normalArgumentCount || maxArity < normalArgumentCount) {
            report(call, WRONG_ARGUMENT_COUNT, typeRegistry.getReadableTypeNameNoDeref(call.getFirstChild()), String.valueOf(normalArgumentCount), String.valueOf(minArity), maxArity == Integer.MAX_VALUE ? "" : " and no more than " + maxArity + " argument(s)");
        }
    }
}
Also used : Node(com.google.javascript.rhino.Node) Parameter(com.google.javascript.rhino.jstype.FunctionType.Parameter)

Aggregations

Parameter (com.google.javascript.rhino.jstype.FunctionType.Parameter)13 Node (com.google.javascript.rhino.Node)8 JSType (com.google.javascript.rhino.jstype.JSType)6 FunctionType (com.google.javascript.rhino.jstype.FunctionType)4 JSTypeExpression (com.google.javascript.rhino.JSTypeExpression)2 FunctionParamBuilder (com.google.javascript.rhino.jstype.FunctionParamBuilder)2 JSDocInfo (com.google.javascript.rhino.JSDocInfo)1 UnionType (com.google.javascript.rhino.jstype.UnionType)1