private NominalType getMaybeParentClass( JSDocInfo jsdoc, String functionName, Node funNode, ImmutableList<String> typeParameters, DeclaredTypeRegistry registry) { if (!jsdoc.hasBaseType()) { return null; } if (!jsdoc.isConstructor()) { warnings.add(JSError.make(funNode, EXTENDS_NOT_ON_CTOR_OR_INTERF, functionName)); return null; } Node docNode = jsdoc.getBaseType().getRoot(); JSType extendedType = getMaybeTypeFromComment(docNode, registry, typeParameters); if (extendedType == null) { return null; } NominalType parentClass = extendedType.getNominalTypeIfSingletonObj(); if (parentClass != null && parentClass.isClass()) { return parentClass; } if (parentClass == null) { warnings.add( JSError.make(funNode, EXTENDS_NON_OBJECT, functionName, extendedType.toString())); } else { Preconditions.checkState(parentClass.isInterface()); warnings.add(JSError.make(funNode, CONFLICTING_EXTENDED_TYPE, "constructor", functionName)); } return null; }
boolean isNominalSubtypeOf(NominalType other) { RawNominalType thisRaw = this.rawType; if (thisRaw == other.rawType) { return areTypeMapsCompatible(other); } if (other.isBuiltinObject()) { return true; } if (other.isInterface()) { // If thisRaw is not finalized, thisRaw.interfaces may be null. for (NominalType i : thisRaw.getInterfaces()) { if (i.instantiateGenerics(this.typeMap).isNominalSubtypeOf(other)) { return true; } } } // Note that other can still be an interface here (implemented by a superclass) return isClass() && thisRaw.getSuperClass() != null && thisRaw.getSuperClass().instantiateGenerics(this.typeMap).isNominalSubtypeOf(other); }
// Returns a type with the same raw type as other, but possibly different type maps. private NominalType findMatchingAncestorWith(NominalType other) { RawNominalType thisRaw = this.rawType; if (thisRaw == other.rawType) { return this; } if (other.isInterface()) { for (NominalType i : thisRaw.getInterfaces()) { NominalType nt = i.instantiateGenerics(this.typeMap).findMatchingAncestorWith(other); if (nt != null) { return nt; } } } // Note that other can still be an interface here (implemented by a superclass) if (isClass() && thisRaw.getSuperClass() != null) { return thisRaw .getSuperClass() .instantiateGenerics(this.typeMap) .findMatchingAncestorWith(other); } return null; }
private ImmutableSet<NominalType> getInterfacesHelper( JSDocInfo jsdoc, DeclaredTypeRegistry registry, ImmutableList<String> typeParameters, boolean implementedIntfs) { ImmutableSet.Builder<NominalType> builder = ImmutableSet.builder(); for (JSTypeExpression texp : (implementedIntfs ? jsdoc.getImplementedInterfaces() : jsdoc.getExtendedInterfaces())) { Node expRoot = texp.getRoot(); JSType interfaceType = getMaybeTypeFromComment(expRoot, registry, typeParameters); if (interfaceType != null) { NominalType nt = interfaceType.getNominalTypeIfSingletonObj(); if (nt != null && nt.isInterface()) { builder.add(nt); } else if (implementedIntfs) { warnings.add(JSError.make(expRoot, IMPLEMENTS_NON_INTERFACE, interfaceType.toString())); } else { warnings.add(JSError.make(expRoot, EXTENDS_NON_INTERFACE, interfaceType.toString())); } } } return builder.build(); }