* @param t The node traversal object that supplies context, such as the
* scope chain to use in name lookups as well as error reporting.
* @param n The node being visited.
*/
private void visitFunction(NodeTraversal t, Node n) {
FunctionType functionType = JSType.toMaybeFunctionType(n.getJSType());
String functionPrivateName = n.getFirstChild().getString();
if (functionType.isConstructor()) {
FunctionType baseConstructor = functionType.getSuperClassConstructor();
if (baseConstructor != getNativeType(OBJECT_FUNCTION_TYPE) &&
baseConstructor != null &&
baseConstructor.isInterface()) {
compiler.report(
t.makeError(n, CONFLICTING_EXTENDED_TYPE,
"constructor", functionPrivateName));
} else {
if (baseConstructor != getNativeType(OBJECT_FUNCTION_TYPE)) {
ObjectType proto = functionType.getPrototype();
if (functionType.makesStructs() && !proto.isStruct()) {
compiler.report(t.makeError(n, CONFLICTING_SHAPE_TYPE,
"struct", functionPrivateName));
} else if (functionType.makesDicts() && !proto.isDict()) {
compiler.report(t.makeError(n, CONFLICTING_SHAPE_TYPE,
"dict", functionPrivateName));
}
}
// All interfaces are properly implemented by a class
for (JSType baseInterface : functionType.getImplementedInterfaces()) {
boolean badImplementedType = false;
ObjectType baseInterfaceObj = ObjectType.cast(baseInterface);
if (baseInterfaceObj != null) {
FunctionType interfaceConstructor =
baseInterfaceObj.getConstructor();
if (interfaceConstructor != null &&
!interfaceConstructor.isInterface()) {
badImplementedType = true;
}
} else {
badImplementedType = true;
}