blob: 7a122901d250c80b6aaaee56f6e4b97a36723674 [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';
void _writeHostApi(Indent indent, Api api) {
assert(api.location == ApiLocation.host);
indent.write('class ${api.name} ');
indent.scoped('{', '}', () {
for (Method func in api.methods) {
indent.write(
'Future<${func.returnType}> ${func.name}(${func.argType} arg) async ');
indent.scoped('{', '}', () {
indent.writeln('Map requestMap = arg._toMap();');
final String channelName = makeChannelName(api, func);
indent.writeln('BasicMessageChannel channel =');
indent.inc();
indent.inc();
indent.writeln(
'BasicMessageChannel(\'$channelName\', StandardMessageCodec());');
indent.dec();
indent.dec();
indent.writeln('Map replyMap = await channel.send(requestMap);');
indent.writeln('return ${func.returnType}._fromMap(replyMap);');
});
}
});
indent.writeln('');
}
void _writeFlutterApi(Indent indent, Api api) {
assert(api.location == ApiLocation.flutter);
indent.write('abstract class ${api.name} ');
indent.scoped('{', '}', () {
for (Method func in api.methods) {
indent.writeln('${func.returnType} ${func.name}(${func.argType} arg);');
}
});
indent.addln('');
indent.write('void ${api.name}Setup(${api.name} api) ');
indent.scoped('{', '}', () {
for (Method func in api.methods) {
indent.write('');
indent.scoped('{', '}', () {
indent.writeln('BasicMessageChannel channel =');
indent.inc();
indent.inc();
indent.writeln(
'BasicMessageChannel("${makeChannelName(api, func)}", StandardMessageCodec());');
indent.dec();
indent.dec();
indent.write('channel.setMessageHandler((dynamic message) async ');
indent.scoped('{', '});', () {
final String argType = func.argType;
final String returnType = func.returnType;
indent.writeln('Map mapMessage = message as Map;');
indent.writeln('$argType input = $argType._fromMap(mapMessage);');
indent.writeln('$returnType output = api.${func.name}(input);');
indent.writeln('return output._toMap();');
});
});
}
});
}
/// Generates Dart source code for the given AST represented by [root],
/// outputting the code to [sink].
void generateDart(Root root, StringSink sink) {
final List<String> customClassNames =
root.classes.map((Class x) => x.name).toList();
final Indent indent = Indent(sink);
indent.writeln('// Autogenerated from Dartle, do not edit directly.');
indent.writeln('import \'package:flutter/services.dart\';');
indent.writeln('');
for (Class klass in root.classes) {
sink.write('class ${klass.name} ');
indent.scoped('{', '}', () {
for (Field field in klass.fields) {
indent.writeln('${field.dataType} ${field.name};');
}
indent.writeln('// ignore: unused_element');
indent.write('Map _toMap() ');
indent.scoped('{', '}', () {
indent.writeln('Map dartleMap = Map();');
for (Field field in klass.fields) {
indent.write('dartleMap["${field.name}"] = ');
if (customClassNames.contains(field.dataType)) {
indent.addln('${field.name}._toMap();');
} else {
indent.addln('${field.name};');
}
}
indent.writeln('return dartleMap;');
});
indent.writeln('// ignore: unused_element');
indent.write('static ${klass.name} _fromMap(Map dartleMap) ');
indent.scoped('{', '}', () {
indent.writeln('var result = ${klass.name}();');
for (Field field in klass.fields) {
indent.write('result.${field.name} = ');
if (customClassNames.contains(field.dataType)) {
indent.addln(
'${field.dataType}._fromMap(dartleMap["${field.name}"]);');
} else {
indent.addln('dartleMap["${field.name}"];');
}
}
indent.writeln('return result;');
});
});
indent.writeln('');
}
for (Api api in root.apis) {
if (api.location == ApiLocation.host) {
_writeHostApi(indent, api);
} else if (api.location == ApiLocation.flutter) {
_writeFlutterApi(indent, api);
}
}
}