in src/pluggable-objc-file-creation.ts [371:626]
function classFileCreationFunctionWithBaseClassAndPlugins<T>(
baseClassName: string,
baseClassLibraryName: string | null,
diagnosticIgnores: List.List<string>,
pathToValueFile: File.AbsoluteFilePath,
plugins: List.List<ObjCGenerationPlugIn<T>>,
typeProvider: ObjCGenerationTypeInfoProvider<T>,
): (
typeInformation: T,
typeName: string,
comments: string[],
file?: Code.File,
) => Either.Either<Error.Error, Code.File> {
return function (
typeInformation: T,
typeName: string,
comments: string[],
file?: Code.File,
): Either.Either<Error.Error, Code.File> {
const fileType = List.foldl<
ObjCGenerationPlugIn<T>,
Either.Either<Error.Error, Code.FileType | null>
>(
(soFar, plugin) => buildFileType(typeInformation, soFar, plugin),
Either.Right<Error.Error, Code.FileType | null>(null),
plugins,
);
const nullabilityEither = List.foldl<
ObjCGenerationPlugIn<T>,
Either.Either<Error.Error, ObjC.ClassNullability | null>
>(
(soFar, plugin) => buildNullability(typeInformation, soFar, plugin),
Either.Right<Error.Error, ObjC.ClassNullability | null>(null),
plugins,
);
const nullability = Either.match(
function () {
return ObjC.ClassNullability.default;
},
function (maybeNullability: ObjC.ClassNullability | null) {
return Maybe.match(
function (nullability: ObjC.ClassNullability) {
return nullability;
},
function () {
return ObjC.ClassNullability.default;
},
maybeNullability,
);
},
nullabilityEither,
);
const visibility = typeProvider.visibilityForType(typeInformation);
const customPluginBaseClass: Either.Either<
Error.Error,
ObjC.BaseClass | null
> = List.foldl(
(currentEither, nextPlugin) => {
return Either.mbind((maybeCurrentBaseClass) => {
const maybeNextBaseClass = nextPlugin.baseClass(typeInformation);
return Maybe.match(
// If we have two conflicting base classes from different plugins,
// we need to fail as there's no way to choose a class to generate.
([currentBaseClass, nextBaseClass]) =>
Either.Left(
Error.Error(
`Conflicting base classes ${currentBaseClass.className} and ${nextBaseClass.className}`,
),
),
// If we only have one of the two, then we can continue with
// whichever one happens to be present.
() =>
Either.Right(Maybe.or(maybeNextBaseClass, maybeCurrentBaseClass)),
Maybe.and(maybeCurrentBaseClass, maybeNextBaseClass),
);
}, currentEither);
},
// We start with Nothing rather than with the configuration-specified base
// class so that we don't always produce an error.
Either.Right(null as ObjC.BaseClass | null),
plugins,
);
// Allow the plugin-specified base class to override the one that was
// specified in the configuration file.
const baseClass: Either.Either<Error.Error, ObjC.BaseClass> = Either.map(
(maybeCustom) =>
Maybe.match(
(custom) => custom,
() => ({className: baseClassName, libraryName: baseClassLibraryName}),
maybeCustom,
),
customPluginBaseClass,
);
return Either.map(([maybeFileType, baseClass]) => {
const fileType = Maybe.match(
function (fileType: Code.FileType) {
return fileType;
},
function () {
return Code.FileType.ObjectiveC;
},
maybeFileType,
);
const functions = List.foldl<ObjCGenerationPlugIn<T>, ObjC.Function[]>(
(soFar, plugin) => buildFunctions(typeInformation, soFar, plugin),
[],
plugins,
);
const classes = createClassesForObjectSpecType<T>(
typeInformation,
typeName,
comments,
baseClass.className,
functions,
plugins,
nullability,
visibility,
);
const imports = importListWithBaseImportAppended(
baseClass.className,
baseClass.libraryName,
List.foldl<ObjCGenerationPlugIn<T>, ObjC.Import[]>(
(soFar, plugin) => buildImports(typeInformation, soFar, plugin),
[],
plugins,
),
);
const enumerations = List.foldl<
ObjCGenerationPlugIn<T>,
ObjC.Enumeration[]
>(
(soFar, plugin) => buildEnumerations(typeInformation, soFar, plugin),
[],
plugins,
);
const forwardDeclarations = List.foldl<
ObjCGenerationPlugIn<T>,
ObjC.ForwardDeclaration[]
>(
(soFar, plugin) =>
buildForwardDeclarations(typeInformation, soFar, plugin),
[],
plugins,
);
const blockTypes = List.foldl<ObjCGenerationPlugIn<T>, ObjC.BlockType[]>(
(soFar, plugin) => buildBlockTypes(typeInformation, soFar, plugin),
[],
plugins,
);
const staticConstants = List.foldl<
ObjCGenerationPlugIn<T>,
ObjC.Constant[]
>(
(soFar, plugin) => buildStaticConstants(typeInformation, soFar, plugin),
[],
plugins,
);
const globalVariables = List.foldl<
ObjCGenerationPlugIn<T>,
ObjC.GlobalVariable[]
>(
(soFar, plugin) => buildglobalVariables(typeInformation, soFar, plugin),
[],
plugins,
);
const macros = List.foldl<ObjCGenerationPlugIn<T>, ObjC.Macro[]>(
(soFar, plugin) => buildMacros(typeInformation, soFar, plugin),
[],
plugins,
);
const protocols = List.foldl<ObjCGenerationPlugIn<T>, ObjC.Protocol[]>(
(soFar, plugin) => buildProtocols(typeInformation, soFar, plugin),
[],
plugins,
);
const structs = List.foldl<ObjCGenerationPlugIn<T>, Code.Struct[]>(
(soFar, plugin) => buildStructs(typeInformation, soFar, plugin),
[],
plugins,
);
const finalFunctions = classes.length > 0 ? [] : functions;
if (file != null) {
var newFile = file;
newFile.imports = file.imports.concat(
List.foldl<ObjCGenerationPlugIn<T>, ObjC.Import[]>(
(soFar, plugin) => buildImports(typeInformation, soFar, plugin),
[],
plugins,
),
);
newFile.enumerations = file.enumerations.concat(enumerations);
newFile.forwardDeclarations =
file.forwardDeclarations.concat(forwardDeclarations);
newFile.blockTypes = file.blockTypes.concat(blockTypes);
newFile.diagnosticIgnores = file.diagnosticIgnores.concat(
List.toArray(diagnosticIgnores),
);
newFile.staticConstants = file.staticConstants.concat(staticConstants);
newFile.globalVariables = file.globalVariables.concat(globalVariables);
newFile.functions = file.functions.concat(finalFunctions);
newFile.macros = file.macros.concat(macros);
newFile.classes = file.classes.concat(classes);
newFile.structs = file.structs.concat(structs);
newFile.cppClasses = file.cppClasses;
return newFile;
} else {
return {
name: typeName,
type: fileType,
imports: imports,
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));
};
}