use of com.google.javascript.rhino.jstype.JSType in project closure-compiler by google.
the class TypeInference method traverseName.
private FlowScope traverseName(Node n, FlowScope scope) {
String varName = n.getString();
Node value = n.getFirstChild();
JSType type = n.getJSType();
if (value != null) {
scope = traverse(value, scope);
updateScopeForTypeChange(scope, n, n.getJSType(), /* could be null */
getJSType(value));
return scope;
} else {
StaticTypedSlot<JSType> var = scope.getSlot(varName);
if (var != null) {
// There are two situations where we don't want to use type information
// from the scope, even if we have it.
// 1) The var is escaped and assigned in an inner scope, e.g.,
// function f() { var x = 3; function g() { x = null } (x); }
boolean isInferred = var.isTypeInferred();
boolean unflowable = isInferred && isUnflowable(currentScope.getVar(varName));
// 2) We're reading type information from another scope for an
// inferred variable. That variable is assigned more than once,
// and we can't know which type we're getting.
//
// var t = null; function f() { (t); } doStuff(); t = {};
//
// Notice that this heuristic isn't perfect. For example, you might
// have:
//
// function f() { (t); } f(); var t = 3;
//
// In this case, we would infer the first reference to t as
// type {number}, even though it's undefined.
TypedVar maybeOuterVar = isInferred && cfgRootScope.isLocal() ? cfgRootScope.getParent().getVar(varName) : null;
boolean nonLocalInferredSlot = var.equals(maybeOuterVar) && !maybeOuterVar.isMarkedAssignedExactlyOnce();
if (!unflowable && !nonLocalInferredSlot) {
type = var.getType();
if (type == null) {
type = unknownType;
}
}
}
}
n.setJSType(type);
return scope;
}
use of com.google.javascript.rhino.jstype.JSType in project closure-compiler by google.
the class TypeInference method traverseAdd.
private FlowScope traverseAdd(Node n, FlowScope scope) {
Node left = n.getFirstChild();
Node right = left.getNext();
scope = traverseChildren(n, scope);
JSType leftType = left.getJSType();
JSType rightType = right.getJSType();
JSType type = unknownType;
if (leftType != null && rightType != null) {
boolean leftIsUnknown = leftType.isUnknownType();
boolean rightIsUnknown = rightType.isUnknownType();
if (leftIsUnknown && rightIsUnknown) {
type = unknownType;
} else if ((!leftIsUnknown && leftType.isString()) || (!rightIsUnknown && rightType.isString())) {
type = getNativeType(STRING_TYPE);
} else if (leftIsUnknown || rightIsUnknown) {
type = unknownType;
} else if (isAddedAsNumber(leftType) && isAddedAsNumber(rightType)) {
type = getNativeType(NUMBER_TYPE);
} else {
type = registry.createUnionType(STRING_TYPE, NUMBER_TYPE);
}
}
n.setJSType(type);
if (n.isAssignAdd()) {
updateScopeForTypeChange(scope, left, leftType, type);
}
return scope;
}
use of com.google.javascript.rhino.jstype.JSType in project closure-compiler by google.
the class TypeInference method inferArguments.
/**
* Infers all of a function's arguments if their types aren't declared.
*/
// unknownType is a singleton
@SuppressWarnings("ReferenceEquality")
private void inferArguments(TypedScope functionScope) {
Node functionNode = functionScope.getRootNode();
Node astParameters = functionNode.getSecondChild();
Node iifeArgumentNode = null;
if (NodeUtil.isInvocationTarget(functionNode)) {
iifeArgumentNode = functionNode.getNext();
}
FunctionType functionType = JSType.toMaybeFunctionType(functionNode.getJSType());
if (functionType != null) {
Node parameterTypes = functionType.getParametersNode();
if (parameterTypes != null) {
Node parameterTypeNode = parameterTypes.getFirstChild();
for (Node astParameter : astParameters.children()) {
TypedVar var = functionScope.getVar(astParameter.getString());
checkNotNull(var);
if (var.isTypeInferred() && var.getType() == unknownType) {
JSType newType = null;
if (iifeArgumentNode != null) {
newType = iifeArgumentNode.getJSType();
} else if (parameterTypeNode != null) {
newType = parameterTypeNode.getJSType();
}
if (newType != null) {
var.setType(newType);
astParameter.setJSType(newType);
}
}
if (parameterTypeNode != null) {
parameterTypeNode = parameterTypeNode.getNext();
}
if (iifeArgumentNode != null) {
iifeArgumentNode = iifeArgumentNode.getNext();
}
}
}
}
}
use of com.google.javascript.rhino.jstype.JSType in project closure-compiler by google.
the class TypeInference method traverseCall.
private FlowScope traverseCall(Node n, FlowScope scope) {
scope = traverseChildren(n, scope);
Node left = n.getFirstChild();
JSType functionType = getJSType(left).restrictByNotNullOrUndefined();
if (functionType.isFunctionType()) {
FunctionType fnType = functionType.toMaybeFunctionType();
n.setJSType(fnType.getReturnType());
backwardsInferenceFromCallSite(n, fnType);
} else if (functionType.isEquivalentTo(getNativeType(CHECKED_UNKNOWN_TYPE))) {
n.setJSType(getNativeType(CHECKED_UNKNOWN_TYPE));
}
scope = tightenTypesAfterAssertions(scope, n);
return scope;
}
use of com.google.javascript.rhino.jstype.JSType in project closure-compiler by google.
the class TypeInference method resolvedTemplateType.
private static void resolvedTemplateType(Map<TemplateType, JSType> map, TemplateType template, JSType resolved) {
JSType previous = map.get(template);
if (!resolved.isUnknownType()) {
if (previous == null) {
map.put(template, resolved);
} else {
JSType join = previous.getLeastSupertype(resolved);
map.put(template, join);
}
}
}
Aggregations