use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method analyzeObjLitBwd.
private EnvTypePair analyzeObjLitBwd(Node objLit, TypeEnv outEnv, JSType requiredType) {
if (NodeUtil.isEnumDecl(objLit.getParent())) {
return analyzeEnumObjLitBwd(objLit, outEnv, requiredType);
}
TypeEnv env = outEnv;
JSType result = pickReqObjType(objLit);
for (Node prop = objLit.getLastChild(); prop != null; prop = prop.getPrevious()) {
if (prop.isGetterDef() || prop.isSetterDef()) {
env = analyzeExprBwd(prop.getFirstChild(), env).env;
} else if (prop.isComputedProp() && !prop.getFirstChild().isString()) {
env = analyzeExprBwd(prop, env).env;
} else {
QualifiedName pname = new QualifiedName(NodeUtil.getObjectLitKeyName(prop));
JSType jsdocType = (JSType) prop.getTypeI();
JSType reqPtype;
if (jsdocType != null) {
reqPtype = jsdocType;
} else if (requiredType.mayHaveProp(pname)) {
reqPtype = requiredType.getProp(pname);
} else {
reqPtype = UNKNOWN;
}
EnvTypePair pair = analyzeExprBwd(prop, env, reqPtype);
result = result.withProperty(pname, pair.type);
env = pair.env;
}
}
return new EnvTypePair(env, result);
}
use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method getExitTypeEnv.
private TypeEnv getExitTypeEnv() {
for (int i = 0; i < exitEnvs.size(); i++) {
TypeEnv env = exitEnvs.get(i);
exitEnvs.set(i, envPutType(env, RETVAL_ID, BOTTOM));
}
if (!this.cfg.getImplicitReturn().getInEdges().isEmpty()) {
exitEnvs.add(getInEnv(this.cfg.getImplicitReturn()));
}
checkState(!exitEnvs.isEmpty(), "There must be at least one exit env, either from a normal function exit or a throw.");
return TypeEnv.join(exitEnvs);
}
use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method analyzeNonStrictComparisonFwd.
private EnvTypePair analyzeNonStrictComparisonFwd(Node expr, TypeEnv inEnv, JSType specializedType) {
Token tokenType = expr.getToken();
Node lhs = expr.getFirstChild();
Node rhs = expr.getLastChild();
if (specializedType.isTrueOrTruthy() || specializedType.isFalseOrFalsy()) {
if (lhs.isTypeOf()) {
return analyzeSpecializedTypeof(lhs, rhs, tokenType, inEnv, specializedType);
} else if (rhs.isTypeOf()) {
return analyzeSpecializedTypeof(rhs, lhs, tokenType, inEnv, specializedType);
} else if (isGoogTypeof(lhs)) {
return analyzeGoogTypeof(lhs, rhs, inEnv, specializedType);
} else if (isGoogTypeof(rhs)) {
return analyzeGoogTypeof(rhs, lhs, inEnv, specializedType);
}
}
EnvTypePair lhsPair = analyzeExprFwd(lhs, inEnv);
EnvTypePair rhsPair = analyzeExprFwd(rhs, lhsPair.env);
// This env may contain types that have been tightened after nullable deref.
TypeEnv preciseEnv = rhsPair.env;
JSType lhsType = lhsPair.type;
JSType rhsType = rhsPair.type;
if ((tokenType == Token.EQ && specializedType.isTrueOrTruthy()) || (tokenType == Token.NE && specializedType.isFalseOrFalsy())) {
if (lhsType.isNullOrUndef()) {
rhsPair = analyzeExprFwd(rhs, preciseEnv, UNKNOWN, NULL_OR_UNDEFINED);
} else if (rhsType.isNullOrUndef()) {
lhsPair = analyzeExprFwd(lhs, preciseEnv, UNKNOWN, NULL_OR_UNDEFINED);
rhsPair = analyzeExprFwd(rhs, lhsPair.env);
} else if (!NULL.isSubtypeOf(lhsType) && !UNDEFINED.isSubtypeOf(lhsType)) {
rhsType = rhsType.removeType(NULL_OR_UNDEFINED);
rhsPair = analyzeExprFwd(rhs, preciseEnv, UNKNOWN, rhsType);
} else if (!NULL.isSubtypeOf(rhsType) && !UNDEFINED.isSubtypeOf(rhsType)) {
lhsType = lhsType.removeType(NULL_OR_UNDEFINED);
lhsPair = analyzeExprFwd(lhs, preciseEnv, UNKNOWN, lhsType);
rhsPair = analyzeExprFwd(rhs, lhsPair.env);
}
} else if ((tokenType == Token.EQ && specializedType.isFalseOrFalsy()) || (tokenType == Token.NE && specializedType.isTrueOrTruthy())) {
if (lhsType.isNullOrUndef()) {
rhsType = rhsType.removeType(NULL_OR_UNDEFINED);
rhsPair = analyzeExprFwd(rhs, preciseEnv, UNKNOWN, rhsType);
} else if (rhsType.isNullOrUndef()) {
lhsType = lhsType.removeType(NULL_OR_UNDEFINED);
lhsPair = analyzeExprFwd(lhs, preciseEnv, UNKNOWN, lhsType);
rhsPair = analyzeExprFwd(rhs, lhsPair.env);
}
}
rhsPair.type = BOOLEAN;
return rhsPair;
}
use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method analyzeAssignBwd.
private EnvTypePair analyzeAssignBwd(Node expr, TypeEnv outEnv, JSType requiredType) {
if (expr.getBooleanProp(Node.ANALYZED_DURING_GTI)) {
return new EnvTypePair(outEnv, requiredType);
}
Node lhs = expr.getFirstChild();
Node rhs = expr.getLastChild();
if (lhs.getBooleanProp(Node.ANALYZED_DURING_GTI)) {
return analyzeExprBwd(rhs, outEnv, markAndGetTypeOfPreanalyzedNode(lhs, outEnv, false));
}
// Here we analyze the LHS twice:
// Once to find out what should be removed for the slicedEnv,
// and again to take into account the side effects of the LHS itself.
LValueResultBwd lvalue = analyzeLValueBwd(lhs, outEnv, requiredType, true);
TypeEnv slicedEnv = lvalue.env;
JSType rhsReqType = specializeKeep2ndWhenBottom(lvalue.type, requiredType);
EnvTypePair pair = analyzeExprBwd(rhs, slicedEnv, rhsReqType);
pair.env = analyzeLValueBwd(lhs, pair.env, requiredType, true).env;
return pair;
}
use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method createSummary.
private void createSummary(NTIScope fn) {
Node fnRoot = fn.getRoot();
checkArgument(!fnRoot.isFromExterns());
FunctionTypeBuilder builder = new FunctionTypeBuilder(this.commonTypes);
TypeEnv entryEnv = getEntryTypeEnv();
TypeEnv exitEnv = getExitTypeEnv();
DeclaredFunctionType declType = fn.getDeclaredFunctionType();
int reqArity = declType.getRequiredArity();
int optArity = declType.getOptionalArity();
if (declType.isGeneric()) {
builder.addTypeParameters(declType.getTypeParameters());
}
// Every trailing undeclared formal whose inferred type is ?
// or contains undefined can be marked as optional.
List<String> formals = fn.getFormals();
for (int i = reqArity - 1; i >= 0; i--) {
JSType formalType = declType.getFormalType(i);
if (formalType != null) {
break;
}
String formalName = formals.get(i);
formalType = getTypeAfterFwd(formalName, entryEnv, exitEnv);
if (formalType.isUnknown() || UNDEFINED.isSubtypeOf(formalType)) {
reqArity--;
} else {
break;
}
}
// Collect types of formals in the builder
int i = 0;
for (String formalName : formals) {
JSType formalType = declType.getFormalType(i);
if (formalType == null) {
formalType = getTypeAfterFwd(formalName, entryEnv, exitEnv);
}
if (i < reqArity) {
builder.addReqFormal(formalType);
} else if (i < optArity) {
builder.addOptFormal(formalType);
}
i++;
}
if (declType.hasRestFormals()) {
builder.addRestFormals(declType.getFormalType(i));
}
for (String outer : fn.getOuterVars()) {
println("Free var ", outer, " going in summary");
builder.addOuterVarPrecondition(outer, envGetType(entryEnv, outer));
}
builder.addNominalType(declType.getNominalType());
builder.addReceiverType(declType.getReceiverType());
builder.addAbstract(declType.isAbstract());
addRetTypeAndWarn(fn, exitEnv, declType, builder);
JSType summary = commonTypes.fromFunctionType(builder.buildFunction());
println("Function summary for ", fn.getReadableName());
println("\t", summary);
summary = changeTypeIfFunctionNamespace(fn, summary);
summaries.put(fn, summary);
maybeSetTypeI(fnRoot, summary);
Node fnNameNode = NodeUtil.getNameNode(fnRoot);
if (fnNameNode != null) {
maybeSetTypeI(fnNameNode, summary);
}
}
Aggregations