writeFlutterApi method

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

Writes a single Flutter Api to indent.

Implementation

@override
void writeFlutterApi(
    ArkTSOptions 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 ArkTS.'
  ];
  addDocumentationComments(indent, api.documentationComments, _docCommentSpec,
      generatorComments: generatedMessages);

  indent.write('export class ${api.name} ');
  indent.addScoped('{', '}', () {
    indent.writeln('binaryMessenger: BinaryMessenger;');
    indent.newln();
    indent.write('constructor(binaryMessenger: BinaryMessenger) ');
    indent.addScoped('{', '}', () {
      indent.writeln('this.binaryMessenger = binaryMessenger;');
    });

    indent.newln();
    final String codecName = _getCodecName(api);
    indent.writeln('/** The codec used by ${api.name}. */');
    indent.write('static getCodec(): MessageCodec<Object> ');
    indent.addScoped('{', '}', () {
      indent.write('return ');
      if (getCodecClasses(api, root).isNotEmpty) {
        indent.addln('$codecName.INSTANCE;');
      } else {
        indent.addln('new $_standardMessageCodec();');
      }
    });

    indent.newln();

    /// Returns an argument name that can be used in a context where it is possible to collide
    /// and append `.index` to enums.
    String getEnumSafeArgumentExpression(int count, NamedType argument) {
      if (isEnum(root, argument.type)) {
        return argument.type.isNullable
            ? '${_getArgumentName(count, argument)}Arg == null ? null : ${_getArgumentName(count, argument)}Arg.index'
            : '${_getArgumentName(count, argument)}Arg.index';
      }
      return '${_getArgumentName(count, argument)}Arg';
    }

    for (final Method func in api.methods) {
      final String channelName = makeChannelName(api, func, dartPackageName);
      final String returnType = func.returnType.isVoid
          ? 'void'
          : _arkTSTypeForDartType(func.returnType);
      String sendArgument;
      addDocumentationComments(
          indent, func.documentationComments, _docCommentSpec);
      if (func.arguments.isEmpty) {
        indent.write('${func.name}(callback: Reply<$returnType>):void ');
        sendArgument = 'null';
      } else {
        final Iterable<String> argTypes = func.arguments
            .map((NamedType e) => _arkTSTypeForDartType(e.type));
        final Iterable<String> argNames =
            indexMap(func.arguments, _getSafeArgumentName);
        final Iterable<String> enumSafeArgNames =
            indexMap(func.arguments, getEnumSafeArgumentExpression);
        sendArgument = '[${argNames.join(', ')}]';
        final String argsSignature =
            map2(argTypes, argNames, (String x, String y) => '$y: $x')
                .join(',');
        indent.write(
            '${func.name}($argsSignature, callback: Reply<$returnType>) ');
      }
      indent.addScoped('{', '}', () {
        const String channel = 'channel';
        indent.writeln('let $channel: BasicMessageChannel<Object> = ');
        indent.nest(2, () {
          indent.writeln('new BasicMessageChannel<Object>(');
          indent.nest(2, () {
            indent.writeln(
                'this.binaryMessenger, "$channelName", ${api.name}.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';
              if (func.returnType.baseName == 'number') {
                indent.writeln(
                    'let $output: $returnType = channelReply == null ? null : channelReply as number;');
              } else if (isEnum(root, func.returnType)) {
                indent.writeln(
                    'let $output: $returnType = channelReply == null ? null : $returnType[channelReply as number];');
              } else {
                indent.writeln(
                    'let $output: $returnType = ${_cast('channelReply', artTSType: returnType)};');
              }
              indent.writeln('callback.reply($output);');
            });
          }
        });
      });
    }
  });
}