comments: commentListWithPathToValueFile()

in src/pluggable-objc-file-creation.ts [600:890]


          comments: commentListWithPathToValueFile(
            pathToValueFile,
            List.foldl<ObjCGenerationPlugIn<T>, ObjC.Comment[]>(
              (soFar, plugin) => buildComments(typeInformation, soFar, plugin),
              [],
              plugins,
            ),
          ),
          enumerations: enumerations,
          forwardDeclarations: forwardDeclarations,
          blockTypes: blockTypes,
          diagnosticIgnores: List.toArray(diagnosticIgnores),
          staticConstants: staticConstants,
          globalVariables: globalVariables,
          functions: finalFunctions,
          nullability: classes.length > 0 ? undefined : nullability,
          macros: macros,
          protocols: protocols,
          classes: classes,
          structs: structs,
          cppClasses: [],
          namespaces: [],
        };
      }
    }, Either.and(fileType, baseClass));
  };
}

function createClassesForObjectSpecType<T>(
  typeInformation: T,
  typeName: string,
  comments: string[],
  baseClassName: string,
  functions: ObjC.Function[],
  plugins: List.List<ObjCGenerationPlugIn<T>>,
  nullability: ObjC.ClassNullability,
  visibility: ObjC.ClassVisibility | undefined,
): ObjC.Class[] {
  const classMethods = List.foldl<ObjCGenerationPlugIn<T>, ObjC.Method[]>(
    (soFar, plugin) => buildClassMethods(typeInformation, soFar, plugin),
    [],
    plugins,
  ).sort(sortInstanceMethodComparitor);

  const instanceMethods = List.foldl<ObjCGenerationPlugIn<T>, ObjC.Method[]>(
    (soFar, plugin) => buildInstanceMethods(typeInformation, soFar, plugin),
    [],
    plugins,
  ).sort(sortInstanceMethodComparitor);

  const properties = List.foldl<ObjCGenerationPlugIn<T>, ObjC.Property[]>(
    (soFar, plugin) => buildProperties(typeInformation, soFar, plugin),
    [],
    plugins,
  );

  const instanceVariables = List.foldl<
    ObjCGenerationPlugIn<T>,
    ObjC.InstanceVariable[]
  >(
    (soFar, plugin) => buildInstanceVariables(typeInformation, soFar, plugin),
    [],
    plugins,
  );

  const implementedProtocols = List.foldr<
    ObjCGenerationPlugIn<T>,
    ObjC.ImplementedProtocol[]
  >(
    (soFar, plugin) =>
      buildImplementedProtocols(typeInformation, soFar, plugin),
    [],
    plugins,
  );

  const classDefintionMaybe = createClassIfNecessary(
    classMethods,
    instanceMethods,
    properties,
    instanceVariables,
    functions,
    implementedProtocols,
    comments,
    typeName,
    baseClassName,
    nullability,
    List.foldr<ObjCGenerationPlugIn<T>, boolean>(
      (soFar, plugin) =>
        checkSubclassingRestricted(typeInformation, soFar, plugin),
      false,
      plugins,
    ),
    visibility,
  );

  return Maybe.match(
    function (classInfo) {
      return [classInfo];
    },
    function () {
      return [];
    },
    classDefintionMaybe,
  );
}

function createClassIfNecessary(
  classMethods: ObjC.Method[],
  instanceMethods: ObjC.Method[],
  properties: ObjC.Property[],
  instanceVariables: ObjC.InstanceVariable[],
  functions: ObjC.Function[],
  implementedProtocols: ObjC.ImplementedProtocol[],
  comments: string[],
  typeName: string,
  baseClassName: string,
  nullability: ObjC.ClassNullability,
  subclassingRestricted: boolean,
  visibility: ObjC.ClassVisibility | undefined,
): ObjC.Class | null {
  if (
    classMethods.length > 0 ||
    instanceMethods.length > 0 ||
    properties.length > 0 ||
    instanceVariables.length > 0 ||
    implementedProtocols.length > 0 ||
    subclassingRestricted
  ) {
    return {
      baseClassName: baseClassName,
      covariantTypes: [],
      comments: ObjCCommentUtils.commentsAsBlockFromStringArray(comments),
      classMethods: classMethods,
      functions: functions,
      inlineBlockTypedefs: [],
      instanceMethods: instanceMethods,
      name: typeName,
      properties: properties,
      instanceVariables: instanceVariables,
      implementedProtocols: implementedProtocols,
      nullability: nullability,
      subclassingRestricted: subclassingRestricted,
      visibility: visibility,
    };
  }

  return null;
}

function fileCreationRequestContainingArrayOfPossibleError(
  fileCreationRequest: Either.Either<Error.Error, FileWriter.FileWriteRequest>,
): Either.Either<Error.Error[], FileWriter.FileWriteRequest> {
  return Either.match(
    function (
      error: Error.Error,
    ): Either.Either<Error.Error[], FileWriter.FileWriteRequest> {
      return Either.Left([error]);
    },
    function (
      fileWriteRequest: FileWriter.FileWriteRequest,
    ): Either.Either<Error.Error[], FileWriter.FileWriteRequest> {
      return Either.Right(fileWriteRequest);
    },
    fileCreationRequest,
  );
}

function fileWriteRequestContainingAdditionalFile(
  outputFlags: OutputControl.OutputFlags,
  containingFolderPath: File.AbsoluteFilePath,
  file: Code.File,
  fileWriteRequest: FileWriter.FileWriteRequest,
): Either.Either<Error.Error, FileWriter.FileWriteRequest> {
  const fileCreationRequestForAdditionalFile: Either.Either<
    Error.Error,
    FileWriter.FileWriteRequest
  > = ObjCFileCreation.fileCreationRequest(
    containingFolderPath,
    file,
    outputFlags.emitHeaders,
    outputFlags.emitImplementations,
  );

  return Either.map(function (
    fileWriteRequestForAdditionalFile: FileWriter.FileWriteRequest,
  ): FileWriter.FileWriteRequest {
    const updatedRequest: FileWriter.FileWriteRequest = {
      name: fileWriteRequest.name,
      requests: List.append(
        fileWriteRequest.requests,
        fileWriteRequestForAdditionalFile.requests,
      ),
    };
    return updatedRequest;
  },
  fileCreationRequestForAdditionalFile);
}

function fileCreationRequestContainingAdditionalFile(
  renderOptions: OutputControl.OutputFlags,
  containingFolderPath: File.AbsoluteFilePath,
  fileCreationRequest: Either.Either<Error.Error, FileWriter.FileWriteRequest>,
  file: Code.File,
): Either.Either<Error.Error, FileWriter.FileWriteRequest> {
  return Either.mbind((fileWriteRequest: FileWriter.FileWriteRequest) => {
    return fileWriteRequestContainingAdditionalFile(
      renderOptions,
      containingFolderPath,
      file,
      fileWriteRequest,
    );
  }, fileCreationRequest);
}

function transformFileWithPlugins<T>(
  baseFile: Code.File,
  typeInformation: T,
  plugins: List.List<ObjCGenerationPlugIn<T>>,
): Code.File {
  return List.foldl<ObjCGenerationPlugIn<T>, Code.File>(
    (soFar, plugin) => plugin.transformBaseFile(typeInformation, soFar),
    baseFile,
    plugins,
  );
}

function buildFileWriteRequest<T>(
  request: ObjCGenerationRequest<T>,
  typeInfoProvider: ObjCGenerationTypeInfoProvider<T>,
  plugins: List.List<ObjCGenerationPlugIn<T>>,
): Either.Either<Error.Error[], FileWriter.FileWriteRequest> {
  const classFileFromTypeInfo: (
    typeInformation: T,
    typeName: string,
    comments: string[],
    file?: Code.File,
  ) => Either.Either<Error.Error, Code.File> =
    classFileCreationFunctionWithBaseClassAndPlugins(
      request.baseClassName,
      request.baseClassLibraryName,
      request.diagnosticIgnores,
      request.path,
      plugins,
      typeInfoProvider,
    );

  const outputPath: File.AbsoluteFilePath = Maybe.match(
    function (file: File.AbsoluteFilePath): File.AbsoluteFilePath {
      return file;
    },
    function (): File.AbsoluteFilePath {
      const fullPathAsString: string = File.getAbsolutePathString(request.path);
      return File.getAbsoluteFilePath(path.dirname(fullPathAsString));
    },
    request.outputPath,
  );

  // filter down to the plugins that we want to emit if we are filtered
  const filteredPlugins = List.filter(function (p) {
    return OutputControl.ShouldEmitPluginFile(
      request.outputFlags,
      p.requiredIncludesToRun[0],
    );
  }, plugins);

  // In single-file output mode, everything goes into the same file, and
  // we don't listen to any of the output control flags for not outputting
  // the base file.
  if (request.outputFlags.singleFile) {
    const baseFileOrError = classFileFromTypeInfo(
      request.typeInformation,
      typeInfoProvider.typeNameForType(request.typeInformation),
      typeInfoProvider.commentsForType(request.typeInformation),
    )
      .map(function (file: Code.File) {
        return transformFileWithPlugins(
          file,
          request.typeInformation,
          filteredPlugins,
        );
      })
      .mbind(function (file: Code.File) {
        // gather additional type files, then merge them into our base file
        const extraTypes = typeInfoProvider.additionalTypesForType(
          request.typeInformation,
        );
        return extraTypes.reduce(function (
          prev: Either.Either<Error.Error, Code.File>,
          type: T,
        ) {
          return prev.mbind(function (prevFile: Code.File) {