Program: 28049
Project: 28049
Buggy source:
/** 
 * Visits an assignment <code>lvalue = rvalue</code>. If the <code>lvalue</code> is a prototype modification, we change the schema of the object type it is referring to.
 * @param t the traversal
 * @param assign the assign node(<code>assign.isAssign()</code> is an implicit invariant)
 */
private void visitAssign(NodeTraversal t,Node assign){
  JSDocInfo info=assign.getJSDocInfo();
  Node lvalue=assign.getFirstChild();
  Node rvalue=assign.getLastChild();
  if (lvalue.isGetProp()) {
    Node object=lvalue.getFirstChild();
    JSType objectJsType=getJSType(object);
    String property=lvalue.getLastChild().getString();
    if (object.isGetProp()) {
      JSType jsType=getJSType(object.getFirstChild());
      if (jsType.isInterface() && object.getLastChild().getString().equals("String_Node_Str")) {
        visitInterfaceGetprop(t,assign,object,property,lvalue,rvalue);
      }
    }
    checkEnumAlias(t,info,rvalue);
    if (property.equals("String_Node_Str")) {
      if (objectJsType != null && objectJsType.isFunctionType()) {
        FunctionType functionType=objectJsType.toMaybeFunctionType();
        if (functionType.isConstructor()) {
          JSType rvalueType=rvalue.getJSType();
          validator.expectObject(t,rvalue,rvalueType,OVERRIDING_PROTOTYPE_WITH_NON_OBJECT);
          return;
        }
      }
    }
    if (object.isGetProp()) {
      Node object2=object.getFirstChild();
      String property2=NodeUtil.getStringValue(object.getLastChild());
      if ("String_Node_Str".equals(property2)) {
        JSType jsType=getJSType(object2);
        if (jsType.isFunctionType()) {
          FunctionType functionType=jsType.toMaybeFunctionType();
          if (functionType.isConstructor() || functionType.isInterface()) {
            checkDeclaredPropertyInheritance(t,assign,functionType,property,info,getJSType(rvalue));
          }
        }
      }
    }
    ObjectType type=ObjectType.cast(objectJsType.restrictByNotNullOrUndefined());
    if (type != null) {
      if (type.hasProperty(property) && !type.isPropertyTypeInferred(property) && !propertyIsImplicitCast(type,property)) {
        validator.expectCanAssignToPropertyOf(t,assign,getJSType(rvalue),type.getPropertyType(property),object,property);
        return;
      }
    }
  }
  JSType leftType=getJSType(lvalue);
  if (lvalue.isQualifiedName()) {
    JSType rvalueType=getJSType(assign.getLastChild());
    Var var=t.getScope().getVar(lvalue.getQualifiedName());
    if (var != null) {
      if (var.isTypeInferred()) {
        return;
      }
      if (var.getType() != null) {
        leftType=var.getType();
      }
    }
  }
  Node rightChild=assign.getLastChild();
  JSType rightType=getJSType(rightChild);
  if (validator.expectCanAssignTo(t,assign,rightType,leftType,"String_Node_Str")) {
    ensureTyped(t,assign,rightType);
  }
 else {
    ensureTyped(t,assign);
  }
}

Fixed version (ground truth):
/** 
 * Visits an assignment <code>lvalue = rvalue</code>. If the <code>lvalue</code> is a prototype modification, we change the schema of the object type it is referring to.
 * @param t the traversal
 * @param assign the assign node(<code>assign.isAssign()</code> is an implicit invariant)
 */
private void visitAssign(NodeTraversal t,Node assign){
  JSDocInfo info=assign.getJSDocInfo();
  Node lvalue=assign.getFirstChild();
  Node rvalue=assign.getLastChild();
  if (lvalue.isGetProp()) {
    Node object=lvalue.getFirstChild();
    JSType objectJsType=getJSType(object);
    String property=lvalue.getLastChild().getString();
    if (object.isGetProp()) {
      JSType jsType=getJSType(object.getFirstChild());
      if (jsType.isInterface() && object.getLastChild().getString().equals("String_Node_Str")) {
        visitInterfaceGetprop(t,assign,object,property,lvalue,rvalue);
      }
    }
    checkEnumAlias(t,info,rvalue);
    if (property.equals("String_Node_Str")) {
      if (objectJsType != null && objectJsType.isFunctionType()) {
        FunctionType functionType=objectJsType.toMaybeFunctionType();
        if (functionType.isConstructor()) {
          JSType rvalueType=rvalue.getJSType();
          validator.expectObject(t,rvalue,rvalueType,OVERRIDING_PROTOTYPE_WITH_NON_OBJECT);
          return;
        }
      }
    }
    if (object.isGetProp()) {
      Node object2=object.getFirstChild();
      String property2=NodeUtil.getStringValue(object.getLastChild());
      if ("String_Node_Str".equals(property2)) {
        JSType jsType=getJSType(object2);
        if (jsType.isFunctionType()) {
          FunctionType functionType=jsType.toMaybeFunctionType();
          if (functionType.isConstructor() || functionType.isInterface()) {
            checkDeclaredPropertyInheritance(t,assign,functionType,property,info,getJSType(rvalue));
          }
        }
      }
    }
    ObjectType type=ObjectType.cast(objectJsType.restrictByNotNullOrUndefined());
    if (type != null) {
      if (type.hasProperty(property) && !type.isPropertyTypeInferred(property) && !propertyIsImplicitCast(type,property)) {
        JSType expectedType=type.getPropertyType(property);
        if (!expectedType.isUnknownType()) {
          validator.expectCanAssignToPropertyOf(t,assign,getJSType(rvalue),expectedType,object,property);
          return;
        }
      }
    }
  }
  JSType leftType=getJSType(lvalue);
  if (lvalue.isQualifiedName()) {
    JSType rvalueType=getJSType(assign.getLastChild());
    Var var=t.getScope().getVar(lvalue.getQualifiedName());
    if (var != null) {
      if (var.isTypeInferred()) {
        return;
      }
      if (NodeUtil.getRootOfQualifiedName(lvalue).isThis() && t.getScope() != var.getScope()) {
        return;
      }
      if (var.getType() != null) {
        leftType=var.getType();
      }
    }
  }
  Node rightChild=assign.getLastChild();
  JSType rightType=getJSType(rightChild);
  if (validator.expectCanAssignTo(t,assign,rightType,leftType,"String_Node_Str")) {
    ensureTyped(t,assign,rightType);
  }
 else {
    ensureTyped(t,assign);
  }
}