Search in sources :

Example 1 with FunctionParamBuilder

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

the class FunctionTypeBuilder method inferParameterTypes.

/**
 * Infer the parameter types from the list of parameter names and the JSDoc info.
 */
FunctionTypeBuilder inferParameterTypes(@Nullable Node paramsParent, @Nullable JSDocInfo info) {
    if (paramsParent == null) {
        if (info == null) {
            return this;
        } else {
            return inferParameterTypes(info);
        }
    }
    // arguments
    final Iterator<Parameter> oldParameters;
    Parameter oldParameterType = null;
    if (parameters != null) {
        oldParameters = parameters.iterator();
        oldParameterType = oldParameters.hasNext() ? oldParameters.next() : null;
    } else {
        oldParameters = Collections.emptyIterator();
    }
    FunctionParamBuilder builder = new FunctionParamBuilder(typeRegistry);
    boolean warnedAboutArgList = false;
    Set<String> allJsDocParams = (info == null) ? new HashSet<>() : new HashSet<>(info.getParameterNames());
    boolean isVarArgs = false;
    int paramIndex = 0;
    for (Node param = paramsParent.getFirstChild(); param != null; param = param.getNext()) {
        boolean isOptionalParam = false;
        final Node paramLhs;
        if (param.isRest()) {
            isVarArgs = true;
            paramLhs = param.getOnlyChild();
        } else if (param.isDefaultValue()) {
            // The first child is the actual positional parameter
            paramLhs = checkNotNull(param.getFirstChild(), param);
            isOptionalParam = true;
        } else {
            isVarArgs = isVarArgsParameterByConvention(param);
            isOptionalParam = isOptionalParameterByConvention(param);
            paramLhs = param;
        }
        String paramName = null;
        if (paramLhs.isName()) {
            paramName = paramLhs.getString();
        } else {
            checkState(paramLhs.isDestructuringPattern());
            // third JSDoc parameter.
            if (info != null) {
                paramName = info.getParameterNameAt(paramIndex);
            }
        }
        allJsDocParams.remove(paramName);
        // type from JSDocInfo
        JSType parameterType = null;
        if (info != null && info.hasParameterType(paramName)) {
            JSTypeExpression parameterTypeExpression = info.getParameterType(paramName);
            parameterType = parameterTypeExpression.evaluate(templateScope, typeRegistry);
            isOptionalParam = isOptionalParam || parameterTypeExpression.isOptionalArg();
            isVarArgs = isVarArgs || parameterTypeExpression.isVarArgs();
        } else if (paramLhs.getJSDocInfo() != null && paramLhs.getJSDocInfo().hasType()) {
            JSTypeExpression parameterTypeExpression = paramLhs.getJSDocInfo().getType();
            parameterType = parameterTypeExpression.evaluate(templateScope, typeRegistry);
            isOptionalParam = parameterTypeExpression.isOptionalArg();
            isVarArgs = parameterTypeExpression.isVarArgs();
        } else if (oldParameterType != null && oldParameterType.getJSType() != null) {
            parameterType = oldParameterType.getJSType();
            isOptionalParam = oldParameterType.isOptional();
            isVarArgs = oldParameterType.isVariadic();
        } else {
            parameterType = typeRegistry.getNativeType(UNKNOWN_TYPE);
        }
        warnedAboutArgList |= addParameter(builder, parameterType, warnedAboutArgList, isOptionalParam, isVarArgs);
        oldParameterType = oldParameters.hasNext() ? oldParameters.next() : null;
        paramIndex++;
    }
    // Copy over any old parameters that aren't in the param list.
    if (!isVarArgs) {
        while (oldParameterType != null && !isVarArgs) {
            builder.newParameterFrom(oldParameterType);
            oldParameterType = oldParameters.hasNext() ? oldParameters.next() : null;
        }
    }
    for (String inexistentName : allJsDocParams) {
        reportWarning(INEXISTENT_PARAM, inexistentName, formatFnName());
    }
    parameters = builder.build();
    return this;
}
Also used : JSType(com.google.javascript.rhino.jstype.JSType) Node(com.google.javascript.rhino.Node) Parameter(com.google.javascript.rhino.jstype.FunctionType.Parameter) JSTypeExpression(com.google.javascript.rhino.JSTypeExpression) FunctionParamBuilder(com.google.javascript.rhino.jstype.FunctionParamBuilder)

Example 2 with FunctionParamBuilder

use of com.google.javascript.rhino.jstype.FunctionParamBuilder 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)

Aggregations

Node (com.google.javascript.rhino.Node)2 FunctionParamBuilder (com.google.javascript.rhino.jstype.FunctionParamBuilder)2 Parameter (com.google.javascript.rhino.jstype.FunctionType.Parameter)2 JSTypeExpression (com.google.javascript.rhino.JSTypeExpression)1 JSType (com.google.javascript.rhino.jstype.JSType)1