use of com.google.javascript.jscomp.newtypes.JSType in project closure-compiler by google.
the class NewTypeInference method computeFnDeclaredTypeForCallback.
/**
* Given a scope whose root is an unannotated callback, finds a declared type for the callback
* using the types in the callback's context.
* Similar to GlobalTypeInfoCollector#computeFnDeclaredTypeFromCallee, but not similar enough
* to use the same code for both.
*/
private void computeFnDeclaredTypeForCallback(NTIScope scope) {
Node callback = scope.getRoot();
checkState(NodeUtil.isUnannotatedCallback(callback));
Node call = callback.getParent();
JSType calleeType = (JSType) call.getFirstChild().getTypeI();
if (calleeType == null) {
return;
}
FunctionType calleeFunType = calleeType.getFunType();
if (calleeFunType == null) {
return;
}
int argIndex = call.getIndexOfChild(callback) - 1;
JSType formalType = calleeFunType.getFormalType(argIndex);
if (formalType == null) {
return;
}
FunctionType ft = formalType.getFunType();
if (ft == null || ft.isLoose()) {
return;
}
DeclaredFunctionType callbackDft = scope.getDeclaredFunctionType();
JSType scopeType = this.commonTypes.fromFunctionType(callbackDft.toFunctionType());
if (ft.isUniqueConstructor() || ft.isInterfaceDefinition()) {
warnAboutInvalidArgument(call, callback, argIndex, formalType, scopeType);
return;
}
DeclaredFunctionType declaredDft = checkNotNull(ft.toDeclaredFunctionType());
// the arity of the callback.
if (ft.acceptsAnyArguments() || callbackDft.getRequiredArity() <= declaredDft.getMaxArity()) {
scope.setDeclaredType(declaredDft);
} else {
warnAboutInvalidArgument(call, callback, argIndex, formalType, scopeType);
}
}
use of com.google.javascript.jscomp.newtypes.JSType in project closure-compiler by google.
the class NewTypeInference method addRetTypeAndWarn.
private void addRetTypeAndWarn(NTIScope fn, TypeEnv exitEnv, DeclaredFunctionType declType, FunctionTypeBuilder builder) {
Node fnRoot = fn.getRoot();
JSType declRetType = declType.getReturnType();
JSType actualRetType = checkNotNull(envGetType(exitEnv, RETVAL_ID));
if (declRetType != null) {
if (fnRoot.isGeneratorFunction()) {
JSType generator = this.commonTypes.getGeneratorInstance(UNKNOWN);
if (!generator.isSubtypeOf(declRetType)) {
registerMismatchAndWarn(JSError.make(fnRoot, INVALID_DECLARED_RETURN_TYPE_OF_GENERATOR_FUNCTION, errorMsgWithTypeDiff(generator, declRetType)), declRetType, generator);
builder.addRetType(UNKNOWN);
} else {
builder.addRetType(declRetType);
}
} else {
builder.addRetType(declRetType);
if (!isAllowedToNotReturn(fn) && !UNDEFINED.isSubtypeOf(declRetType) && hasPathWithNoReturn(this.cfg)) {
warnings.add(JSError.make(fnRoot, MISSING_RETURN_STATEMENT, declRetType.toString()));
}
}
} else if (fnRoot.isGeneratorFunction()) {
// No declared return type for Generator. Use inferred type.
JSType yieldType = envGetType(exitEnv, YIELDVAL_ID);
builder.addRetType(this.commonTypes.getGeneratorInstance(firstNonNull(yieldType, UNKNOWN)));
} else if (declType.getNominalType() == null) {
// If a function doesn't return, make the return type unknown.
builder.addRetType(firstNonBottom(actualRetType, UNKNOWN));
} else {
// Don't infer a return type for constructors. We want to warn for
// constructors called without new who don't explicitly declare @return.
builder.addRetType(UNDEFINED);
}
}
use of com.google.javascript.jscomp.newtypes.JSType in project closure-compiler by google.
the class NewTypeInference method analyzeSuperFwd.
private EnvTypePair analyzeSuperFwd(Node expr, TypeEnv inEnv) {
checkArgument(expr.isSuper());
if (this.currentScope.hasThis()) {
NominalType thisClass = checkNotNull(envGetType(inEnv, THIS_ID).getNominalTypeIfSingletonObj());
NominalType superClass = thisClass.getInstantiatedSuperclass();
if (superClass == null) {
// This indicates bad code and there will probably be other errors reported.
// In particular JSC_NTI_INHERITANCE_CYCLE for `class Foo extends Foo ...`.
warnings.add(JSError.make(expr, UNDEFINED_SUPER_CLASS, thisClass.toString()));
return new EnvTypePair(inEnv, UNKNOWN);
}
if (this.currentScope.isConstructor()) {
JSType superCtor = commonTypes.fromFunctionType(superClass.getConstructorFunction());
return new EnvTypePair(inEnv, superCtor);
}
return new EnvTypePair(inEnv, superClass.getInstanceAsJSType());
}
// Use of super in a static method.
Node funName = NodeUtil.getBestLValue(this.currentScope.getRoot());
Node classNameNode = funName.getFirstChild();
JSType thisClassAsJstype = analyzeExprFwd(classNameNode, inEnv).type;
FunctionType thisCtor = thisClassAsJstype.getFunTypeIfSingletonObj();
NominalType thisClass = thisCtor.getThisType().getNominalTypeIfSingletonObj();
NominalType superClass = thisClass.getInstantiatedSuperclass();
if (superClass == null) {
// This indicates bad code and there will probably be other errors reported.
// In particular JSC_NTI_INHERITANCE_CYCLE for `class Foo extends Foo ...`.
warnings.add(JSError.make(expr, UNDEFINED_SUPER_CLASS, funName.toString()));
return new EnvTypePair(inEnv, UNKNOWN);
}
return new EnvTypePair(inEnv, superClass.getNamespaceType());
}
use of com.google.javascript.jscomp.newtypes.JSType in project closure-compiler by google.
the class NewTypeInference method analyzeLooseCallNodeFwd.
private EnvTypePair analyzeLooseCallNodeFwd(Node callNode, TypeEnv inEnv, JSType requiredType) {
checkArgument(callNode.isCall() || callNode.isNew());
Node callee = callNode.getFirstChild();
FunctionTypeBuilder builder = new FunctionTypeBuilder(this.commonTypes);
TypeEnv tmpEnv = inEnv;
for (Node arg = callee.getNext(); arg != null; arg = arg.getNext()) {
EnvTypePair pair = analyzeExprFwd(arg, tmpEnv);
tmpEnv = pair.env;
builder.addReqFormal(pair.type);
}
JSType looseRetType = requiredType.isUnknown() ? BOTTOM : requiredType;
JSType looseFunctionType = commonTypes.fromFunctionType(builder.addRetType(looseRetType).addLoose().buildFunction());
// Unsound if the arguments and callee have interacting side effects
EnvTypePair calleePair = analyzeExprFwd(callee, tmpEnv, commonTypes.topFunction(), looseFunctionType);
FunctionType calleeType = calleePair.type.getFunType();
JSType result = calleeType.getReturnType();
return new EnvTypePair(calleePair.env, isImpreciseType(result) ? requiredType : result);
}
use of com.google.javascript.jscomp.newtypes.JSType in project closure-compiler by google.
the class NewTypeInference method analyzeForOfFwd.
private TypeEnv analyzeForOfFwd(Node n, TypeEnv inEnv) {
Node rhs = n.getSecondChild();
EnvTypePair rhsPair = analyzeExprFwd(rhs, inEnv, pickReqObjType(n));
rhsPair = mayWarnAboutNullableReferenceAndTighten(n, rhsPair.type, null, inEnv);
JSType rhsObjType = rhsPair.type;
JSType boxedType = rhsObjType.autobox();
JSType lhsExpectedType;
JSType iterable = this.commonTypes.getIterableInstance(UNKNOWN);
if (boxedType.isSubtypeOf(iterable)) {
lhsExpectedType = boxedType.getInstantiatedTypeArgument(iterable);
} else {
warnings.add(JSError.make(rhs, FOROF_EXPECTS_ITERABLE, rhsObjType.toString()));
lhsExpectedType = UNKNOWN;
}
Node lhsNode = n.getFirstChild();
LValueResultFwd lhsLval = analyzeLValueFwd(lhsNode, inEnv, lhsExpectedType);
TypeEnv outEnv;
if (lhsLval.declType == null || lhsExpectedType.isSubtypeOf(lhsLval.declType)) {
outEnv = updateLvalueTypeInEnv(lhsLval.env, lhsNode, lhsLval.ptr, lhsExpectedType);
} else {
registerMismatchAndWarn(JSError.make(n, MISTYPED_FOROF_ELEMENT_TYPE, errorMsgWithTypeDiff(lhsLval.declType, lhsExpectedType)), lhsExpectedType, lhsLval.declType);
outEnv = updateLvalueTypeInEnv(lhsLval.env, lhsNode, lhsLval.ptr, lhsLval.declType);
}
return outEnv;
}
Aggregations