| // 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); |
| } |
| } |
| } |