in src/pluggable-objc-file-creation.ts [826:1029]
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) {
return classFileFromTypeInfo(
type,
typeInfoProvider.typeNameForType(type),
typeInfoProvider.commentsForType(type),
prevFile,
)
.map(function (file: Code.File) {
return transformFileWithPlugins(file, type, filteredPlugins);
})
.map(function (file: Code.File) {
// plugins can add headers we don't want, as it's tough to know whether you
// are the main type, or an additional type when generating the file, so for
// now I am just going to filter the headers out.
var newFile = file;
newFile.imports = file.imports.filter(function (
value: ObjC.Import,
) {
return (
value.file != typeInfoProvider.typeNameForType(type) + '.h'
);
});
newFile.forwardDeclarations = file.forwardDeclarations.concat([
ObjC.ForwardDeclaration.ForwardClassDeclaration(
typeInfoProvider.typeNameForType(type),
),
]);
return newFile;
});
});
},
Either.Right<Error.Error, Code.File>(file));
});
const fileWriteRequestOrError: Either.Either<
Error.Error,
FileWriter.FileWriteRequest
> = Either.mbind(function (file: Code.File) {
const emptyRequest = Either.Right<
Error.Error,
FileWriter.FileWriteRequest
>({
name: typeInfoProvider.typeNameForType(request.typeInformation),
requests: List.of<FileWriter.Request>(),
});
const result = fileCreationRequestContainingAdditionalFile(
request.outputFlags,
outputPath,
emptyRequest,
file,
);
return result;
}, baseFileOrError);
return fileCreationRequestContainingArrayOfPossibleError(
fileWriteRequestOrError,
);
} else {
const typeInfos = [request.typeInformation].concat(
typeInfoProvider.additionalTypesForType(request.typeInformation),
);
// each type info will manifest as its own file, regardless of whether
// the single-file output flag is set.
const allFileRequests = typeInfos.map(function (type: T) {
// build base file if we are allowed to
const classFile: Either.Either<Error.Error, Code.File[]> =
OutputControl.ShouldEmitObject(request.outputFlags)
? classFileFromTypeInfo(
type,
typeInfoProvider.typeNameForType(type),
typeInfoProvider.commentsForType(type),
).map(function (file: Code.File) {
return [file];
})
: Either.Right<Error.Error, Code.File[]>([]);
// add files from plugins, or merge them into our base file
// We'll end up with an array of files. If single file is set,
// we will only have one entry in the array.
const filesToWrite: Either.Either<Error.Error, Code.File[]> =
classFile.map(function (files: Code.File[]) {
const additionalFiles: Code.File[] = List.foldl<
ObjCGenerationPlugIn<T>,
Code.File[]
>(
(soFar, plugin) => buildAdditionalFiles(type, soFar, plugin),
[],
filteredPlugins,
);
return files.concat(additionalFiles);
});
// create file write requests for each file
const completeFileCreationRequest: Either.Either<
Error.Error,
FileWriter.FileWriteRequest
> = Either.mbind(function (files: Code.File[]) {
return files.reduce(
function (
soFar: Either.Either<Error.Error, FileWriter.FileWriteRequest>,
currentFile: Code.File,
) {
return fileCreationRequestContainingAdditionalFile(
request.outputFlags,
outputPath,
soFar,
currentFile,
);
},
Either.Right<Error.Error, FileWriter.FileWriteRequest>({
name: typeInfoProvider.typeNameForType(type),
requests: List.of<FileWriter.Request>(),
}),
);
}, filesToWrite);
return fileCreationRequestContainingArrayOfPossibleError(
completeFileCreationRequest,
);
});
// Unify all write requests
return allFileRequests.reduce(function (
soFar: Either.Either<Error.Error[], FileWriter.FileWriteRequest>,
current: Either.Either<Error.Error[], FileWriter.FileWriteRequest>,
) {
return Either.map(function (
request: FileWriter.FileWriteRequest,
): FileWriter.FileWriteRequest {
return {
name: request.name,
requests: List.append(request.requests, current.right!.requests),
};
},
soFar);
});
}
}