use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method analyzeReturnFwd.
private TypeEnv analyzeReturnFwd(Node n, TypeEnv inEnv) {
if (this.currentScope.getRoot().isGeneratorFunction()) {
JSType declRetType = getDeclaredReturnTypeOfCurrentScope(this.commonTypes.getGeneratorInstance(UNKNOWN));
if (n.hasChildren()) {
EnvTypePair retPair = analyzeExprFwd(n.getFirstChild(), inEnv, UNKNOWN);
return envPutType(retPair.env, RETVAL_ID, declRetType);
}
return envPutType(inEnv, RETVAL_ID, declRetType);
}
TypeEnv outEnv;
JSType declRetType = getDeclaredReturnTypeOfCurrentScope(UNKNOWN);
JSType actualRetType;
Node retExp = n.getFirstChild();
if (retExp == null) {
actualRetType = UNDEFINED;
outEnv = envPutType(inEnv, RETVAL_ID, actualRetType);
} else {
EnvTypePair retPair = analyzeExprFwd(retExp, inEnv, declRetType);
actualRetType = retPair.type;
outEnv = envPutType(retPair.env, RETVAL_ID, actualRetType);
}
if (!actualRetType.isSubtypeOf(declRetType)) {
registerMismatchAndWarn(JSError.make(n, RETURN_NONDECLARED_TYPE, errorMsgWithTypeDiff(declRetType, actualRetType)), actualRetType, declRetType);
}
return outEnv;
}
use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method analyzeEnumObjLitBwd.
private EnvTypePair analyzeEnumObjLitBwd(Node objLit, TypeEnv outEnv, JSType requiredType) {
if (objLit.getFirstChild() == null) {
return new EnvTypePair(outEnv, requiredType);
}
String pname = NodeUtil.getObjectLitKeyName(objLit.getFirstChild());
JSType enumeratedType = requiredType.getProp(new QualifiedName(pname)).getEnumeratedTypeOfEnumElement();
if (enumeratedType == null) {
return new EnvTypePair(outEnv, requiredType);
}
TypeEnv env = outEnv;
for (Node prop = objLit.getLastChild(); prop != null; prop = prop.getPrevious()) {
env = analyzeExprBwd(prop, env, enumeratedType).env;
}
return new EnvTypePair(env, requiredType);
}
use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method analyzeForInFwd.
private TypeEnv analyzeForInFwd(Node n, TypeEnv inEnv) {
Node obj = n.getSecondChild();
EnvTypePair pair = analyzeExprFwd(obj, inEnv, pickReqObjType(n));
pair = mayWarnAboutNullableReferenceAndTighten(n, pair.type, null, inEnv);
JSType objType = pair.type;
if (!objType.isSubtypeOf(TOP_OBJECT)) {
warnings.add(JSError.make(obj, FORIN_EXPECTS_OBJECT, objType.toString()));
} else if (objType.isStruct()) {
warnings.add(JSError.make(obj, IN_USED_WITH_STRUCT));
}
Node lhs = n.getFirstChild();
LValueResultFwd lval = analyzeLValueFwd(lhs, inEnv, STRING);
TypeEnv outEnv;
if (lval.declType != null && !commonTypes.isStringScalarOrObj(lval.declType)) {
warnings.add(JSError.make(lhs, FORIN_EXPECTS_STRING_KEY, lval.declType.toString()));
outEnv = lval.env;
} else {
outEnv = updateLvalueTypeInEnv(lval.env, lhs, lval.ptr, STRING);
}
return outEnv;
}
use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method analyzeArrayLitFwd.
private EnvTypePair analyzeArrayLitFwd(Node expr, TypeEnv inEnv) {
TypeEnv env = inEnv;
JSType elementType = BOTTOM;
for (Node arrayElm = expr.getFirstChild(); arrayElm != null; arrayElm = arrayElm.getNext()) {
EnvTypePair pair = analyzeExprFwd(arrayElm, env);
env = pair.env;
elementType = JSType.join(elementType, pair.type);
}
elementType = firstNonBottom(elementType, UNKNOWN);
return new EnvTypePair(env, commonTypes.getArrayInstance(elementType));
}
use of com.google.javascript.jscomp.newtypes.TypeEnv in project closure-compiler by google.
the class NewTypeInference method analyzeExprFwd.
/**
* @param requiredType The context requires this type; warn if the expression
* doesn't have this type.
* @param specializedType Used in boolean contexts to infer types of names.
*
* Invariant: specializedType is a subtype of requiredType.
*/
private EnvTypePair analyzeExprFwd(Node expr, TypeEnv inEnv, JSType requiredType, JSType specializedType) {
checkArgument(requiredType != null && !requiredType.isBottom());
EnvTypePair resultPair = null;
switch(expr.getToken()) {
case // can be created by a FOR with empty condition
EMPTY:
resultPair = new EnvTypePair(inEnv, UNKNOWN);
break;
case FUNCTION:
{
String fnName = symbolTable.getFunInternalName(expr);
JSType fnType = envGetType(inEnv, fnName);
Preconditions.checkState(fnType != null, "Could not find type for %s", fnName);
TypeEnv outEnv = collectTypesForEscapedVarsFwd(expr, inEnv);
resultPair = new EnvTypePair(outEnv, fnType);
break;
}
case FALSE:
case NULL:
case NUMBER:
case STRING:
case TRUE:
resultPair = new EnvTypePair(inEnv, scalarValueToType(expr.getToken()));
break;
case OBJECTLIT:
resultPair = analyzeObjLitFwd(expr, inEnv, requiredType, specializedType);
break;
case THIS:
{
resultPair = analyzeThisFwd(expr, inEnv, requiredType, specializedType);
break;
}
case SUPER:
{
resultPair = analyzeSuperFwd(expr, inEnv);
break;
}
case NAME:
resultPair = analyzeNameFwd(expr, inEnv, requiredType, specializedType);
break;
case AND:
case OR:
resultPair = analyzeLogicalOpFwd(expr, inEnv, requiredType, specializedType);
break;
case INC:
case DEC:
resultPair = analyzeIncDecFwd(expr, inEnv, requiredType);
break;
case BITNOT:
case NEG:
resultPair = analyzeUnaryNumFwd(expr, inEnv);
break;
case POS:
{
// We are more permissive with +, because it is used to coerce to number
resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv);
resultPair.type = NUMBER;
break;
}
case TYPEOF:
{
resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv);
resultPair.type = STRING;
break;
}
case INSTANCEOF:
resultPair = analyzeInstanceofFwd(expr, inEnv, specializedType);
break;
case ADD:
resultPair = analyzeAddFwd(expr, inEnv, requiredType);
break;
case BITOR:
case BITAND:
case BITXOR:
case DIV:
case EXPONENT:
case LSH:
case MOD:
case MUL:
case RSH:
case SUB:
case URSH:
resultPair = analyzeBinaryNumericOpFwd(expr, inEnv);
break;
case ASSIGN:
resultPair = analyzeAssignFwd(expr, inEnv, requiredType, specializedType);
break;
case ASSIGN_ADD:
resultPair = analyzeAssignAddFwd(expr, inEnv, requiredType);
break;
case ASSIGN_BITOR:
case ASSIGN_BITXOR:
case ASSIGN_BITAND:
case ASSIGN_LSH:
case ASSIGN_RSH:
case ASSIGN_URSH:
case ASSIGN_SUB:
case ASSIGN_MUL:
case ASSIGN_DIV:
case ASSIGN_MOD:
case ASSIGN_EXPONENT:
resultPair = analyzeAssignNumericOpFwd(expr, inEnv);
break;
case SHEQ:
case SHNE:
resultPair = analyzeStrictComparisonFwd(expr.getToken(), expr.getFirstChild(), expr.getLastChild(), inEnv, specializedType);
break;
case EQ:
case NE:
resultPair = analyzeNonStrictComparisonFwd(expr, inEnv, specializedType);
break;
case LT:
case GT:
case LE:
case GE:
resultPair = analyzeLtGtFwd(expr, inEnv);
break;
case GETPROP:
Preconditions.checkState(!NodeUtil.isAssignmentOp(expr.getParent()) || !NodeUtil.isLValue(expr));
if (expr.getBooleanProp(Node.ANALYZED_DURING_GTI)) {
if (expr.isQualifiedName() && !NodeUtil.isTypedefDecl(expr)) {
markAndGetTypeOfPreanalyzedNode(expr, inEnv, true);
}
expr.removeProp(Node.ANALYZED_DURING_GTI);
resultPair = new EnvTypePair(inEnv, requiredType);
} else {
resultPair = analyzePropAccessFwd(expr.getFirstChild(), expr.getLastChild().getString(), inEnv, requiredType, specializedType);
}
break;
case HOOK:
resultPair = analyzeHookFwd(expr, inEnv, requiredType, specializedType);
break;
case CALL:
case NEW:
case TAGGED_TEMPLATELIT:
resultPair = analyzeInvocationFwd(expr, inEnv, requiredType, specializedType);
break;
case COMMA:
resultPair = analyzeExprFwd(expr.getLastChild(), analyzeExprFwd(expr.getFirstChild(), inEnv).env, requiredType, specializedType);
break;
case NOT:
{
resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv, UNKNOWN, specializedType.negate());
resultPair.type = resultPair.type.negate().toBoolean();
break;
}
case GETELEM:
resultPair = analyzeGetElemFwd(expr, inEnv, requiredType, specializedType);
break;
case VOID:
{
resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv);
resultPair.type = UNDEFINED;
break;
}
case IN:
resultPair = analyzeInFwd(expr, inEnv, specializedType);
break;
case DELPROP:
{
// IRFactory checks that the operand is a name, getprop or getelem.
// analyzePropAccessFwd warns if we delete a constant property.
resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv);
resultPair.type = BOOLEAN;
break;
}
case REGEXP:
resultPair = new EnvTypePair(inEnv, commonTypes.getRegexpType());
break;
case ARRAYLIT:
resultPair = analyzeArrayLitFwd(expr, inEnv);
break;
case CAST:
resultPair = analyzeCastFwd(expr, inEnv);
break;
case CASE:
// For a statement of the form: switch (exp1) { ... case exp2: ... }
// we analyze the case as if it were (exp1 === exp2).
// We analyze the body of the case when the test is true and the stm
// following the body when the test is false.
resultPair = analyzeStrictComparisonFwd(Token.SHEQ, expr.getParent().getFirstChild(), expr.getFirstChild(), inEnv, specializedType);
break;
case TEMPLATELIT:
resultPair = analyzeTemplateLitFwd(expr, inEnv);
break;
case TEMPLATELIT_SUB:
resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv, requiredType);
break;
case STRING_KEY:
if (expr.hasChildren()) {
resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv, requiredType, specializedType);
} else {
resultPair = analyzeNameFwd(expr, inEnv, requiredType, specializedType);
}
break;
case MEMBER_FUNCTION_DEF:
resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv, requiredType, specializedType);
break;
case COMPUTED_PROP:
resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv, requiredType, specializedType);
resultPair = analyzeExprFwd(expr.getSecondChild(), resultPair.env, requiredType, specializedType);
break;
case YIELD:
resultPair = analyzeYieldFwd(expr, inEnv);
break;
default:
throw new RuntimeException("Unhandled expression type: " + expr.getToken());
}
JSType resultType = resultPair.type;
mayWarnAboutUnknownType(expr, resultType);
if (resultType.isUnresolved()) {
resultPair.type = UNKNOWN;
}
maybeSetTypeI(expr, resultType);
if (this.currentScope.isFunction()) {
// In global scope, the env is too big and produces too much output
println("AnalyzeExprFWD: ", expr, " ::reqtype: ", requiredType, " ::spectype: ", specializedType, " ::resulttype: ", resultType);
}
return resultPair;
}
Aggregations