writeFlutterApi method

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

Writes the code for a flutter Api, api. Example: public static final class Foo { public Foo(BinaryMessenger argBinaryMessenger) {...} public interface Reply

Implementation

@override
void writeFlutterApi(
  JavaOptions generatorOptions,
  Root root,
  Indent indent,
  Api api, {
  required String dartPackageName,
}) {
  assert(api.location == ApiLocation.flutter);
  if (getCodecClasses(api, root).isNotEmpty) {
    _writeCodec(indent, api, root);
  }
  const List<String> generatedMessages = <String>[
    ' Generated class from Pigeon that represents Flutter messages that can be called from Java.'
  ];
  addDocumentationComments(indent, api.documentationComments, _docCommentSpec,
      generatorComments: generatedMessages);

  indent.write('public static class ${api.name} ');
  indent.addScoped('{', '}', () {
    indent.writeln('private final @NonNull BinaryMessenger binaryMessenger;');
    indent.newln();
    indent.write(
        'public ${api.name}(@NonNull BinaryMessenger argBinaryMessenger) ');
    indent.addScoped('{', '}', () {
      indent.writeln('this.binaryMessenger = argBinaryMessenger;');
    });
    indent.newln();
    indent.writeln('/** Public interface for sending reply. */ ');
    // This warning can't be fixed without a breaking change, and the next
    // breaking change to this part of the code should be eliminating Reply
    // entirely in favor of using Result<T> for
    // https://github.com/flutter/flutter/issues/118243
    // See also the comment on the Result<T> code.
    indent.writeln('@SuppressWarnings("UnknownNullness")');
    indent.write('public interface Reply<T> ');
    indent.addScoped('{', '}', () {
      indent.writeln('void reply(T reply);');
    });
    final String codecName = _getCodecName(api);
    indent.writeln('/** The codec used by ${api.name}. */');
    indent.write('static @NonNull MessageCodec<Object> getCodec() ');
    indent.addScoped('{', '}', () {
      indent.write('return ');
      if (getCodecClasses(api, root).isNotEmpty) {
        indent.addln('$codecName.INSTANCE;');
      } else {
        indent.addln('new $_standardMessageCodec();');
      }
    });

    for (final Method func in api.methods) {
      final String channelName = makeChannelName(api, func, dartPackageName);
      final String returnType = func.returnType.isVoid
          ? 'Void'
          : _javaTypeForDartType(func.returnType);
      String sendArgument;
      addDocumentationComments(
          indent, func.documentationComments, _docCommentSpec);
      if (func.arguments.isEmpty) {
        indent.write(
            'public void ${func.name}(@NonNull Reply<$returnType> callback) ');
        sendArgument = 'null';
      } else {
        final Iterable<String> argTypes = func.arguments
            .map((NamedType e) => _nullsafeJavaTypeForDartType(e.type));
        final Iterable<String> argNames =
            indexMap(func.arguments, _getSafeArgumentName);
        if (func.arguments.length == 1) {
          sendArgument =
              'new ArrayList<Object>(Collections.singletonList(${argNames.first}))';
        } else {
          sendArgument =
              'new ArrayList<Object>(Arrays.asList(${argNames.join(', ')}))';
        }
        final String argsSignature =
            map2(argTypes, argNames, (String x, String y) => '$x $y')
                .join(', ');
        indent.write(
            'public void ${func.name}($argsSignature, @NonNull Reply<$returnType> callback) ');
      }
      indent.addScoped('{', '}', () {
        const String channel = 'channel';
        indent.writeln('BasicMessageChannel<Object> $channel =');
        indent.nest(2, () {
          indent.writeln('new BasicMessageChannel<>(');
          indent.nest(2, () {
            indent.writeln('binaryMessenger, "$channelName", getCodec());');
          });
        });
        indent.writeln('$channel.send(');
        indent.nest(2, () {
          indent.writeln('$sendArgument,');
          indent.write('channelReply -> ');
          if (func.returnType.isVoid) {
            indent.addln('callback.reply(null));');
          } else {
            indent.addScoped('{', '});', () {
              const String output = 'output';
              indent.writeln('@SuppressWarnings("ConstantConditions")');
              if (func.returnType.baseName == 'int') {
                indent.writeln(
                    '$returnType $output = channelReply == null ? null : ((Number) channelReply).longValue();');
              } else {
                indent.writeln(
                    '$returnType $output = ${_cast('channelReply', javaType: returnType)};');
              }
              indent.writeln('callback.reply($output);');
            });
          }
        });
      });
    }
  });
}