}
// base type
if (info.hasBaseType()) {
if (isConstructor) {
JSType maybeBaseType =
info.getBaseType().evaluate(scope, typeRegistry);
if (maybeBaseType != null &&
maybeBaseType.setValidator(new ExtendedTypeValidator())) {
baseType = (ObjectType) maybeBaseType;
}
} else {
reportWarning(EXTENDS_WITHOUT_TYPEDEF, formatFnName());
}
}
// Implemented interfaces (for constructors only).
if (info.getImplementedInterfaceCount() > 0) {
if (isConstructor) {
implementedInterfaces = Lists.newArrayList();
Set<JSType> baseInterfaces = new HashSet<>();
for (JSTypeExpression t : info.getImplementedInterfaces()) {
JSType maybeInterType = t.evaluate(scope, typeRegistry);
if (maybeInterType != null &&
maybeInterType.setValidator(new ImplementedTypeValidator())) {
// Disallow implementing the same base (not templatized) interface
// type more than once.
JSType baseInterface = maybeInterType;
if (baseInterface.toMaybeTemplatizedType() != null) {
baseInterface =
baseInterface.toMaybeTemplatizedType().getReferencedType();
}
if (baseInterfaces.contains(baseInterface)) {
reportWarning(SAME_INTERFACE_MULTIPLE_IMPLEMENTS,
baseInterface.toString());
} else {
baseInterfaces.add(baseInterface);
}
implementedInterfaces.add((ObjectType) maybeInterType);
}
}
} else if (isInterface) {
reportWarning(
TypeCheck.CONFLICTING_IMPLEMENTED_TYPE, formatFnName());
} else {
reportWarning(CONSTRUCTOR_REQUIRED, "@implements", formatFnName());
}
}
// extended interfaces (for interfaces only)
// We've already emitted a warning if this is not an interface.
if (isInterface) {
extendedInterfaces = Lists.newArrayList();
for (JSTypeExpression t : info.getExtendedInterfaces()) {
JSType maybeInterfaceType = t.evaluate(scope, typeRegistry);
if (maybeInterfaceType != null &&
maybeInterfaceType.setValidator(new ExtendedTypeValidator())) {
extendedInterfaces.add((ObjectType) maybeInterfaceType);
}
}
}
}