Skip to content

Commit

Permalink
pigeon 1.4 (flutter#188)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
gaaclarke authored Aug 7, 2020
1 parent 7d26c62 commit cf96cba
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 13 deletions.
6 changes: 6 additions & 0 deletions packages/pigeon/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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

* Added error message if supported datatypes are used as arguments or return
Expand Down
7 changes: 6 additions & 1 deletion packages/pigeon/lib/dart_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ void generateDart(Root root, StringSink sink) {
for (Field field in klass.fields) {
indent.write('pigeonMap[\'${field.name}\'] = ');
if (customClassNames.contains(field.dataType)) {
indent.addln('${field.name}._toMap();');
indent.addln(
'${field.name} == null ? null : ${field.name}._toMap();');
} else {
indent.addln('${field.name};');
}
Expand All @@ -162,6 +163,10 @@ void generateDart(Root root, StringSink sink) {
indent.write(
'static ${klass.name} _fromMap(Map<dynamic, dynamic> pigeonMap) ');
indent.scoped('{', '}', () {
indent.write('if (pigeonMap == null)');
indent.scoped('{', '}', () {
indent.writeln('return null;');
});
indent.writeln('final ${klass.name} result = ${klass.name}();');
for (Field field in klass.fields) {
indent.write('result.${field.name} = ');
Expand Down
2 changes: 1 addition & 1 deletion packages/pigeon/lib/generator_tools.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import 'dart:mirrors';
import 'ast.dart';

/// 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.
String readStdin() {
Expand Down
4 changes: 2 additions & 2 deletions packages/pigeon/lib/objc_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ String _className(String prefix, String className) {

String _callbackForType(String dartType, String objcType) {
return dartType == 'void'
? 'void(^)(NSError*)'
: 'void(^)($objcType*, NSError*)';
? 'void(^)(NSError* _Nullable)'
: 'void(^)($objcType*, NSError* _Nullable)';
}

const Map<String, String> _objcTypeForDartTypeMap = <String, String>{
Expand Down
28 changes: 27 additions & 1 deletion packages/pigeon/mock_handler_tester/test/message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ class SearchReply {

// ignore: unused_element
static SearchReply _fromMap(Map<dynamic, dynamic> pigeonMap) {
if (pigeonMap == null) {
return null;
}
final SearchReply result = SearchReply();
result.result = pigeonMap['result'];
result.error = pigeonMap['error'];
Expand All @@ -39,6 +42,9 @@ class SearchRequest {

// ignore: unused_element
static SearchRequest _fromMap(Map<dynamic, dynamic> pigeonMap) {
if (pigeonMap == null) {
return null;
}
final SearchRequest result = SearchRequest();
result.query = pigeonMap['query'];
result.anInt = pigeonMap['anInt'];
Expand All @@ -52,12 +58,15 @@ class Nested {
// ignore: unused_element
Map<dynamic, dynamic> _toMap() {
final Map<dynamic, dynamic> pigeonMap = <dynamic, dynamic>{};
pigeonMap['request'] = request._toMap();
pigeonMap['request'] = request == null ? null : request._toMap();
return pigeonMap;
}

// ignore: unused_element
static Nested _fromMap(Map<dynamic, dynamic> pigeonMap) {
if (pigeonMap == null) {
return null;
}
final Nested result = Nested();
result.request = SearchRequest._fromMap(pigeonMap['request']);
return result;
Expand Down Expand Up @@ -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 {
Future<SearchReply> search(SearchRequest arg) async {
final Map<dynamic, dynamic> requestMap = arg._toMap();
Expand Down
24 changes: 23 additions & 1 deletion packages/pigeon/mock_handler_tester/test/widget_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
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 Mock mock = Mock();
TestHostApi.setup(mock);
Expand Down
2 changes: 1 addition & 1 deletion packages/pigeon/pigeons/message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Nested {
SearchRequest request;
}

@HostApi()
@HostApi(dartHostTestHandler: 'TestNestedApi')
abstract class NestedApi {
SearchReply search(Nested nested);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/pigeon/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
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.
homepage: https://github.com/flutter/packages/tree/master/packages/pigeon
dependencies:
Expand Down
5 changes: 4 additions & 1 deletion packages/pigeon/test/dart_generator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ void main() {
final StringBuffer sink = StringBuffer();
generateDart(root, sink);
final String code = sink.toString();
expect(code, contains('pigeonMap[\'nested\'] = nested._toMap()'));
expect(
code,
contains(
'pigeonMap[\'nested\'] = nested == null ? null : nested._toMap()'));
expect(code,
contains('result.nested = Input._fromMap(pigeonMap[\'nested\']);'));
});
Expand Down
8 changes: 4 additions & 4 deletions packages/pigeon/test/objc_generator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ void main() {
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(code, contains('completion:(void(^)(NSError*))'));
expect(code, contains('completion:(void(^)(NSError* _Nullable))'));
});

test('gen flutter void return source', () {
Expand All @@ -331,7 +331,7 @@ void main() {
final StringBuffer sink = StringBuffer();
generateObjcSource(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(code, contains('completion:(void(^)(NSError*))'));
expect(code, contains('completion:(void(^)(NSError* _Nullable))'));
expect(code, contains('completion(nil)'));
});

Expand Down Expand Up @@ -383,7 +383,7 @@ void main() {
expect(
code,
contains(
'(void)doSomething:(void(^)(ABCOutput*, NSError*))completion'));
'(void)doSomething:(void(^)(ABCOutput*, NSError* _Nullable))completion'));
});

test('gen flutter void arg header', () {
Expand All @@ -402,7 +402,7 @@ void main() {
expect(
code,
contains(
'(void)doSomething:(void(^)(ABCOutput*, NSError*))completion'));
'(void)doSomething:(void(^)(ABCOutput*, NSError* _Nullable))completion'));
expect(code, contains('channel sendMessage:nil'));
});

Expand Down
19 changes: 19 additions & 0 deletions packages/pigeon/test/version_test.dart
Original file line number Diff line number Diff line change
@@ -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());
});
}

0 comments on commit cf96cba

Please sign in to comment.