Program: 18682
Project: 18682
Buggy source:
/** 
 * This is the meat of the type checking.  It is basically one big switch, with each case representing one type of parse tree node.  The individual cases are usually pretty straightforward.
 * @param t The node traversal object that supplies context, such as thescope chain to use in name lookups as well as error reporting.
 * @param n The node being visited.
 * @param parent The parent of the node n.
 */
@Override public void visit(NodeTraversal t,Node n,Node parent){
  JSType childType;
  JSType leftType, rightType;
  Node left, right;
  boolean typeable=true;
switch (n.getType()) {
case Token.NAME:
    typeable=visitName(t,n,parent);
  break;
case Token.PARAM_LIST:
if (!parent.isFunction()) {
  ensureTyped(t,n,getJSType(n.getFirstChild()));
}
 else {
  typeable=false;
}
break;
case Token.COMMA:
ensureTyped(t,n,getJSType(n.getLastChild()));
break;
case Token.TRUE:
case Token.FALSE:
ensureTyped(t,n,BOOLEAN_TYPE);
break;
case Token.THIS:
ensureTyped(t,n,t.getScope().getTypeOfThis());
break;
case Token.NULL:
ensureTyped(t,n,NULL_TYPE);
break;
case Token.NUMBER:
ensureTyped(t,n,NUMBER_TYPE);
break;
case Token.STRING:
ensureTyped(t,n,STRING_TYPE);
break;
case Token.STRING_KEY:
typeable=false;
break;
case Token.GETTER_DEF:
case Token.SETTER_DEF:
break;
case Token.ARRAYLIT:
ensureTyped(t,n,ARRAY_TYPE);
break;
case Token.REGEXP:
ensureTyped(t,n,REGEXP_TYPE);
break;
case Token.GETPROP:
visitGetProp(t,n,parent);
typeable=!(parent.isAssign() && parent.getFirstChild() == n);
break;
case Token.GETELEM:
visitGetElem(t,n);
typeable=false;
break;
case Token.VAR:
visitVar(t,n);
typeable=false;
break;
case Token.NEW:
visitNew(t,n);
typeable=true;
break;
case Token.CALL:
visitCall(t,n);
typeable=!parent.isExprResult();
break;
case Token.RETURN:
visitReturn(t,n);
typeable=false;
break;
case Token.DEC:
case Token.INC:
left=n.getFirstChild();
validator.expectNumber(t,left,getJSType(left),"String_Node_Str");
ensureTyped(t,n,NUMBER_TYPE);
break;
case Token.NOT:
ensureTyped(t,n,BOOLEAN_TYPE);
break;
case Token.VOID:
ensureTyped(t,n,VOID_TYPE);
break;
case Token.TYPEOF:
ensureTyped(t,n,STRING_TYPE);
break;
case Token.BITNOT:
childType=getJSType(n.getFirstChild());
if (!childType.matchesInt32Context()) {
report(t,n,BIT_OPERATION,NodeUtil.opToStr(n.getType()),childType.toString());
}
ensureTyped(t,n,NUMBER_TYPE);
break;
case Token.POS:
case Token.NEG:
left=n.getFirstChild();
validator.expectNumber(t,left,getJSType(left),"String_Node_Str");
ensureTyped(t,n,NUMBER_TYPE);
break;
case Token.EQ:
case Token.NE:
case Token.SHEQ:
case Token.SHNE:
{
leftType=getJSType(n.getFirstChild());
rightType=getJSType(n.getLastChild());
JSType leftTypeRestricted=leftType.restrictByNotNullOrUndefined();
JSType rightTypeRestricted=rightType.restrictByNotNullOrUndefined();
TernaryValue result=TernaryValue.UNKNOWN;
if (n.getType() == Token.EQ || n.getType() == Token.NE) {
result=leftTypeRestricted.testForEquality(rightTypeRestricted);
if (n.isNE()) {
result=result.not();
}
}
 else {
if (!leftTypeRestricted.canTestForShallowEqualityWith(rightTypeRestricted)) {
result=n.getType() == Token.SHEQ ? TernaryValue.FALSE : TernaryValue.TRUE;
}
}
if (result != TernaryValue.UNKNOWN) {
report(t,n,DETERMINISTIC_TEST,leftType.toString(),rightType.toString(),result.toString());
}
ensureTyped(t,n,BOOLEAN_TYPE);
break;
}
case Token.LT:
case Token.LE:
case Token.GT:
case Token.GE:
leftType=getJSType(n.getFirstChild());
rightType=getJSType(n.getLastChild());
if (rightType.isNumber()) {
validator.expectNumber(t,n,leftType,"String_Node_Str");
}
 else if (leftType.isNumber()) {
validator.expectNumber(t,n,rightType,"String_Node_Str");
}
 else if (leftType.matchesNumberContext() && rightType.matchesNumberContext()) {
}
 else {
String message="String_Node_Str";
validator.expectString(t,n,leftType,message);
validator.expectNotNullOrUndefined(t,n,leftType,message,getNativeType(STRING_TYPE));
message="String_Node_Str";
validator.expectString(t,n,rightType,message);
validator.expectNotNullOrUndefined(t,n,rightType,message,getNativeType(STRING_TYPE));
}
ensureTyped(t,n,BOOLEAN_TYPE);
break;
case Token.IN:
left=n.getFirstChild();
right=n.getLastChild();
leftType=getJSType(left);
rightType=getJSType(right);
validator.expectObject(t,n,rightType,"String_Node_Str");
validator.expectString(t,left,leftType,"String_Node_Str");
ensureTyped(t,n,BOOLEAN_TYPE);
break;
case Token.INSTANCEOF:
left=n.getFirstChild();
right=n.getLastChild();
leftType=getJSType(left);
rightType=getJSType(right).restrictByNotNullOrUndefined();
validator.expectAnyObject(t,left,leftType,"String_Node_Str");
validator.expectActualObject(t,right,rightType,"String_Node_Str");
ensureTyped(t,n,BOOLEAN_TYPE);
break;
case Token.ASSIGN:
visitAssign(t,n);
typeable=false;
break;
case Token.ASSIGN_LSH:
case Token.ASSIGN_RSH:
case Token.ASSIGN_URSH:
case Token.ASSIGN_DIV:
case Token.ASSIGN_MOD:
case Token.ASSIGN_BITOR:
case Token.ASSIGN_BITXOR:
case Token.ASSIGN_BITAND:
case Token.ASSIGN_SUB:
case Token.ASSIGN_ADD:
case Token.ASSIGN_MUL:
case Token.LSH:
case Token.RSH:
case Token.URSH:
case Token.DIV:
case Token.MOD:
case Token.BITOR:
case Token.BITXOR:
case Token.BITAND:
case Token.SUB:
case Token.ADD:
case Token.MUL:
visitBinaryOperator(n.getType(),t,n);
break;
case Token.DELPROP:
ensureTyped(t,n,BOOLEAN_TYPE);
break;
case Token.CASE:
JSType switchType=getJSType(parent.getFirstChild());
JSType caseType=getJSType(n.getFirstChild());
validator.expectSwitchMatchesCase(t,n,switchType,caseType);
typeable=false;
break;
case Token.WITH:
{
Node child=n.getFirstChild();
childType=getJSType(child);
validator.expectObject(t,child,childType,"String_Node_Str");
typeable=false;
break;
}
case Token.FUNCTION:
visitFunction(t,n);
break;
case Token.LABEL:
case Token.LABEL_NAME:
case Token.SWITCH:
case Token.BREAK:
case Token.CATCH:
case Token.TRY:
case Token.SCRIPT:
case Token.EXPR_RESULT:
case Token.BLOCK:
case Token.EMPTY:
case Token.DEFAULT_CASE:
case Token.CONTINUE:
case Token.DEBUGGER:
case Token.THROW:
typeable=false;
break;
case Token.DO:
case Token.FOR:
case Token.IF:
case Token.WHILE:
typeable=false;
break;
case Token.AND:
case Token.HOOK:
case Token.OBJECTLIT:
case Token.OR:
if (n.getJSType() != null) {
ensureTyped(t,n);
}
 else {
if ((n.isObjectLit()) && (parent.getJSType() instanceof EnumType)) {
ensureTyped(t,n,parent.getJSType());
}
 else {
ensureTyped(t,n);
}
}
if (n.isObjectLit()) {
for (Node key : n.children()) {
visitObjLitKey(t,key,n);
}
}
break;
default :
report(t,n,UNEXPECTED_TOKEN,Token.name(n.getType()));
ensureTyped(t,n);
break;
}
typeable=typeable && !inExterns;
if (typeable) {
doPercentTypedAccounting(t,n);
}
checkNoTypeCheckSection(n,false);
}

Fixed version (ground truth):
/** 
 * This is the meat of the type checking.  It is basically one big switch, with each case representing one type of parse tree node.  The individual cases are usually pretty straightforward.
 * @param t The node traversal object that supplies context, such as thescope chain to use in name lookups as well as error reporting.
 * @param n The node being visited.
 * @param parent The parent of the node n.
 */
@Override public void visit(NodeTraversal t,Node n,Node parent){
  JSType childType;
  JSType leftType, rightType;
  Node left, right;
  boolean typeable=true;
switch (n.getType()) {
case Token.NAME:
    typeable=visitName(t,n,parent);
  break;
case Token.PARAM_LIST:
if (!parent.isFunction()) {
  ensureTyped(t,n,getJSType(n.getFirstChild()));
}
 else {
  typeable=false;
}
break;
case Token.COMMA:
ensureTyped(t,n,getJSType(n.getLastChild()));
break;
case Token.TRUE:
case Token.FALSE:
ensureTyped(t,n,BOOLEAN_TYPE);
break;
case Token.THIS:
ensureTyped(t,n,t.getScope().getTypeOfThis());
break;
case Token.NULL:
ensureTyped(t,n,NULL_TYPE);
break;
case Token.NUMBER:
ensureTyped(t,n,NUMBER_TYPE);
break;
case Token.STRING:
ensureTyped(t,n,STRING_TYPE);
break;
case Token.STRING_KEY:
typeable=false;
break;
case Token.GETTER_DEF:
case Token.SETTER_DEF:
break;
case Token.ARRAYLIT:
ensureTyped(t,n,ARRAY_TYPE);
break;
case Token.REGEXP:
ensureTyped(t,n,REGEXP_TYPE);
break;
case Token.GETPROP:
visitGetProp(t,n,parent);
typeable=!(parent.isAssign() && parent.getFirstChild() == n);
break;
case Token.GETELEM:
visitGetElem(t,n);
typeable=false;
break;
case Token.VAR:
visitVar(t,n);
typeable=false;
break;
case Token.NEW:
visitNew(t,n);
typeable=true;
break;
case Token.CALL:
visitCall(t,n);
typeable=!parent.isExprResult();
break;
case Token.RETURN:
visitReturn(t,n);
typeable=false;
break;
case Token.DEC:
case Token.INC:
left=n.getFirstChild();
validator.expectNumber(t,left,getJSType(left),"String_Node_Str");
ensureTyped(t,n,NUMBER_TYPE);
break;
case Token.NOT:
ensureTyped(t,n,BOOLEAN_TYPE);
break;
case Token.VOID:
ensureTyped(t,n,VOID_TYPE);
break;
case Token.TYPEOF:
ensureTyped(t,n,STRING_TYPE);
break;
case Token.BITNOT:
childType=getJSType(n.getFirstChild());
if (!childType.matchesInt32Context()) {
report(t,n,BIT_OPERATION,NodeUtil.opToStr(n.getType()),childType.toString());
}
ensureTyped(t,n,NUMBER_TYPE);
break;
case Token.POS:
case Token.NEG:
left=n.getFirstChild();
validator.expectNumber(t,left,getJSType(left),"String_Node_Str");
ensureTyped(t,n,NUMBER_TYPE);
break;
case Token.EQ:
case Token.NE:
case Token.SHEQ:
case Token.SHNE:
{
left=n.getFirstChild();
right=n.getLastChild();
if (left.isTypeOf()) {
if (right.isString()) {
checkTypeofString(t,right,right.getString());
}
}
 else if (right.isTypeOf() && left.isString()) {
checkTypeofString(t,left,left.getString());
}
leftType=getJSType(left);
rightType=getJSType(right);
JSType leftTypeRestricted=leftType.restrictByNotNullOrUndefined();
JSType rightTypeRestricted=rightType.restrictByNotNullOrUndefined();
TernaryValue result=TernaryValue.UNKNOWN;
if (n.getType() == Token.EQ || n.getType() == Token.NE) {
result=leftTypeRestricted.testForEquality(rightTypeRestricted);
if (n.isNE()) {
result=result.not();
}
}
 else {
if (!leftTypeRestricted.canTestForShallowEqualityWith(rightTypeRestricted)) {
result=n.getType() == Token.SHEQ ? TernaryValue.FALSE : TernaryValue.TRUE;
}
}
if (result != TernaryValue.UNKNOWN) {
report(t,n,DETERMINISTIC_TEST,leftType.toString(),rightType.toString(),result.toString());
}
ensureTyped(t,n,BOOLEAN_TYPE);
break;
}
case Token.LT:
case Token.LE:
case Token.GT:
case Token.GE:
leftType=getJSType(n.getFirstChild());
rightType=getJSType(n.getLastChild());
if (rightType.isNumber()) {
validator.expectNumber(t,n,leftType,"String_Node_Str");
}
 else if (leftType.isNumber()) {
validator.expectNumber(t,n,rightType,"String_Node_Str");
}
 else if (leftType.matchesNumberContext() && rightType.matchesNumberContext()) {
}
 else {
String message="String_Node_Str";
validator.expectString(t,n,leftType,message);
validator.expectNotNullOrUndefined(t,n,leftType,message,getNativeType(STRING_TYPE));
message="String_Node_Str";
validator.expectString(t,n,rightType,message);
validator.expectNotNullOrUndefined(t,n,rightType,message,getNativeType(STRING_TYPE));
}
ensureTyped(t,n,BOOLEAN_TYPE);
break;
case Token.IN:
left=n.getFirstChild();
right=n.getLastChild();
leftType=getJSType(left);
rightType=getJSType(right);
validator.expectObject(t,n,rightType,"String_Node_Str");
validator.expectString(t,left,leftType,"String_Node_Str");
ensureTyped(t,n,BOOLEAN_TYPE);
break;
case Token.INSTANCEOF:
left=n.getFirstChild();
right=n.getLastChild();
leftType=getJSType(left);
rightType=getJSType(right).restrictByNotNullOrUndefined();
validator.expectAnyObject(t,left,leftType,"String_Node_Str");
validator.expectActualObject(t,right,rightType,"String_Node_Str");
ensureTyped(t,n,BOOLEAN_TYPE);
break;
case Token.ASSIGN:
visitAssign(t,n);
typeable=false;
break;
case Token.ASSIGN_LSH:
case Token.ASSIGN_RSH:
case Token.ASSIGN_URSH:
case Token.ASSIGN_DIV:
case Token.ASSIGN_MOD:
case Token.ASSIGN_BITOR:
case Token.ASSIGN_BITXOR:
case Token.ASSIGN_BITAND:
case Token.ASSIGN_SUB:
case Token.ASSIGN_ADD:
case Token.ASSIGN_MUL:
case Token.LSH:
case Token.RSH:
case Token.URSH:
case Token.DIV:
case Token.MOD:
case Token.BITOR:
case Token.BITXOR:
case Token.BITAND:
case Token.SUB:
case Token.ADD:
case Token.MUL:
visitBinaryOperator(n.getType(),t,n);
break;
case Token.DELPROP:
ensureTyped(t,n,BOOLEAN_TYPE);
break;
case Token.CASE:
JSType switchType=getJSType(parent.getFirstChild());
JSType caseType=getJSType(n.getFirstChild());
validator.expectSwitchMatchesCase(t,n,switchType,caseType);
typeable=false;
break;
case Token.WITH:
{
Node child=n.getFirstChild();
childType=getJSType(child);
validator.expectObject(t,child,childType,"String_Node_Str");
typeable=false;
break;
}
case Token.FUNCTION:
visitFunction(t,n);
break;
case Token.LABEL:
case Token.LABEL_NAME:
case Token.SWITCH:
case Token.BREAK:
case Token.CATCH:
case Token.TRY:
case Token.SCRIPT:
case Token.EXPR_RESULT:
case Token.BLOCK:
case Token.EMPTY:
case Token.DEFAULT_CASE:
case Token.CONTINUE:
case Token.DEBUGGER:
case Token.THROW:
typeable=false;
break;
case Token.DO:
case Token.FOR:
case Token.IF:
case Token.WHILE:
typeable=false;
break;
case Token.AND:
case Token.HOOK:
case Token.OBJECTLIT:
case Token.OR:
if (n.getJSType() != null) {
ensureTyped(t,n);
}
 else {
if ((n.isObjectLit()) && (parent.getJSType() instanceof EnumType)) {
ensureTyped(t,n,parent.getJSType());
}
 else {
ensureTyped(t,n);
}
}
if (n.isObjectLit()) {
for (Node key : n.children()) {
visitObjLitKey(t,key,n);
}
}
break;
default :
report(t,n,UNEXPECTED_TOKEN,Token.name(n.getType()));
ensureTyped(t,n);
break;
}
typeable=typeable && !inExterns;
if (typeable) {
doPercentTypedAccounting(t,n);
}
checkNoTypeCheckSection(n,false);
}