writeHostApi method
void
writeHostApi(
- KotlinOptions generatorOptions,
- Root root,
- Indent indent,
- Api api, {
- required String dartPackageName,
override
Write the kotlin code that represents a host Api, api
.
Example:
interface Foo {
Int add(x: Int, y: Int);
companion object {
fun setUp(binaryMessenger: BinaryMessenger, api: Api) {...}
}
}
Implementation
@override
void writeHostApi(
KotlinOptions generatorOptions,
Root root,
Indent indent,
Api api, {
required String dartPackageName,
}) {
assert(api.location == ApiLocation.host);
final String apiName = api.name;
final bool isCustomCodec = getCodecClasses(api, root).isNotEmpty;
if (isCustomCodec) {
_writeCodec(indent, api, root);
}
const List<String> generatedMessages = <String>[
' Generated interface from Pigeon that represents a handler of messages from Flutter.'
];
addDocumentationComments(indent, api.documentationComments, _docCommentSpec,
generatorComments: generatedMessages);
indent.write('interface $apiName ');
indent.addScoped('{', '}', () {
for (final Method method in api.methods) {
final List<String> argSignature = <String>[];
if (method.arguments.isNotEmpty) {
final Iterable<String> argTypes = method.arguments
.map((NamedType e) => _nullsafeKotlinTypeForDartType(e.type));
final Iterable<String> argNames =
method.arguments.map((NamedType e) => e.name);
argSignature.addAll(
map2(argTypes, argNames, (String argType, String argName) {
return '$argName: $argType';
}));
}
final String returnType = method.returnType.isVoid
? ''
: _nullsafeKotlinTypeForDartType(method.returnType);
final String resultType =
method.returnType.isVoid ? 'Unit' : returnType;
addDocumentationComments(
indent, method.documentationComments, _docCommentSpec);
if (method.isAsynchronous) {
argSignature.add('callback: (Result<$resultType>) -> Unit');
indent.writeln('fun ${method.name}(${argSignature.join(', ')})');
} else if (method.returnType.isVoid) {
indent.writeln('fun ${method.name}(${argSignature.join(', ')})');
} else {
indent.writeln(
'fun ${method.name}(${argSignature.join(', ')}): $returnType');
}
}
indent.newln();
indent.write('companion object ');
indent.addScoped('{', '}', () {
indent.writeln('/** The codec used by $apiName. */');
indent.write('val codec: MessageCodec<Any?> by lazy ');
indent.addScoped('{', '}', () {
if (isCustomCodec) {
indent.writeln(_getCodecName(api));
} else {
indent.writeln('StandardMessageCodec()');
}
});
indent.writeln(
'/** Sets up an instance of `$apiName` to handle messages through the `binaryMessenger`. */');
indent.writeln('@Suppress("UNCHECKED_CAST")');
indent.write(
'fun setUp(binaryMessenger: BinaryMessenger, api: $apiName?) ');
indent.addScoped('{', '}', () {
for (final Method method in api.methods) {
indent.write('run ');
indent.addScoped('{', '}', () {
String? taskQueue;
if (method.taskQueueType != TaskQueueType.serial) {
taskQueue = 'taskQueue';
indent.writeln(
'val $taskQueue = binaryMessenger.makeBackgroundTaskQueue()');
}
final String channelName =
makeChannelName(api, method, dartPackageName);
indent.write(
'val channel = BasicMessageChannel<Any?>(binaryMessenger, "$channelName", codec');
if (taskQueue != null) {
indent.addln(', $taskQueue)');
} else {
indent.addln(')');
}
indent.write('if (api != null) ');
indent.addScoped('{', '}', () {
final String messageVarName =
method.arguments.isNotEmpty ? 'message' : '_';
indent.write('channel.setMessageHandler ');
indent.addScoped('{ $messageVarName, reply ->', '}', () {
final List<String> methodArguments = <String>[];
if (method.arguments.isNotEmpty) {
indent.writeln('val args = message as List<Any?>');
enumerate(method.arguments, (int index, NamedType arg) {
final String argName = _getSafeArgumentName(index, arg);
final String argIndex = 'args[$index]';
indent.writeln(
'val $argName = ${_castForceUnwrap(argIndex, arg.type, root)}');
methodArguments.add(argName);
});
}
final String call =
'api.${method.name}(${methodArguments.join(', ')})';
if (method.isAsynchronous) {
indent.write('$call ');
final String resultType = method.returnType.isVoid
? 'Unit'
: _nullsafeKotlinTypeForDartType(method.returnType);
indent.addScoped('{ result: Result<$resultType> ->', '}',
() {
indent.writeln('val error = result.exceptionOrNull()');
indent.writeScoped('if (error != null) {', '}', () {
indent.writeln('reply.reply(wrapError(error))');
}, addTrailingNewline: false);
indent.addScoped(' else {', '}', () {
if (method.returnType.isVoid) {
indent.writeln('reply.reply(wrapResult(null))');
} else {
indent.writeln('val data = result.getOrNull()');
indent.writeln('reply.reply(wrapResult(data))');
}
});
});
} else {
indent.writeln('var wrapped: List<Any?>');
indent.write('try ');
indent.addScoped('{', '}', () {
if (method.returnType.isVoid) {
indent.writeln(call);
indent.writeln('wrapped = listOf<Any?>(null)');
} else {
indent.writeln('wrapped = listOf<Any?>($call)');
}
}, addTrailingNewline: false);
indent.add(' catch (exception: Throwable) ');
indent.addScoped('{', '}', () {
indent.writeln('wrapped = wrapError(exception)');
});
indent.writeln('reply.reply(wrapped)');
}
});
}, addTrailingNewline: false);
indent.addScoped(' else {', '}', () {
indent.writeln('channel.setMessageHandler(null)');
});
});
}
});
});
});
}