private void handleConstructorAnnotation(
     String functionName,
     Node funNode,
     RawNominalType constructorType,
     NominalType parentClass,
     ImmutableSet<NominalType> implementedIntfs,
     DeclaredTypeRegistry registry,
     FunctionTypeBuilder builder) {
   String className = constructorType.toString();
   NominalType builtinObject = registry.getCommonTypes().getObjectType();
   if (parentClass == null && !functionName.equals("Object")) {
     parentClass = builtinObject;
   }
   if (parentClass != null) {
     if (!constructorType.addSuperClass(parentClass)) {
       warnings.add(JSError.make(funNode, INHERITANCE_CYCLE, className));
     } else if (parentClass != builtinObject) {
       if (constructorType.isStruct() && !parentClass.isStruct()) {
         warnings.add(JSError.make(funNode, CONFLICTING_SHAPE_TYPE, "struct", className));
       } else if (constructorType.isDict() && !parentClass.isDict()) {
         warnings.add(JSError.make(funNode, CONFLICTING_SHAPE_TYPE, "dict", className));
       }
     }
   }
   if (constructorType.isDict() && !implementedIntfs.isEmpty()) {
     warnings.add(JSError.make(funNode, DICT_IMPLEMENTS_INTERF, className));
   }
   boolean noCycles = constructorType.addInterfaces(implementedIntfs);
   Preconditions.checkState(noCycles);
   builder.addNominalType(constructorType.getInstanceAsJSType());
 }
 private JSType lookupTypeByName(
     String name, Node n, DeclaredTypeRegistry registry, ImmutableList<String> outerTypeParameters)
     throws UnknownTypeException {
   String tvar = UniqueNameGenerator.findGeneratedName(name, outerTypeParameters);
   if (tvar != null) {
     return JSType.fromTypeVar(tvar);
   }
   Declaration decl = registry.getDeclaration(QualifiedName.fromQualifiedString(name), true);
   if (decl == null) {
     unknownTypeNames.put(n, name);
     throw new UnknownTypeException("Unhandled type: " + name);
   }
   // It's either a typedef, an enum, a type variable or a nominal type
   if (decl.getTypedef() != null) {
     return getTypedefType(decl.getTypedef(), registry);
   }
   if (decl.getEnum() != null) {
     return getEnumPropType(decl.getEnum(), registry);
   }
   if (decl.isTypeVar()) {
     howmanyTypeVars++;
     return decl.getTypeOfSimpleDecl();
   }
   if (decl.getNominal() != null) {
     return getNominalTypeHelper(decl.getNominal(), n, registry, outerTypeParameters);
   }
   return JSType.UNKNOWN;
 }
 // Computes a type from a jsdoc that includes a function type, rather than
 // one that includes @param, @return, etc.
 private JSType getFunTypeHelper(
     Node jsdocNode, DeclaredTypeRegistry registry, ImmutableList<String> typeParameters)
     throws UnknownTypeException {
   FunctionTypeBuilder builder = new FunctionTypeBuilder();
   fillInFunTypeBuilder(jsdocNode, null, registry, typeParameters, builder);
   return registry.getCommonTypes().fromFunctionType(builder.buildFunction());
 }
 private JSType getNamedTypeHelper(
     Node n, DeclaredTypeRegistry registry, ImmutableList<String> outerTypeParameters)
     throws UnknownTypeException {
   String typeName = n.getString();
   switch (typeName) {
     case "boolean":
       return JSType.BOOLEAN;
     case "null":
       return JSType.NULL;
     case "number":
       return JSType.NUMBER;
     case "string":
       return JSType.STRING;
     case "undefined":
     case "void":
       return JSType.UNDEFINED;
     case "Function":
       return maybeMakeNullable(registry.getCommonTypes().qmarkFunction());
     case "Object":
       // We don't generally handle parameterized Object<...>, but we want to
       // at least not warn about inexistent properties on it, so we type it
       // as @dict.
       return maybeMakeNullable(n.hasChildren() ? JSType.TOP_DICT : JSType.TOP_OBJECT);
     default:
       return lookupTypeByName(typeName, n, registry, outerTypeParameters);
   }
 }
 private void handleInterfaceAnnotation(
     JSDocInfo jsdoc,
     String functionName,
     Node funNode,
     RawNominalType constructorType,
     ImmutableSet<NominalType> implementedIntfs,
     ImmutableList<String> typeParameters,
     DeclaredTypeRegistry registry,
     FunctionTypeBuilder builder) {
   if (!implementedIntfs.isEmpty()) {
     warnings.add(JSError.make(funNode, CONFLICTING_IMPLEMENTED_TYPE, functionName));
   }
   ImmutableSet<NominalType> extendedInterfaces =
       getExtendedInterfaces(jsdoc, registry, typeParameters);
   boolean noCycles =
       constructorType.addInterfaces(
           extendedInterfaces.isEmpty()
               ? ImmutableSet.of(registry.getCommonTypes().getObjectType())
               : extendedInterfaces);
   if (!noCycles) {
     warnings.add(JSError.make(funNode, INHERITANCE_CYCLE, constructorType.toString()));
   }
   builder.addNominalType(constructorType.getInstanceAsJSType());
 }