use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method analyzeInvocationArgumentsFwd.
private TypeEnv analyzeInvocationArgumentsFwd(Node n, Iterable<Node> args, FunctionType funType, List<JSType> argTypesForDeferredCheck, TypeEnv inEnv) {
checkState(NodeUtil.isCallOrNew(n) || n.isTemplateLit());
TypeEnv env = inEnv;
int i = n.isTemplateLit() ? 1 : 0;
for (Node arg : args) {
JSType formalType = funType.getFormalType(i);
checkState(!formalType.isBottom());
EnvTypePair pair = analyzeExprFwd(arg, env, formalType);
if (NodeUtil.isUnannotatedCallback(arg) && formalType.getFunType() != null) {
i++;
// No deferred check needed.
argTypesForDeferredCheck.add(null);
continue;
}
JSType argTypeForDeferredCheck = pair.type;
// Allow passing undefined for an optional argument.
if (funType.isOptionalArg(i) && pair.type.equals(UNDEFINED)) {
// No deferred check needed.
argTypeForDeferredCheck = null;
} else if (!pair.type.isSubtypeOf(formalType)) {
warnAboutInvalidArgument(n, arg, i, formalType, pair.type);
// No deferred check needed.
argTypeForDeferredCheck = null;
} else {
registerImplicitUses(arg, pair.type, formalType);
}
argTypesForDeferredCheck.add(argTypeForDeferredCheck);
env = pair.env;
i++;
}
return env;
}
use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method analyzeFunctionFwd.
private void analyzeFunctionFwd(NTIWorkset workset) {
for (DiGraphNode<Node, ControlFlowGraph.Branch> dn : workset.forward()) {
Node n = dn.getValue();
Node parent = n.getParent();
checkState(n != null, "Implicit return should not be in workset.");
TypeEnv inEnv = getInEnv(dn);
TypeEnv outEnv = null;
if (parent.isScript() || (parent.isNormalBlock() && parent.getParent().isFunction())) {
// All joins have merged; forget changes
inEnv = inEnv.clearChangeLog();
}
println("\tFWD Statment: ", n);
println("\t\tinEnv: ", inEnv);
boolean conditional = false;
switch(n.getToken()) {
case BLOCK:
case ROOT:
case BREAK:
case CONTINUE:
case DEFAULT_CASE:
case DEBUGGER:
case EMPTY:
case FUNCTION:
case SCRIPT:
case TRY:
case // We don't typecheck WITH, we just avoid crashing.
WITH:
outEnv = inEnv;
break;
case CATCH:
Node catchVar = n.getFirstChild();
String catchVarname = catchVar.getString();
outEnv = envPutType(inEnv, catchVarname, UNKNOWN);
maybeSetTypeI(catchVar, UNKNOWN);
break;
case EXPR_RESULT:
println("\tsemi ", n.getFirstChild().getToken());
if (n.getBooleanProp(Node.ANALYZED_DURING_GTI)) {
n.removeProp(Node.ANALYZED_DURING_GTI);
outEnv = inEnv;
} else {
outEnv = analyzeExprFwd(n.getFirstChild(), inEnv, UNKNOWN).env;
}
break;
case RETURN:
outEnv = analyzeReturnFwd(n, inEnv);
break;
case DO:
case IF:
case FOR:
case WHILE:
conditional = true;
analyzeConditionalStmFwd(dn, NodeUtil.getConditionExpression(n), inEnv);
break;
case FOR_IN:
outEnv = analyzeForInFwd(n, inEnv);
break;
case FOR_OF:
outEnv = analyzeForOfFwd(n, inEnv);
break;
case CASE:
{
conditional = true;
// See analyzeExprFwd#Token.CASE for how to handle this precisely
analyzeConditionalStmFwd(dn, n, inEnv);
break;
}
case VAR:
outEnv = inEnv;
if (NodeUtil.isTypedefDecl(n)) {
maybeSetTypeI(n.getFirstChild(), UNDEFINED);
break;
}
for (Node nameNode : n.children()) {
outEnv = analyzeVarDeclFwd(nameNode, outEnv);
}
break;
case SWITCH:
outEnv = analyzeExprFwd(n.getFirstChild(), inEnv).env;
break;
case THROW:
{
outEnv = analyzeExprFwd(n.getFirstChild(), inEnv).env;
exitEnvs.add(outEnv);
break;
}
default:
if (NodeUtil.isStatement(n)) {
throw new RuntimeException("Unhandled statement type: " + n.getToken());
} else {
outEnv = analyzeExprFwd(n, inEnv, UNKNOWN).env;
break;
}
}
if (!conditional) {
println("\t\toutEnv: ", outEnv);
setOutEnv(dn, outEnv);
}
}
}
use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method getTypeEnvFromDeclaredTypes.
private TypeEnv getTypeEnvFromDeclaredTypes() {
TypeEnv env = new TypeEnv();
Set<String> varNames = this.currentScope.getOuterVars();
Set<String> locals = this.currentScope.getLocals();
varNames.addAll(locals);
varNames.addAll(this.currentScope.getExterns());
if (this.currentScope.hasThis()) {
varNames.add(THIS_ID);
}
if (this.currentScope.isFunction()) {
Node fn = this.currentScope.getRoot();
if (!this.currentScope.hasThis() && // a function.
NodeUtil.containsType(fn.getLastChild(), Token.SUPER, NodeUtil.MATCH_NOT_FUNCTION)) {
// This function is a static method on some class. To do lookups of the
// class name, we add the root of the qualified name to the environment.
Node funNameNode = NodeUtil.getBestLValue(fn);
Node qnameRoot = NodeUtil.getRootOfQualifiedName(funNameNode);
checkState(qnameRoot.isName());
varNames.add(qnameRoot.getString());
}
if (this.currentScope.getName() != null) {
varNames.add(this.currentScope.getName());
}
varNames.addAll(this.currentScope.getFormals());
// In the rare case when there is a local variable named "arguments",
// this entry will be overwritten in the foreach loop below.
JSType argumentsType;
DeclaredFunctionType dft = this.currentScope.getDeclaredTypeForOwnBody();
if (dft.getOptionalArity() == 0 && dft.hasRestFormals()) {
argumentsType = dft.getRestFormalsType();
} else {
argumentsType = UNKNOWN;
}
env = envPutType(env, "arguments", commonTypes.getArgumentsArrayType(argumentsType));
}
for (String varName : varNames) {
if (!this.currentScope.isLocalFunDef(varName)) {
JSType declType = this.currentScope.getDeclaredTypeOf(varName);
if (declType == null) {
declType = UNKNOWN;
} else if (areTypeVariablesUnknown) {
declType = declType.substituteGenericsWithUnknown();
}
env = envPutType(env, varName, declType);
}
}
for (String fnName : this.currentScope.getLocalFunDefs()) {
env = envPutType(env, fnName, getSummaryOfLocalFunDef(fnName));
}
return env;
}
use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method analyzeInvocationBwd.
private EnvTypePair analyzeInvocationBwd(Node expr, TypeEnv outEnv, JSType requiredType) {
checkArgument(expr.isNew() || expr.isCall() || expr.isTaggedTemplateLit());
Node callee = expr.getFirstChild();
EnvTypePair pair = analyzeExprBwd(callee, outEnv, commonTypes.topFunction());
TypeEnv envAfterCallee = pair.env;
FunctionType funType = pair.type.getFunType();
if (funType == null) {
return analyzeInvocationArgumentsBwd(expr, expr.getFirstChild(), envAfterCallee);
} else if (funType.isLoose()) {
return analyzeLooseCallNodeBwd(expr, envAfterCallee, requiredType);
} else if ((expr.isCall() && funType.isSomeConstructorOrInterface()) || (expr.isNew() && !funType.isSomeConstructorOrInterface())) {
return analyzeInvocationArgumentsBwd(expr, expr.getFirstChild(), envAfterCallee);
} else if (funType.isTopFunction()) {
return analyzeInvocationArgumentsBwd(expr, expr.getFirstChild(), envAfterCallee);
}
if (callee.isName() && !funType.isGeneric() && (expr.isCall() || expr.isTaggedTemplateLit())) {
createDeferredCheckBwd(expr, requiredType);
}
int numArgs = NodeUtil.getInvocationArgsCount(expr);
if (numArgs < funType.getMinArity() || numArgs > funType.getMaxArity()) {
if (expr.isTaggedTemplateLit()) {
return analyzeInvocationArgumentsBwd(expr.getLastChild(), null, envAfterCallee);
} else {
return analyzeInvocationArgumentsBwd(expr, expr.getFirstChild(), envAfterCallee);
}
}
if (funType.isGeneric()) {
Map<String, JSType> typeMap = calcTypeInstantiationBwd(expr, funType, envAfterCallee);
funType = funType.instantiateGenerics(typeMap);
}
TypeEnv tmpEnv = envAfterCallee;
// In bwd direction, analyze arguments in reverse
Node target = expr.isTaggedTemplateLit() ? null : expr.getFirstChild();
Node start = expr.isTaggedTemplateLit() ? expr.getLastChild().getLastChild() : expr.getLastChild();
int i = numArgs;
for (Node arg = start; arg != target; arg = arg.getPrevious()) {
if (expr.isTaggedTemplateLit() && !arg.isTemplateLitSub()) {
// with the formal types of the tag function, i needs to stay unchanged here.
continue;
}
i--;
JSType formalType = funType.getFormalType(i);
// The type of a formal can be BOTTOM as the result of a join.
// Don't use this as a requiredType.
formalType = firstNonBottom(formalType, UNKNOWN);
tmpEnv = analyzeExprBwd(arg, tmpEnv, formalType).env;
// We don't need deferred checks for args in BWD
}
JSType retType = expr.isNew() ? funType.getThisType() : funType.getReturnType();
return new EnvTypePair(tmpEnv, retType);
}
use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method mayWarnAboutNullableReferenceAndTighten.
private EnvTypePair mayWarnAboutNullableReferenceAndTighten(Node obj, JSType recvType, JSType maybeSpecType, TypeEnv inEnv) {
if (!recvType.isUnknown() && !recvType.isTop() && (NULL.isSubtypeOf(recvType) || UNDEFINED.isSubtypeOf(recvType))) {
JSType minusNull = recvType.removeType(NULL_OR_UNDEFINED);
if (!minusNull.isBottom()) {
if (this.reportNullDeref) {
warnings.add(JSError.make(obj, NULLABLE_DEREFERENCE, recvType.toString()));
}
TypeEnv outEnv = inEnv;
if (obj.isQualifiedName()) {
QualifiedName qname = QualifiedName.fromNode(obj);
if (maybeSpecType != null && maybeSpecType.isSubtypeOf(minusNull)) {
minusNull = maybeSpecType;
}
outEnv = updateLvalueTypeInEnv(inEnv, obj, qname, minusNull);
}
return new EnvTypePair(outEnv, minusNull);
}
}
return new EnvTypePair(inEnv, recvType);
}
Aggregations