writeFlutterApi method
void
writeFlutterApi(
- DartOptions generatorOptions,
- Root root,
- Indent indent,
- Api api, {
- String channelNameFunc()?,
- bool isMockHandler = false,
- required String dartPackageName,
override
Writes the code for host Api, api
.
Example:
class FooCodec extends StandardMessageCodec {...}
abstract class Foo { static const MessageCodec<Object?> codec = FooCodec(); int add(int x, int y); static void setup(Foo api, {BinaryMessenger? binaryMessenger}) {...} }
Implementation
@override
void writeFlutterApi(
DartOptions generatorOptions,
Root root,
Indent indent,
Api api, {
String Function(Method)? channelNameFunc,
bool isMockHandler = false,
required String dartPackageName,
}) {
assert(api.location == ApiLocation.flutter);
final List<String> customEnumNames =
root.enums.map((Enum x) => x.name).toList();
String codecName = _standardMessageCodec;
if (getCodecClasses(api, root).isNotEmpty) {
codecName = _getCodecName(api);
_writeCodec(indent, codecName, api, root);
}
indent.newln();
addDocumentationComments(
indent, api.documentationComments, _docCommentSpec);
indent.write('abstract class ${api.name} ');
indent.addScoped('{', '}', () {
if (isMockHandler) {
indent.writeln(
'static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => TestDefaultBinaryMessengerBinding.instance;');
}
indent
.writeln('static const MessageCodec<Object?> codec = $codecName();');
indent.newln();
for (final Method func in api.methods) {
addDocumentationComments(
indent, func.documentationComments, _docCommentSpec);
final bool isAsync = func.isAsynchronous;
final String returnType = isAsync
? 'Future<${_addGenericTypesNullable(func.returnType)}>'
: _addGenericTypesNullable(func.returnType);
final String argSignature = _getMethodArgumentsSignature(
func,
_getArgumentName,
);
indent.writeln('$returnType ${func.name}($argSignature);');
indent.newln();
}
indent.write(
'static void setup(${api.name}? api, {BinaryMessenger? binaryMessenger}) ');
indent.addScoped('{', '}', () {
for (final Method func in api.methods) {
indent.write('');
indent.addScoped('{', '}', () {
indent.writeln(
'final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(',
);
final String channelName = channelNameFunc == null
? makeChannelName(api, func, dartPackageName)
: channelNameFunc(func);
indent.nest(2, () {
indent.writeln("'$channelName', codec,");
indent.writeln(
'binaryMessenger: binaryMessenger);',
);
});
final String messageHandlerSetterWithOpeningParentheses = isMockHandler
? '_testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler<Object?>(channel, '
: 'channel.setMessageHandler(';
indent.write('if (api == null) ');
indent.addScoped('{', '}', () {
indent.writeln(
'${messageHandlerSetterWithOpeningParentheses}null);');
}, addTrailingNewline: false);
indent.add(' else ');
indent.addScoped('{', '}', () {
indent.write(
'$messageHandlerSetterWithOpeningParentheses(Object? message) async ',
);
indent.addScoped('{', '});', () {
final String returnType =
_addGenericTypesNullable(func.returnType);
final bool isAsync = func.isAsynchronous;
final String emptyReturnStatement = isMockHandler
? 'return <Object?>[];'
: func.returnType.isVoid
? 'return;'
: 'return null;';
String call;
if (func.arguments.isEmpty) {
indent.writeln('// ignore message');
call = 'api.${func.name}()';
} else {
indent.writeln('assert(message != null,');
indent.writeln("'Argument for $channelName was null.');");
const String argsArray = 'args';
indent.writeln(
'final List<Object?> $argsArray = (message as List<Object?>?)!;');
String argNameFunc(int index, NamedType type) =>
_getSafeArgumentName(index, type);
enumerate(func.arguments, (int count, NamedType arg) {
final String argType = _addGenericTypes(arg.type);
final String argName = argNameFunc(count, arg);
final String genericArgType =
_makeGenericTypeArguments(arg.type);
final String castCall = _makeGenericCastCall(arg.type);
final String leftHandSide = 'final $argType? $argName';
if (customEnumNames.contains(arg.type.baseName)) {
indent.writeln(
'$leftHandSide = $argsArray[$count] == null ? null : $argType.values[$argsArray[$count] as int];');
} else {
indent.writeln(
'$leftHandSide = ($argsArray[$count] as $genericArgType?)${castCall.isEmpty ? '' : '?$castCall'};');
}
if (!arg.type.isNullable) {
indent.writeln('assert($argName != null,');
indent.writeln(
" 'Argument for $channelName was null, expected non-null $argType.');");
}
});
final Iterable<String> argNames =
indexMap(func.arguments, (int index, NamedType field) {
final String name = _getSafeArgumentName(index, field);
return '$name${field.type.isNullable ? '' : '!'}';
});
call = 'api.${func.name}(${argNames.join(', ')})';
}
if (func.returnType.isVoid) {
if (isAsync) {
indent.writeln('await $call;');
} else {
indent.writeln('$call;');
}
indent.writeln(emptyReturnStatement);
} else {
if (isAsync) {
indent.writeln('final $returnType output = await $call;');
} else {
indent.writeln('final $returnType output = $call;');
}
const String returnExpression = 'output';
final String returnStatement = isMockHandler
? 'return <Object?>[$returnExpression];'
: 'return $returnExpression;';
indent.writeln(returnStatement);
}
});
});
});
}
});
});
}