Пример #1
0
  /**
   * Returns a constructor function either by returning it from the registry if it exists or
   * creating and registering a new type. If there is already a type, then warn if the existing type
   * is different than the one we are creating, though still return the existing function if
   * possible. The primary purpose of this is that registering a constructor will fail for all
   * built-in types that are initialized in {@link JSTypeRegistry}. We a) want to make sure that the
   * type information specified in the externs file matches what is in the registry and b) annotate
   * the externs with the {@link JSType} from the registry so that there are not two separate JSType
   * objects for one type.
   */
  private FunctionType getOrCreateConstructor() {
    FunctionType fnType =
        typeRegistry.createConstructorType(fnName, sourceNode, parametersNode, returnType);
    JSType existingType = typeRegistry.getType(fnName);

    if (existingType != null) {
      boolean isInstanceObject = existingType instanceof InstanceObjectType;
      if (isInstanceObject || fnName.equals("Function")) {
        FunctionType existingFn =
            isInstanceObject
                ? ((InstanceObjectType) existingType).getConstructor()
                : typeRegistry.getNativeFunctionType(FUNCTION_FUNCTION_TYPE);

        if (existingFn.getSource() == null) {
          existingFn.setSource(sourceNode);
        }

        if (!existingFn.hasEqualCallType(fnType)) {
          reportWarning(TYPE_REDEFINITION, fnName, fnType.toString(), existingFn.toString());
        }

        return existingFn;
      } else {
        // We fall through and return the created type, even though it will fail
        // to register. We have no choice as we have to return a function. We
        // issue an error elsewhere though, so the user should fix it.
      }
    }

    maybeSetBaseType(fnType);

    if (getScopeDeclaredIn().isGlobal() && !fnName.isEmpty()) {
      typeRegistry.declareType(fnName, fnType.getInstanceType());
    }
    return fnType;
  }