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) {