blob: 95487cec806b1483a82287d226a6c4c1af74abd3 [file] [log] [blame]
// Copyright 2020 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'ast.dart';
import 'generator_tools.dart';
const Map<String, String> _javaTypeForDartTypeMap = <String, String>{
'bool': 'Boolean',
'int': 'Long',
'String': 'String',
'double': 'Double',
'Uint8List': 'byte[]',
'Int32List': 'int[]',
'Int64List': 'long[]',
'Float64List': 'double[]',
};
/// Options that control how Java code will be generated.
class JavaOptions {
/// The name of the class that will house all the generated classes.
String className;
/// The package where the generated class will live.
String package;
}
void _writeHostApi(Indent indent, Api api) {
assert(api.location == ApiLocation.host);
indent.writeln(
'/** Generated interface from Pigeon that represents a handler of messages from Flutter.*/');
indent.write('public interface ${api.name} ');
indent.scoped('{', '}', () {
for (Method method in api.methods) {
indent.writeln(
'${method.returnType} ${method.name}(${method.argType} arg);');
}
indent.addln('');
indent.writeln(
'/** Sets up an instance of `${api.name}` to handle messages through the `binaryMessenger` */');
indent.write(
'public static void setup(BinaryMessenger binaryMessenger, ${api.name} api) ');
indent.scoped('{', '}', () {
for (Method method in api.methods) {
final String channelName = makeChannelName(api, method);
indent.write('');
indent.scoped('{', '}', () {
indent.writeln('BasicMessageChannel<Object> channel =');
indent.inc();
indent.inc();
indent.writeln(
'new BasicMessageChannel<Object>(binaryMessenger, "$channelName", new StandardMessageCodec());');
indent.dec();
indent.dec();
indent.write(
'channel.setMessageHandler(new BasicMessageChannel.MessageHandler<Object>() ');
indent.scoped('{', '});', () {
indent.write(
'public void onMessage(Object message, BasicMessageChannel.Reply<Object> reply) ');
indent.scoped('{', '}', () {
final String argType = method.argType;
final String returnType = method.returnType;
indent.writeln(
'$argType input = $argType.fromMap((HashMap)message);');
indent.writeln('$returnType output = api.${method.name}(input);');
indent.writeln('reply.reply(output.toMap());');
});
});
});
}
});
});
}
// void _writeFlutterApi(Indent indent, Api api) {
// assert(api.location == ApiLocation.flutter);
// }
String _makeGetter(Field field) {
final String uppercased =
field.name.substring(0, 1).toUpperCase() + field.name.substring(1);
return 'get$uppercased';
}
String _makeSetter(Field field) {
final String uppercased =
field.name.substring(0, 1).toUpperCase() + field.name.substring(1);
return 'set$uppercased';
}
String _javaTypeForDartType(String datatype) {
return _javaTypeForDartTypeMap[datatype];
}
/// Generates the ".java" file for the AST represented by [root] to [sink] with the
/// provided [options].
void generateJava(JavaOptions options, Root root, StringSink sink) {
final Indent indent = Indent(sink);
indent.writeln('// Autogenerated from Pigeon, do not edit directly.');
indent.writeln('// See also: https://pub.dev/packages/pigeon');
indent.addln('');
if (options.package != null) {
indent.writeln('package ${options.package};');
}
indent.addln('');
indent.writeln('import java.util.HashMap;');
indent.addln('');
indent.writeln('import io.flutter.plugin.common.BasicMessageChannel;');
indent.writeln('import io.flutter.plugin.common.BinaryMessenger;');
indent.writeln('import io.flutter.plugin.common.StandardMessageCodec;');
indent.addln('');
assert(options.className != null);
indent.writeln('/** Generated class from Pigeon. */');
indent.write('public class ${options.className} ');
indent.scoped('{', '}', () {
for (Class klass in root.classes) {
indent.addln('');
indent.writeln(
'/** Generated class from Pigeon that represents data sent in messages. */');
indent.write('public static class ${klass.name} ');
indent.scoped('{', '}', () {
for (Field field in klass.fields) {
final HostDatatype hostDatatype = getHostDatatype(
field, root.classes, _javaTypeForDartType, (String x) => x);
indent.writeln('private ${hostDatatype.datatype} ${field.name};');
indent.writeln(
'public ${hostDatatype.datatype} ${_makeGetter(field)}() { return ${field.name}; }');
indent.writeln(
'public void ${_makeSetter(field)}(${hostDatatype.datatype} setterArg) { this.${field.name} = setterArg; }');
indent.addln('');
}
indent.write('HashMap toMap() ');
indent.scoped('{', '}', () {
indent.writeln(
'HashMap<String, Object> toMapResult = new HashMap<String, Object>();');
for (Field field in klass.fields) {
indent.writeln('toMapResult.put("${field.name}", ${field.name});');
}
indent.writeln('return toMapResult;');
});
indent.write('static ${klass.name} fromMap(HashMap map) ');
indent.scoped('{', '}', () {
indent.writeln('${klass.name} fromMapResult = new ${klass.name}();');
for (Field field in klass.fields) {
indent.writeln(
'fromMapResult.${field.name} = (${field.dataType})map.get("${field.name}");');
}
indent.writeln('return fromMapResult;');
});
});
}
for (Api api in root.apis) {
indent.addln('');
if (api.location == ApiLocation.host) {
_writeHostApi(indent, api);
} else if (api.location == ApiLocation.flutter) {
// _writeFlutterApi(indent, api);
}
}
});
}