writeFlutterApi method

  1. @override
void writeFlutterApi(
  1. CppOptions generatorOptions,
  2. Root root,
  3. Indent indent,
  4. AstFlutterApi api, {
  5. required String dartPackageName,
})
override

Writes a single Flutter Api to indent.

Implementation

@override
void writeFlutterApi(
  CppOptions generatorOptions,
  Root root,
  Indent indent,
  AstFlutterApi api, {
  required String dartPackageName,
}) {
  if (getCodecClasses(api, root).isNotEmpty) {
    _writeCodec(generatorOptions, root, indent, api);
  }
  indent.writeln(
      '$_commentPrefix Generated class from Pigeon that represents Flutter messages that can be called from C++.');
  _writeFunctionDefinition(
    indent,
    api.name,
    scope: api.name,
    parameters: <String>[
      'flutter::BinaryMessenger* binary_messenger',
    ],
    initializers: <String>[
      'binary_messenger_(binary_messenger)',
      'message_channel_suffix_("")'
    ],
  );
  _writeFunctionDefinition(
    indent,
    api.name,
    scope: api.name,
    parameters: <String>[
      'flutter::BinaryMessenger* binary_messenger',
      'const std::string& message_channel_suffix'
    ],
    initializers: <String>[
      'binary_messenger_(binary_messenger)',
      'message_channel_suffix_(message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix : "")'
    ],
  );
  final String codeSerializerName = getCodecClasses(api, root).isNotEmpty
      ? _getCodecSerializerName(api)
      : _defaultCodecSerializer;
  _writeFunctionDefinition(
    indent,
    'GetCodec',
    scope: api.name,
    returnType: 'const flutter::StandardMessageCodec&',
    body: () {
      indent.writeln(
          'return flutter::StandardMessageCodec::GetInstance(&$codeSerializerName::GetInstance());');
    },
  );
  for (final Method func in api.methods) {
    final HostDatatype returnType =
        getHostDatatype(func.returnType, _shortBaseCppTypeForBuiltinDartType);

    // Determine the input parameter list, saved in a structured form for later
    // use as platform channel call arguments.
    final Iterable<_HostNamedType> hostParameters =
        indexMap(func.parameters, (int i, NamedType arg) {
      final HostDatatype hostType =
          getFieldHostDatatype(arg, _shortBaseCppTypeForBuiltinDartType);
      return _HostNamedType(_getSafeArgumentName(i, arg), hostType, arg.type);
    });
    final List<String> parameters = <String>[
      ...hostParameters.map((_HostNamedType arg) =>
          '${_flutterApiArgumentType(arg.hostType)} ${arg.name}'),
      ..._flutterApiCallbackParameters(returnType),
    ];
    _writeFunctionDefinition(indent, _makeMethodName(func),
        scope: api.name,
        returnType: _voidType,
        parameters: parameters, body: () {
      indent.writeln(
          'const std::string channel_name = "${makeChannelName(api, func, dartPackageName)}" + message_channel_suffix_;');
      indent.writeln('BasicMessageChannel<> channel(binary_messenger_, '
          'channel_name, &GetCodec());');

      // Convert arguments to EncodableValue versions.
      const String argumentListVariableName = 'encoded_api_arguments';
      indent.write('EncodableValue $argumentListVariableName = ');
      if (func.parameters.isEmpty) {
        indent.addln('EncodableValue();');
      } else {
        indent.addScoped('EncodableValue(EncodableList{', '});', () {
          for (final _HostNamedType param in hostParameters) {
            final String encodedArgument = _wrappedHostApiArgumentExpression(
              root,
              param.name,
              param.originalType,
              param.hostType,
              false,
            );
            indent.writeln('$encodedArgument,');
          }
        });
      }

      indent.write('channel.Send($argumentListVariableName, '
          // ignore: missing_whitespace_between_adjacent_strings
          '[channel_name, on_success = std::move(on_success), on_error = std::move(on_error)]'
          '(const uint8_t* reply, size_t reply_size) ');
      indent.addScoped('{', '});', () {
        String successCallbackArgument;
        successCallbackArgument = 'return_value';
        final String encodedReplyName = 'encodable_$successCallbackArgument';
        final String listReplyName = 'list_$successCallbackArgument';
        indent.writeln(
            'std::unique_ptr<EncodableValue> response = GetCodec().DecodeMessage(reply, reply_size);');
        indent.writeln('const auto& $encodedReplyName = *response;');
        indent.writeln(
            'const auto* $listReplyName = std::get_if<EncodableList>(&$encodedReplyName);');
        indent.writeScoped('if ($listReplyName) {', '} ', () {
          indent.writeScoped('if ($listReplyName->size() > 1) {', '} ', () {
            indent.writeln(
                'on_error(FlutterError(std::get<std::string>($listReplyName->at(0)), std::get<std::string>($listReplyName->at(1)), $listReplyName->at(2)));');
          }, addTrailingNewline: false);
          indent.addScoped('else {', '}', () {
            if (func.returnType.isVoid) {
              successCallbackArgument = '';
            } else {
              _writeEncodableValueArgumentUnwrapping(
                indent,
                root,
                returnType,
                argName: successCallbackArgument,
                encodableArgName: '$listReplyName->at(0)',
                apiType: ApiType.flutter,
              );
            }
            indent.writeln('on_success($successCallbackArgument);');
          });
        }, addTrailingNewline: false);
        indent.addScoped('else {', '} ', () {
          indent.writeln('on_error(CreateConnectionError(channel_name));');
        });
      });
    });
  }
}