mirror of
https://github.com/flutter/packages.git
synced 2025-07-03 17:18:22 +08:00
pigeon 1.4 (#188)
* fixed nullability in objc code for callback errors * fixed nullability of nested types in dart * added test that asserts the version in generated code headers is correct
This commit is contained in:
@ -1,3 +1,9 @@
|
|||||||
|
## 0.1.4
|
||||||
|
|
||||||
|
* Fixed nullability for NSError's in generated objc code.
|
||||||
|
* Fixed nullability of nested objects in the Dart generator.
|
||||||
|
* Added test to make sure the pigeon version is correct in generated code headers.
|
||||||
|
|
||||||
## 0.1.3
|
## 0.1.3
|
||||||
|
|
||||||
* Added error message if supported datatypes are used as arguments or return
|
* Added error message if supported datatypes are used as arguments or return
|
||||||
|
@ -151,7 +151,8 @@ void generateDart(Root root, StringSink sink) {
|
|||||||
for (Field field in klass.fields) {
|
for (Field field in klass.fields) {
|
||||||
indent.write('pigeonMap[\'${field.name}\'] = ');
|
indent.write('pigeonMap[\'${field.name}\'] = ');
|
||||||
if (customClassNames.contains(field.dataType)) {
|
if (customClassNames.contains(field.dataType)) {
|
||||||
indent.addln('${field.name}._toMap();');
|
indent.addln(
|
||||||
|
'${field.name} == null ? null : ${field.name}._toMap();');
|
||||||
} else {
|
} else {
|
||||||
indent.addln('${field.name};');
|
indent.addln('${field.name};');
|
||||||
}
|
}
|
||||||
@ -162,6 +163,10 @@ void generateDart(Root root, StringSink sink) {
|
|||||||
indent.write(
|
indent.write(
|
||||||
'static ${klass.name} _fromMap(Map<dynamic, dynamic> pigeonMap) ');
|
'static ${klass.name} _fromMap(Map<dynamic, dynamic> pigeonMap) ');
|
||||||
indent.scoped('{', '}', () {
|
indent.scoped('{', '}', () {
|
||||||
|
indent.write('if (pigeonMap == null)');
|
||||||
|
indent.scoped('{', '}', () {
|
||||||
|
indent.writeln('return null;');
|
||||||
|
});
|
||||||
indent.writeln('final ${klass.name} result = ${klass.name}();');
|
indent.writeln('final ${klass.name} result = ${klass.name}();');
|
||||||
for (Field field in klass.fields) {
|
for (Field field in klass.fields) {
|
||||||
indent.write('result.${field.name} = ');
|
indent.write('result.${field.name} = ');
|
||||||
|
@ -8,7 +8,7 @@ import 'dart:mirrors';
|
|||||||
import 'ast.dart';
|
import 'ast.dart';
|
||||||
|
|
||||||
/// The current version of pigeon.
|
/// The current version of pigeon.
|
||||||
const String pigeonVersion = '0.1.2';
|
const String pigeonVersion = '0.1.4';
|
||||||
|
|
||||||
/// Read all the content from [stdin] to a String.
|
/// Read all the content from [stdin] to a String.
|
||||||
String readStdin() {
|
String readStdin() {
|
||||||
|
@ -28,8 +28,8 @@ String _className(String prefix, String className) {
|
|||||||
|
|
||||||
String _callbackForType(String dartType, String objcType) {
|
String _callbackForType(String dartType, String objcType) {
|
||||||
return dartType == 'void'
|
return dartType == 'void'
|
||||||
? 'void(^)(NSError*)'
|
? 'void(^)(NSError* _Nullable)'
|
||||||
: 'void(^)($objcType*, NSError*)';
|
: 'void(^)($objcType*, NSError* _Nullable)';
|
||||||
}
|
}
|
||||||
|
|
||||||
const Map<String, String> _objcTypeForDartTypeMap = <String, String>{
|
const Map<String, String> _objcTypeForDartTypeMap = <String, String>{
|
||||||
|
@ -17,6 +17,9 @@ class SearchReply {
|
|||||||
|
|
||||||
// ignore: unused_element
|
// ignore: unused_element
|
||||||
static SearchReply _fromMap(Map<dynamic, dynamic> pigeonMap) {
|
static SearchReply _fromMap(Map<dynamic, dynamic> pigeonMap) {
|
||||||
|
if (pigeonMap == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
final SearchReply result = SearchReply();
|
final SearchReply result = SearchReply();
|
||||||
result.result = pigeonMap['result'];
|
result.result = pigeonMap['result'];
|
||||||
result.error = pigeonMap['error'];
|
result.error = pigeonMap['error'];
|
||||||
@ -39,6 +42,9 @@ class SearchRequest {
|
|||||||
|
|
||||||
// ignore: unused_element
|
// ignore: unused_element
|
||||||
static SearchRequest _fromMap(Map<dynamic, dynamic> pigeonMap) {
|
static SearchRequest _fromMap(Map<dynamic, dynamic> pigeonMap) {
|
||||||
|
if (pigeonMap == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
final SearchRequest result = SearchRequest();
|
final SearchRequest result = SearchRequest();
|
||||||
result.query = pigeonMap['query'];
|
result.query = pigeonMap['query'];
|
||||||
result.anInt = pigeonMap['anInt'];
|
result.anInt = pigeonMap['anInt'];
|
||||||
@ -52,12 +58,15 @@ class Nested {
|
|||||||
// ignore: unused_element
|
// ignore: unused_element
|
||||||
Map<dynamic, dynamic> _toMap() {
|
Map<dynamic, dynamic> _toMap() {
|
||||||
final Map<dynamic, dynamic> pigeonMap = <dynamic, dynamic>{};
|
final Map<dynamic, dynamic> pigeonMap = <dynamic, dynamic>{};
|
||||||
pigeonMap['request'] = request._toMap();
|
pigeonMap['request'] = request == null ? null : request._toMap();
|
||||||
return pigeonMap;
|
return pigeonMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore: unused_element
|
// ignore: unused_element
|
||||||
static Nested _fromMap(Map<dynamic, dynamic> pigeonMap) {
|
static Nested _fromMap(Map<dynamic, dynamic> pigeonMap) {
|
||||||
|
if (pigeonMap == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
final Nested result = Nested();
|
final Nested result = Nested();
|
||||||
result.request = SearchRequest._fromMap(pigeonMap['request']);
|
result.request = SearchRequest._fromMap(pigeonMap['request']);
|
||||||
return result;
|
return result;
|
||||||
@ -105,6 +114,23 @@ class NestedApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class TestNestedApi {
|
||||||
|
SearchReply search(Nested arg);
|
||||||
|
static void setup(TestNestedApi api) {
|
||||||
|
{
|
||||||
|
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
|
||||||
|
'dev.flutter.pigeon.NestedApi.search', StandardMessageCodec());
|
||||||
|
channel.setMockMessageHandler((dynamic message) async {
|
||||||
|
final Map<dynamic, dynamic> mapMessage =
|
||||||
|
message as Map<dynamic, dynamic>;
|
||||||
|
final Nested input = Nested._fromMap(mapMessage);
|
||||||
|
final SearchReply output = api.search(input);
|
||||||
|
return <dynamic, dynamic>{'result': output._toMap()};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Api {
|
class Api {
|
||||||
Future<SearchReply> search(SearchRequest arg) async {
|
Future<SearchReply> search(SearchRequest arg) async {
|
||||||
final Map<dynamic, dynamic> requestMap = arg._toMap();
|
final Map<dynamic, dynamic> requestMap = arg._toMap();
|
||||||
|
@ -14,10 +14,32 @@ class Mock implements TestHostApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MockNested implements TestNestedApi {
|
||||||
|
bool didCall = false;
|
||||||
|
@override
|
||||||
|
SearchReply search(Nested arg) {
|
||||||
|
didCall = true;
|
||||||
|
if (arg.request == null) {
|
||||||
|
return SearchReply();
|
||||||
|
} else {
|
||||||
|
return SearchReply()..result = arg.request.query;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
test('description', () async {
|
test('simple', () async {
|
||||||
|
final NestedApi api = NestedApi();
|
||||||
|
final MockNested mock = MockNested();
|
||||||
|
TestNestedApi.setup(mock);
|
||||||
|
final SearchReply reply = await api.search(Nested()..request = null);
|
||||||
|
expect(mock.didCall, true);
|
||||||
|
expect(reply.result, null);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('nested', () async {
|
||||||
final Api api = Api();
|
final Api api = Api();
|
||||||
final Mock mock = Mock();
|
final Mock mock = Mock();
|
||||||
TestHostApi.setup(mock);
|
TestHostApi.setup(mock);
|
||||||
|
@ -27,7 +27,7 @@ class Nested {
|
|||||||
SearchRequest request;
|
SearchRequest request;
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostApi()
|
@HostApi(dartHostTestHandler: 'TestNestedApi')
|
||||||
abstract class NestedApi {
|
abstract class NestedApi {
|
||||||
SearchReply search(Nested nested);
|
SearchReply search(Nested nested);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
name: pigeon
|
name: pigeon
|
||||||
version: 0.1.3
|
version: 0.1.4
|
||||||
description: Code generator tool to make communication between Flutter and the host platform type-safe and easier.
|
description: Code generator tool to make communication between Flutter and the host platform type-safe and easier.
|
||||||
homepage: https://github.com/flutter/packages/tree/master/packages/pigeon
|
homepage: https://github.com/flutter/packages/tree/master/packages/pigeon
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -58,7 +58,10 @@ void main() {
|
|||||||
final StringBuffer sink = StringBuffer();
|
final StringBuffer sink = StringBuffer();
|
||||||
generateDart(root, sink);
|
generateDart(root, sink);
|
||||||
final String code = sink.toString();
|
final String code = sink.toString();
|
||||||
expect(code, contains('pigeonMap[\'nested\'] = nested._toMap()'));
|
expect(
|
||||||
|
code,
|
||||||
|
contains(
|
||||||
|
'pigeonMap[\'nested\'] = nested == null ? null : nested._toMap()'));
|
||||||
expect(code,
|
expect(code,
|
||||||
contains('result.nested = Input._fromMap(pigeonMap[\'nested\']);'));
|
contains('result.nested = Input._fromMap(pigeonMap[\'nested\']);'));
|
||||||
});
|
});
|
||||||
|
@ -315,7 +315,7 @@ void main() {
|
|||||||
final StringBuffer sink = StringBuffer();
|
final StringBuffer sink = StringBuffer();
|
||||||
generateObjcHeader(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
|
generateObjcHeader(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
|
||||||
final String code = sink.toString();
|
final String code = sink.toString();
|
||||||
expect(code, contains('completion:(void(^)(NSError*))'));
|
expect(code, contains('completion:(void(^)(NSError* _Nullable))'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('gen flutter void return source', () {
|
test('gen flutter void return source', () {
|
||||||
@ -331,7 +331,7 @@ void main() {
|
|||||||
final StringBuffer sink = StringBuffer();
|
final StringBuffer sink = StringBuffer();
|
||||||
generateObjcSource(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
|
generateObjcSource(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
|
||||||
final String code = sink.toString();
|
final String code = sink.toString();
|
||||||
expect(code, contains('completion:(void(^)(NSError*))'));
|
expect(code, contains('completion:(void(^)(NSError* _Nullable))'));
|
||||||
expect(code, contains('completion(nil)'));
|
expect(code, contains('completion(nil)'));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -383,7 +383,7 @@ void main() {
|
|||||||
expect(
|
expect(
|
||||||
code,
|
code,
|
||||||
contains(
|
contains(
|
||||||
'(void)doSomething:(void(^)(ABCOutput*, NSError*))completion'));
|
'(void)doSomething:(void(^)(ABCOutput*, NSError* _Nullable))completion'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('gen flutter void arg header', () {
|
test('gen flutter void arg header', () {
|
||||||
@ -402,7 +402,7 @@ void main() {
|
|||||||
expect(
|
expect(
|
||||||
code,
|
code,
|
||||||
contains(
|
contains(
|
||||||
'(void)doSomething:(void(^)(ABCOutput*, NSError*))completion'));
|
'(void)doSomething:(void(^)(ABCOutput*, NSError* _Nullable))completion'));
|
||||||
expect(code, contains('channel sendMessage:nil'));
|
expect(code, contains('channel sendMessage:nil'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
19
packages/pigeon/test/version_test.dart
Normal file
19
packages/pigeon/test/version_test.dart
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// 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 'dart:io';
|
||||||
|
|
||||||
|
import 'package:pigeon/generator_tools.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
test('pigeon version matches pubspec', () {
|
||||||
|
final String pubspecPath = '${Directory.current.path}/pubspec.yaml';
|
||||||
|
final String pubspec = File(pubspecPath).readAsStringSync();
|
||||||
|
final RegExp regex = RegExp('version:\s*(.*)');
|
||||||
|
final RegExpMatch match = regex.firstMatch(pubspec);
|
||||||
|
expect(match, isNotNull);
|
||||||
|
expect(pigeonVersion, match.group(1).trim());
|
||||||
|
});
|
||||||
|
}
|
Reference in New Issue
Block a user