src/com/google/javascript/jscomp/TypeCheck.java
/**
   * Given a constructor type and a property name, check that the property has
   * the JSDoc annotation @override iff the property is declared on a
   * superclass. Several checks regarding inheritance correctness are also
   * performed.
   */
Given a constructor type and a property name, check that the property has
the JSDoc annotation @override iff the property is declared on a
superclass. Several checks regarding inheritance correctness are also
performed.
Given a constructor type and a property name check that the property has the JSDoc annotation @override iff the property is declared on a superclass . Several checks regarding inheritance correctness are also performed .
private void checkDeclaredPropertyInheritance(
      NodeTraversal t, Node n, FunctionType ctorType, String propertyName,
      JSDocInfo info, JSType propertyType) {
    if (hasUnknownOrEmptySupertype(ctorType)) {
      return;
    }
    FunctionType superClass = ctorType.getSuperClassConstructor();
    boolean superClassHasProperty =
        superClass != null && superClass.getInstanceType().hasProperty(propertyName);
    boolean superClassHasDeclaredProperty =
        superClass != null && superClass.getInstanceType().isPropertyTypeDeclared(propertyName);
    boolean superInterfaceHasProperty = false;
    boolean superInterfaceHasDeclaredProperty = false;
    if (ctorType.isInterface()) {
      for (ObjectType interfaceType : ctorType.getExtendedInterfaces()) {
        superInterfaceHasProperty =
            superInterfaceHasProperty || interfaceType.hasProperty(propertyName);
        superInterfaceHasDeclaredProperty =
            superInterfaceHasDeclaredProperty || interfaceType.isPropertyTypeDeclared(propertyName);
      }
    }
    boolean declaredOverride = info != null && info.isOverride();
    boolean foundInterfaceProperty = false;
    if (ctorType.isConstructor()) {
      for (JSType implementedInterface :
          ctorType.getAllImplementedInterfaces()) {
        if (implementedInterface.isUnknownType() || implementedInterface.isEmptyType()) {
          continue;
        }
        FunctionType interfaceType =
            implementedInterface.toObjectType().getConstructor();
        checkNotNull(interfaceType);
        boolean interfaceHasProperty =
            interfaceType.getPrototype().hasProperty(propertyName);
        foundInterfaceProperty = foundInterfaceProperty || interfaceHasProperty;
        if (!declaredOverride
            && interfaceHasProperty
            && !"__proto__".equals(propertyName)
            && !"constructor".equals(propertyName)) {
          compiler.report(
              t.makeError(
                  n,
                  HIDDEN_INTERFACE_PROPERTY,
                  propertyName,
                  interfaceType.getTopMostDefiningType(propertyName).toString()));
        }
      }
    }
    if (!declaredOverride
        && !superClassHasProperty
        && !superInterfaceHasProperty) {
      return;
    }
    ObjectType topInstanceType = superClassHasDeclaredProperty
        ? superClass.getTopMostDefiningType(propertyName) : null;
    boolean declaredLocally =
        ctorType.isConstructor()
            && (ctorType.getPrototype().hasOwnProperty(propertyName)
                || ctorType.getInstanceType().hasOwnProperty(propertyName));
    if (!declaredOverride
        && superClassHasDeclaredProperty
        && declaredLocally
        && !"__proto__".equals(propertyName)
        && !"constructor".equals(propertyName)) {
      compiler.report(
          t.makeError(n, HIDDEN_SUPERCLASS_PROPERTY, propertyName, topInstanceType.toString()));
    }
    if (superClassHasDeclaredProperty) {
      JSType superClassPropType =
          superClass.getInstanceType().getPropertyType(propertyName);
      TemplateTypeMap ctorTypeMap =
          ctorType.getTypeOfThis().getTemplateTypeMap();
      if (!ctorTypeMap.isEmpty()) {
        superClassPropType = superClassPropType.visit(
            new TemplateTypeMapReplacer(typeRegistry, ctorTypeMap));
      }
      if (!propertyType.isSubtype(superClassPropType, this.subtypingMode)) {
        compiler.report(
            t.makeError(n, HIDDEN_SUPERCLASS_PROPERTY_MISMATCH,
                propertyName, topInstanceType.toString(),
                superClassPropType.toString(), propertyType.toString()));
      }
    } else if (superInterfaceHasDeclaredProperty) {
      for (ObjectType interfaceType : ctorType.getExtendedInterfaces()) {
        if (interfaceType.hasProperty(propertyName)) {
          JSType superPropertyType =
              interfaceType.getPropertyType(propertyName);
          if (!propertyType.isSubtype(superPropertyType, this.subtypingMode)) {
            topInstanceType = interfaceType.getConstructor().
                getTopMostDefiningType(propertyName);
            compiler.report(
                t.makeError(n, HIDDEN_SUPERCLASS_PROPERTY_MISMATCH,
                    propertyName, topInstanceType.toString(),
                    superPropertyType.toString(),
                    propertyType.toString()));
          }
        }
      }
    } else if (!foundInterfaceProperty
        && !superClassHasProperty
        && !superInterfaceHasProperty) {
      compiler.report(
          t.makeError(n, UNKNOWN_OVERRIDE,
              propertyName, ctorType.getInstanceType().toString()));
    }
  }
private void checkDeclaredPropertyInheritance ( NodeTraversal t , Node n , FunctionType ctorType , String propertyName , JSDocInfo info , JSType propertyType ) { if ( hasUnknownOrEmptySupertype ( ctorType ) ) { return ; } FunctionType superClass = ctorType . getSuperClassConstructor ( ) ; boolean superClassHasProperty = superClass != null && superClass . getInstanceType ( ) . hasProperty ( propertyName ) ; boolean superClassHasDeclaredProperty = superClass != null && superClass . getInstanceType ( ) . isPropertyTypeDeclared ( propertyName ) ; boolean superInterfaceHasProperty = false ; boolean superInterfaceHasDeclaredProperty = false ; if ( ctorType . isInterface ( ) ) { for ( ObjectType interfaceType : ctorType . getExtendedInterfaces ( ) ) { superInterfaceHasProperty = superInterfaceHasProperty || interfaceType . hasProperty ( propertyName ) ; superInterfaceHasDeclaredProperty = superInterfaceHasDeclaredProperty || interfaceType . isPropertyTypeDeclared ( propertyName ) ; } } boolean declaredOverride = info != null && info . isOverride ( ) ; boolean foundInterfaceProperty = false ; if ( ctorType . isConstructor ( ) ) { for ( JSType implementedInterface : ctorType . getAllImplementedInterfaces ( ) ) { if ( implementedInterface . isUnknownType ( ) || implementedInterface . isEmptyType ( ) ) { continue ; } FunctionType interfaceType = implementedInterface . toObjectType ( ) . getConstructor ( ) ; checkNotNull ( interfaceType ) ; boolean interfaceHasProperty = interfaceType . getPrototype ( ) . hasProperty ( propertyName ) ; foundInterfaceProperty = foundInterfaceProperty || interfaceHasProperty ; if ( ! declaredOverride && interfaceHasProperty && ! "__proto__" . equals ( propertyName ) && ! "constructor" . equals ( propertyName ) ) { compiler . report ( t . makeError ( n , HIDDEN_INTERFACE_PROPERTY , propertyName , interfaceType . getTopMostDefiningType ( propertyName ) . toString ( ) ) ) ; } } } if ( ! declaredOverride && ! superClassHasProperty && ! superInterfaceHasProperty ) { return ; } ObjectType topInstanceType = superClassHasDeclaredProperty ? superClass . getTopMostDefiningType ( propertyName ) : null ; boolean declaredLocally = ctorType . isConstructor ( ) && ( ctorType . getPrototype ( ) . hasOwnProperty ( propertyName ) || ctorType . getInstanceType ( ) . hasOwnProperty ( propertyName ) ) ; if ( ! declaredOverride && superClassHasDeclaredProperty && declaredLocally && ! "__proto__" . equals ( propertyName ) && ! "constructor" . equals ( propertyName ) ) { compiler . report ( t . makeError ( n , HIDDEN_SUPERCLASS_PROPERTY , propertyName , topInstanceType . toString ( ) ) ) ; } if ( superClassHasDeclaredProperty ) { JSType superClassPropType = superClass . getInstanceType ( ) . getPropertyType ( propertyName ) ; TemplateTypeMap ctorTypeMap = ctorType . getTypeOfThis ( ) . getTemplateTypeMap ( ) ; if ( ! ctorTypeMap . isEmpty ( ) ) { superClassPropType = superClassPropType . visit ( new TemplateTypeMapReplacer ( typeRegistry , ctorTypeMap ) ) ; } if ( ! propertyType . isSubtype ( superClassPropType , this . subtypingMode ) ) { compiler . report ( t . makeError ( n , HIDDEN_SUPERCLASS_PROPERTY_MISMATCH , propertyName , topInstanceType . toString ( ) , superClassPropType . toString ( ) , propertyType . toString ( ) ) ) ; } } else if ( superInterfaceHasDeclaredProperty ) { for ( ObjectType interfaceType : ctorType . getExtendedInterfaces ( ) ) { if ( interfaceType . hasProperty ( propertyName ) ) { JSType superPropertyType = interfaceType . getPropertyType ( propertyName ) ; if ( ! propertyType . isSubtype ( superPropertyType , this . subtypingMode ) ) { topInstanceType = interfaceType . getConstructor ( ) . getTopMostDefiningType ( propertyName ) ; compiler . report ( t . makeError ( n , HIDDEN_SUPERCLASS_PROPERTY_MISMATCH , propertyName , topInstanceType . toString ( ) , superPropertyType . toString ( ) , propertyType . toString ( ) ) ) ; } } } } else if ( ! foundInterfaceProperty && ! superClassHasProperty && ! superInterfaceHasProperty ) { compiler . report ( t . makeError ( n , UNKNOWN_OVERRIDE , propertyName , ctorType . getInstanceType ( ) . toString ( ) ) ) ; } }
Given a constructor type and a property name, check that the property has
 the JSDoc annotation @override iff the property is declared on a
 superclass.
Given a constructor type and a property name check that the property has the JSDoc annotation @override iff the property is declared on a superclass .
// If the supertype doesn't resolve correctly, we've warned about this // already. // For interface // @override not present, but the property does override an interface property // nothing to do here, it's just a plain new property // constructor always "overrides" the superclass "constructor" there is no // value in marking it with "@override". // @override not present, but the property does override a superclass // property // @override is present and we have to check that it is ok // there is a superclass implementation // there is an super interface property // there is no superclass nor interface implementation