}
// Check if the type has already been computed during scope-creation.
// This is mostly useful for literals like BOOLEAN, NUMBER, STRING, and
// OBJECT_LITERAL
JSType type = rValue.getJSType();
if (type != null && !type.isUnknownType()) {
return type;
}
// If rValue is a name, try looking it up in the current scope.
if (rValue.isQualifiedName()) {
return lookupQualifiedName(rValue);
}
// Check for simple invariant operations, such as "!x" or "+x" or "''+x"
if (NodeUtil.isBooleanResult(rValue)) {
return getNativeType(BOOLEAN_TYPE);
}
if (NodeUtil.isNumericResult(rValue)) {
return getNativeType(NUMBER_TYPE);
}
if (NodeUtil.isStringResult(rValue)) {
return getNativeType(STRING_TYPE);
}
if (rValue.isNew() && rValue.getFirstChild().isQualifiedName()) {
JSType targetType = lookupQualifiedName(rValue.getFirstChild());
if (targetType != null) {
FunctionType fnType = targetType
.restrictByNotNullOrUndefined()
.toMaybeFunctionType();
if (fnType != null && fnType.hasInstanceType()) {
return fnType.getInstanceType();
}