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;
}
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);
}
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());
}
}
}
}
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()));
}
}
}
}
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)");
}
}
}
Aggregations