Skip to content

Commit ccaf34b

Browse files
committed
[pigeon] Fixed decoding code for null-safe classes.
1 parent f17b20a commit ccaf34b

File tree

11 files changed

+285
-6
lines changed

11 files changed

+285
-6
lines changed

packages/pigeon/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 0.1.21
2+
3+
* Fixed decode method on generated Flutter classes that use null-safety and have
4+
null values.
5+
16
## 0.1.20
27

38
* Implemented `@async` HostApi's for iOS.

packages/pigeon/lib/dart_generator.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,11 @@ void _writeFlutterApi(
178178
String _addGenericTypes(String dataType, String nullTag) {
179179
switch (dataType) {
180180
case 'List':
181-
return 'List<Object$nullTag>';
181+
return 'List<Object$nullTag>$nullTag';
182182
case 'Map':
183-
return 'Map<Object$nullTag, Object$nullTag>';
183+
return 'Map<Object$nullTag, Object$nullTag>$nullTag';
184184
default:
185-
return dataType;
185+
return '$dataType$nullTag';
186186
}
187187
}
188188

@@ -212,7 +212,7 @@ void generateDart(DartOptions opt, Root root, StringSink sink) {
212212
indent.scoped('{', '}', () {
213213
for (Field field in klass.fields) {
214214
final String datatype =
215-
'${_addGenericTypes(field.dataType, nullTag)}$nullTag';
215+
'${_addGenericTypes(field.dataType, nullTag)}';
216216
indent.writeln('$datatype ${field.name};');
217217
}
218218
if (klass.fields.isNotEmpty) {

packages/pigeon/lib/generator_tools.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import 'dart:mirrors';
88
import 'ast.dart';
99

1010
/// The current version of pigeon. This must match the version in pubspec.yaml.
11-
const String pigeonVersion = '0.1.20';
11+
const String pigeonVersion = '0.1.21';
1212

1313
/// Read all the content from [stdin] to a String.
1414
String readStdin() {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Miscellaneous
2+
*.class
3+
*.log
4+
*.pyc
5+
*.swp
6+
.DS_Store
7+
.atom/
8+
.buildlog/
9+
.history
10+
.svn/
11+
12+
# IntelliJ related
13+
*.iml
14+
*.ipr
15+
*.iws
16+
.idea/
17+
18+
# The .vscode folder contains launch configuration and tasks you configure in
19+
# VS Code which you may wish to be included in version control, so this line
20+
# is commented out by default.
21+
#.vscode/
22+
23+
# Flutter/Dart/Pub related
24+
**/doc/api/
25+
**/ios/Flutter/.last_build_id
26+
.dart_tool/
27+
.flutter-plugins
28+
.flutter-plugins-dependencies
29+
.packages
30+
.pub-cache/
31+
.pub/
32+
/build/
33+
34+
# Web related
35+
lib/generated_plugin_registrant.dart
36+
37+
# Symbolication related
38+
app.*.symbols
39+
40+
# Obfuscation related
41+
app.*.map.json
42+
43+
# Android Studio will place build artifacts here
44+
/android/app/debug
45+
/android/app/profile
46+
/android/app/release
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# This file tracks properties of this Flutter project.
2+
# Used by Flutter tool to assess capabilities and perform upgrades etc.
3+
#
4+
# This file should be version controlled and should not be manually edited.
5+
6+
version:
7+
revision: 6db3d61ed4a58ba89140d7fe1fd294b598cc29c5
8+
channel: master
9+
10+
project_type: app
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# flutter_unit_tests
2+
3+
Unit test scaffold for null safe Flutter projects.
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// Autogenerated from Pigeon (v0.1.21), do not edit directly.
2+
// See also: https://pub.dev/packages/pigeon
3+
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import
4+
// @dart = 2.12
5+
import 'dart:async';
6+
import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List;
7+
8+
import 'package:flutter/services.dart';
9+
10+
class SearchReply {
11+
String? result;
12+
String? error;
13+
14+
Object encode() {
15+
final Map<Object?, Object?> pigeonMap = <Object?, Object?>{};
16+
pigeonMap['result'] = result;
17+
pigeonMap['error'] = error;
18+
return pigeonMap;
19+
}
20+
21+
static SearchReply decode(Object message) {
22+
final Map<Object?, Object?> pigeonMap = message as Map<Object?, Object?>;
23+
return SearchReply()
24+
..result = pigeonMap['result'] as String?
25+
..error = pigeonMap['error'] as String?;
26+
}
27+
}
28+
29+
class SearchRequest {
30+
String? query;
31+
int? anInt;
32+
bool? aBool;
33+
34+
Object encode() {
35+
final Map<Object?, Object?> pigeonMap = <Object?, Object?>{};
36+
pigeonMap['query'] = query;
37+
pigeonMap['anInt'] = anInt;
38+
pigeonMap['aBool'] = aBool;
39+
return pigeonMap;
40+
}
41+
42+
static SearchRequest decode(Object message) {
43+
final Map<Object?, Object?> pigeonMap = message as Map<Object?, Object?>;
44+
return SearchRequest()
45+
..query = pigeonMap['query'] as String?
46+
..anInt = pigeonMap['anInt'] as int?
47+
..aBool = pigeonMap['aBool'] as bool?;
48+
}
49+
}
50+
51+
class Nested {
52+
SearchRequest? request;
53+
54+
Object encode() {
55+
final Map<Object?, Object?> pigeonMap = <Object?, Object?>{};
56+
pigeonMap['request'] = request == null ? null : request!.encode();
57+
return pigeonMap;
58+
}
59+
60+
static Nested decode(Object message) {
61+
final Map<Object?, Object?> pigeonMap = message as Map<Object?, Object?>;
62+
return Nested()
63+
..request = pigeonMap['request'] != null ? SearchRequest.decode(pigeonMap['request']!) : null;
64+
}
65+
}
66+
67+
abstract class FlutterSearchApi {
68+
SearchReply search(SearchRequest arg);
69+
static void setup(FlutterSearchApi? api) {
70+
{
71+
const BasicMessageChannel<Object?> channel =
72+
BasicMessageChannel<Object?>('dev.flutter.pigeon.FlutterSearchApi.search', StandardMessageCodec());
73+
if (api == null) {
74+
channel.setMessageHandler(null);
75+
} else {
76+
channel.setMessageHandler((Object? message) async {
77+
assert(message != null, 'Argument for dev.flutter.pigeon.FlutterSearchApi.search was null. Expected SearchRequest.');
78+
final SearchRequest input = SearchRequest.decode(message!);
79+
final SearchReply output = api.search(input);
80+
return output.encode();
81+
});
82+
}
83+
}
84+
}
85+
}
86+
87+
class NestedApi {
88+
Future<SearchReply> search(Nested arg) async {
89+
final Object encoded = arg.encode();
90+
const BasicMessageChannel<Object?> channel =
91+
BasicMessageChannel<Object?>('dev.flutter.pigeon.NestedApi.search', StandardMessageCodec());
92+
final Map<Object?, Object?>? replyMap = await channel.send(encoded) as Map<Object?, Object?>?;
93+
if (replyMap == null) {
94+
throw PlatformException(
95+
code: 'channel-error',
96+
message: 'Unable to establish connection on channel.',
97+
details: null,
98+
);
99+
} else if (replyMap['error'] != null) {
100+
final Map<Object?, Object?> error = replyMap['error'] as Map<Object?, Object?>;
101+
throw PlatformException(
102+
code: error['code'] as String,
103+
message: error['message'] as String?,
104+
details: error['details'],
105+
);
106+
} else {
107+
return SearchReply.decode(replyMap['result']!);
108+
}
109+
}
110+
}
111+
112+
class Api {
113+
Future<void> initialize() async {
114+
const BasicMessageChannel<Object?> channel =
115+
BasicMessageChannel<Object?>('dev.flutter.pigeon.Api.initialize', StandardMessageCodec());
116+
final Map<Object?, Object?>? replyMap = await channel.send(null) as Map<Object?, Object?>?;
117+
if (replyMap == null) {
118+
throw PlatformException(
119+
code: 'channel-error',
120+
message: 'Unable to establish connection on channel.',
121+
details: null,
122+
);
123+
} else if (replyMap['error'] != null) {
124+
final Map<Object?, Object?> error = replyMap['error'] as Map<Object?, Object?>;
125+
throw PlatformException(
126+
code: error['code'] as String,
127+
message: error['message'] as String?,
128+
details: error['details'],
129+
);
130+
} else {
131+
// noop
132+
}
133+
}
134+
135+
Future<SearchReply> search(SearchRequest arg) async {
136+
final Object encoded = arg.encode();
137+
const BasicMessageChannel<Object?> channel =
138+
BasicMessageChannel<Object?>('dev.flutter.pigeon.Api.search', StandardMessageCodec());
139+
final Map<Object?, Object?>? replyMap = await channel.send(encoded) as Map<Object?, Object?>?;
140+
if (replyMap == null) {
141+
throw PlatformException(
142+
code: 'channel-error',
143+
message: 'Unable to establish connection on channel.',
144+
details: null,
145+
);
146+
} else if (replyMap['error'] != null) {
147+
final Map<Object?, Object?> error = replyMap['error'] as Map<Object?, Object?>;
148+
throw PlatformException(
149+
code: error['code'] as String,
150+
message: error['message'] as String?,
151+
details: error['details'],
152+
);
153+
} else {
154+
return SearchReply.decode(replyMap['result']!);
155+
}
156+
}
157+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: flutter_unit_tests
2+
description: Unit test scaffold for null safe Flutter projects.
3+
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
4+
version: 1.0.0+1
5+
environment:
6+
sdk: ">=2.12.0 <3.0.0"
7+
8+
dependencies:
9+
flutter:
10+
sdk: flutter
11+
12+
dev_dependencies:
13+
flutter_test:
14+
sdk: flutter
15+
16+
flutter:
17+
uses-material-design: true
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2020 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:flutter_unit_tests/null_safe_pigeon.dart';
6+
import 'package:flutter_test/flutter_test.dart';
7+
8+
void main() {
9+
test('with values filled', () {
10+
final SearchReply reply = SearchReply()
11+
..result = 'foo'
12+
..error = 'bar';
13+
final Object encoded = reply.encode();
14+
final SearchReply decoded = SearchReply.decode(encoded);
15+
expect(reply.result, decoded.result);
16+
expect(reply.error, decoded.error);
17+
});
18+
19+
test('with null value', () {
20+
final SearchReply reply = SearchReply()
21+
..result = 'foo'
22+
..error = null;
23+
final Object encoded = reply.encode();
24+
final SearchReply decoded = SearchReply.decode(encoded);
25+
expect(reply.result, decoded.result);
26+
expect(reply.error, decoded.error);
27+
});
28+
}

packages/pigeon/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: pigeon
2-
version: 0.1.20 # This must match the version in lib/generator_tools.dart
2+
version: 0.1.21 # This must match the version in lib/generator_tools.dart
33
description: Code generator tool to make communication between Flutter and the host platform type-safe and easier.
44
homepage: https://github.com/flutter/packages/tree/master/packages/pigeon
55
dependencies:

packages/pigeon/run_tests.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,19 @@ pub run test test/
110110
###############################################################################
111111
pub run pigeon 1> /dev/null
112112

113+
###############################################################################
114+
# Run unit tests on generated Dart code.
115+
###############################################################################
116+
pushd $PWD
117+
pub run pigeon \
118+
--input pigeons/message.dart \
119+
--dart_null_safety \
120+
--dart_out platform_tests/flutter_null_safe_unit_tests/lib/null_safe_pigeon.dart
121+
cd platform_tests/flutter_null_safe_unit_tests
122+
flutter pub get
123+
flutter test test/null_safe_test.dart
124+
popd
125+
113126
###############################################################################
114127
# Mock handler flutter tests.
115128
###############################################################################

0 commit comments

Comments
 (0)