in packages/pigeon/lib/objc_generator.dart [789:927]
void generateObjcSource(ObjcOptions options, Root root, StringSink sink) {
final Indent indent = Indent(sink);
final List<String> classNames =
root.classes.map((Class x) => x.name).toList();
final List<String> enumNames = root.enums.map((Enum x) => x.name).toList();
void writeHeader() {
if (options.copyrightHeader != null) {
addLines(indent, options.copyrightHeader!, linePrefix: '// ');
}
indent.writeln('// $generatedCodeWarning');
indent.writeln('// $seeAlsoWarning');
}
void writeImports() {
indent.writeln('#import "${options.header}"');
indent.writeln('#import <Flutter/Flutter.h>');
}
void writeArcEnforcer() {
indent.writeln('#if !__has_feature(objc_arc)');
indent.writeln('#error File requires ARC to be enabled.');
indent.writeln('#endif');
}
void writeWrapResultFunction() {
indent.format('''
static NSDictionary<NSString *, id> *wrapResult(id result, FlutterError *error) {
\tNSDictionary *errorDict = (NSDictionary *)[NSNull null];
\tif (error) {
\t\terrorDict = @{
\t\t\t\t@"${Keys.errorCode}": (error.code ? error.code : [NSNull null]),
\t\t\t\t@"${Keys.errorMessage}": (error.message ? error.message : [NSNull null]),
\t\t\t\t@"${Keys.errorDetails}": (error.details ? error.details : [NSNull null]),
\t\t\t\t};
\t}
\treturn @{
\t\t\t@"${Keys.result}": (result ? result : [NSNull null]),
\t\t\t@"${Keys.error}": errorDict,
\t\t\t};
}''');
}
void writeDataClassExtension(Class klass) {
final String className = _className(options.prefix, klass.name);
indent.writeln('@interface $className ()');
indent.writeln('+ ($className *)fromMap:(NSDictionary *)dict;');
indent.writeln('- (NSDictionary *)toMap;');
indent.writeln('@end');
}
void writeDataClassImplementation(Class klass) {
final String className = _className(options.prefix, klass.name);
void writeInitializer() {
_writeInitializerDeclaration(
indent, klass, root.classes, root.enums, options.prefix);
indent.writeScoped(' {', '}', () {
const String result = 'pigeonResult';
indent.writeln('$className* $result = [[$className alloc] init];');
for (final NamedType field in klass.fields) {
indent.writeln('$result.${field.name} = ${field.name};');
}
indent.writeln('return $result;');
});
}
void writeFromMap() {
indent.write('+ ($className *)fromMap:(NSDictionary *)dict ');
indent.scoped('{', '}', () {
const String resultName = 'pigeonResult';
indent.writeln('$className *$resultName = [[$className alloc] init];');
for (final NamedType field in klass.fields) {
if (enumNames.contains(field.type.baseName)) {
indent.writeln(
'$resultName.${field.name} = [${_dictGetter(classNames, 'dict', field, options.prefix)} integerValue];');
} else {
indent.writeln(
'$resultName.${field.name} = ${_dictGetter(classNames, 'dict', field, options.prefix)};');
if (field.type.isNullable) {
indent.write(
'if ((NSNull *)$resultName.${field.name} == [NSNull null]) ');
indent.scoped('{', '}', () {
indent.writeln('$resultName.${field.name} = nil;');
});
} else {
indent.writeln(
'NSAssert((NSNull *)$resultName.${field.name} != [NSNull null], @"");');
}
}
}
indent.writeln('return $resultName;');
});
}
void writeToMap() {
indent.write('- (NSDictionary *)toMap ');
indent.scoped('{', '}', () {
indent.write('return [NSDictionary dictionaryWithObjectsAndKeys:');
for (final NamedType field in klass.fields) {
indent.add(_dictValue(classNames, enumNames, field) +
', @"${field.name}", ');
}
indent.addln('nil];');
});
}
indent.writeln('@implementation $className');
writeInitializer();
writeFromMap();
writeToMap();
indent.writeln('@end');
}
void writeApi(Api api) {
final String codecName = _getCodecName(options.prefix, api.name);
_writeCodec(indent, codecName, options, api, root);
indent.addln('');
if (api.location == ApiLocation.host) {
_writeHostApiSource(indent, options, api);
} else if (api.location == ApiLocation.flutter) {
_writeFlutterApiSource(indent, options, api);
}
}
writeHeader();
writeImports();
indent.writeln('');
writeArcEnforcer();
indent.addln('');
writeWrapResultFunction();
indent.addln('');
root.classes.forEach(writeDataClassExtension);
indent.writeln('');
for (final Class klass in root.classes) {
writeDataClassImplementation(klass);
indent.writeln('');
}
root.apis.forEach(writeApi);
}