src/com/google/javascript/jscomp/TypeCheck.java
/**
   * Checks that we can assign the given right type to the given lvalue.
   *
   * <p>If the lvalue is a qualified name, and has a declared type in the given scope, uses the
   * declared type of the qualified name instead of the type on the node.
   *
   * @param nodeToWarn A node to report type mismatch warnings on
   * @param lvalue The lvalue to which we're assigning - a NAME, GETELEM, or GETPROP
   * @param rightType The type we're assigning to the lvalue
   * @param msg A message to report along with any type mismatch warnings
   */
Checks that we can assign the given right type to the given lvalue.
If the lvalue is a qualified name, and has a declared type in the given scope, uses the
declared type of the qualified name instead of the type on the node.

@param nodeToWarn A node to report type mismatch warnings on
@param lvalue The lvalue to which we're assigning - a NAME, GETELEM, or GETPROP
@param rightType The type we're assigning to the lvalue
@param msg A message to report along with any type mismatch warnings
Checks that we can assign the given right type to the given lvalue . If the lvalue is a qualified name and has a declared type in the given scope uses the declared type of the qualified name instead of the type on the node . @param nodeToWarn A node to report type mismatch warnings on @param lvalue The lvalue to which we ' re assigning - a NAME GETELEM or GETPROP @param rightType The type we ' re assigning to the lvalue @param msg A message to report along with any type mismatch warnings
private void checkCanAssignToNameGetpropOrGetelem(
      NodeTraversal t, Node nodeToWarn, Node lvalue, JSType rightType, JSDocInfo info, String msg) {
    checkArgument(
        lvalue.isName() || lvalue.isGetProp() || lvalue.isGetElem() || lvalue.isCast(), lvalue);
    if (lvalue.isGetProp()) {
      Node object = lvalue.getFirstChild();
      JSType objectJsType = getJSType(object);
      Node property = lvalue.getLastChild();
      String pname = property.getString();
      if (object.isGetProp()) {
        JSType jsType = getJSType(object.getFirstChild());
        if (jsType.isInterface() && object.getLastChild().getString().equals("prototype")) {
          visitInterfacePropertyAssignment(t, object, lvalue);
        }
      }
      checkEnumAlias(t, info, rightType, nodeToWarn);
      checkPropCreation(t, lvalue);
      if (pname.equals("prototype")) {
        validator.expectCanAssignToPrototype(t, objectJsType, nodeToWarn, rightType);
        return;
      }
      ObjectType objectCastType = ObjectType.cast(objectJsType.restrictByNotNullOrUndefined());
      JSType expectedPropertyType = getPropertyTypeIfDeclared(objectCastType, pname);
      checkPropertyInheritanceOnGetpropAssign(
          t, nodeToWarn, object, pname, info, expectedPropertyType);
      if (!expectedPropertyType.isUnknownType()) {
        if (!propertyIsImplicitCast(objectCastType, pname)) {
          validator.expectCanAssignToPropertyOf(
              t, nodeToWarn, rightType, expectedPropertyType, object, pname);
        }
        return;
      }
    }
    JSType leftType = getJSType(lvalue);
    if (lvalue.isQualifiedName()) {
      TypedVar var = t.getTypedScope().getVar(lvalue.getQualifiedName());
      if (var != null) {
        if (var.isTypeInferred()) {
          return;
        }
        if (NodeUtil.getRootOfQualifiedName(lvalue).isThis()
            && t.getTypedScope() != var.getScope()) {
          return;
        }
        if (var.getType() != null) {
          leftType = var.getType();
        }
      }
    } 
    validator.expectCanAssignTo(t, nodeToWarn, rightType, leftType, msg);
  }
private void checkCanAssignToNameGetpropOrGetelem ( NodeTraversal t , Node nodeToWarn , Node lvalue , JSType rightType , JSDocInfo info , String msg ) { checkArgument ( lvalue . isName ( ) || lvalue . isGetProp ( ) || lvalue . isGetElem ( ) || lvalue . isCast ( ) , lvalue ) ; if ( lvalue . isGetProp ( ) ) { Node object = lvalue . getFirstChild ( ) ; JSType objectJsType = getJSType ( object ) ; Node property = lvalue . getLastChild ( ) ; String pname = property . getString ( ) ; if ( object . isGetProp ( ) ) { JSType jsType = getJSType ( object . getFirstChild ( ) ) ; if ( jsType . isInterface ( ) && object . getLastChild ( ) . getString ( ) . equals ( "prototype" ) ) { visitInterfacePropertyAssignment ( t , object , lvalue ) ; } } checkEnumAlias ( t , info , rightType , nodeToWarn ) ; checkPropCreation ( t , lvalue ) ; if ( pname . equals ( "prototype" ) ) { validator . expectCanAssignToPrototype ( t , objectJsType , nodeToWarn , rightType ) ; return ; } ObjectType objectCastType = ObjectType . cast ( objectJsType . restrictByNotNullOrUndefined ( ) ) ; JSType expectedPropertyType = getPropertyTypeIfDeclared ( objectCastType , pname ) ; checkPropertyInheritanceOnGetpropAssign ( t , nodeToWarn , object , pname , info , expectedPropertyType ) ; if ( ! expectedPropertyType . isUnknownType ( ) ) { if ( ! propertyIsImplicitCast ( objectCastType , pname ) ) { validator . expectCanAssignToPropertyOf ( t , nodeToWarn , rightType , expectedPropertyType , object , pname ) ; } return ; } } JSType leftType = getJSType ( lvalue ) ; if ( lvalue . isQualifiedName ( ) ) { TypedVar var = t . getTypedScope ( ) . getVar ( lvalue . getQualifiedName ( ) ) ; if ( var != null ) { if ( var . isTypeInferred ( ) ) { return ; } if ( NodeUtil . getRootOfQualifiedName ( lvalue ) . isThis ( ) && t . getTypedScope ( ) != var . getScope ( ) ) { return ; } if ( var . getType ( ) != null ) { leftType = var . getType ( ) ; } } } validator . expectCanAssignTo ( t , nodeToWarn , rightType , leftType , msg ) ; }
Checks that we can assign the given right type to the given lvalue.
Checks that we can assign the given right type to the given lvalue .
// the first name in this getprop refers to an interface // we perform checks in addition to the ones below // Prototype assignments are special, because they actually affect // the definition of a class. These are mostly validated // during TypedScopeCreator, and we only look for the "dumb" cases here. // object.prototype = ...; // The generic checks for 'object.property' when 'object' is known, // and 'property' is declared on it. // object.property = ...; // If we successfully found a non-unknown declared type, validate the assignment and don't do // any further checks. // Note: if the property has @implicitCast at its declaration, we don't check any // assignments to it. // Check qualified name sets to 'object' and 'object.property'. // This can sometimes handle cases when the type of 'object' is not known. // e.g., // var obj = createUnknownType(); // /** @type {number} */ obj.foo = true; // variable with inferred type case // Don't look at "this.foo" variables from other scopes. // Fall through case for arbitrary LHS and arbitrary RHS.