Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/pigeon/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 26.1.9

* [dart] Reduces much duplication in reply-handling code.

## 26.1.8

* Makes some internal class constructors constant.
Expand Down
97 changes: 44 additions & 53 deletions packages/pigeon/example/app/lib/src/messages.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,29 @@ import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';

PlatformException _createConnectionError(String channelName) {
return PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel: "$channelName".',
);
Object? _extractReplyValueOrThrow(
List<Object?>? replyList,
String channelName, {
required bool isNullValid,
}) {
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel: "$channelName".',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
}
return replyList.firstOrNull;
}

List<Object?> wrapResponse({
Expand Down Expand Up @@ -162,22 +180,13 @@ class ExampleHostApi {
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else if (pigeonVar_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (pigeonVar_replyList[0] as String?)!;
}

final Object pigeonVar_replyValue = _extractReplyValueOrThrow(
pigeonVar_replyList,
pigeonVar_channelName,
isNullValid: false,
)!;
return pigeonVar_replyValue as String;
}

Future<int> add(int a, int b) async {
Expand All @@ -192,22 +201,13 @@ class ExampleHostApi {
<Object?>[a, b],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else if (pigeonVar_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (pigeonVar_replyList[0] as int?)!;
}

final Object pigeonVar_replyValue = _extractReplyValueOrThrow(
pigeonVar_replyList,
pigeonVar_channelName,
isNullValid: false,
)!;
return pigeonVar_replyValue as int;
}

Future<bool> sendMessage(MessageData message) async {
Expand All @@ -222,22 +222,13 @@ class ExampleHostApi {
<Object?>[message],
);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else if (pigeonVar_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (pigeonVar_replyList[0] as bool?)!;
}

final Object pigeonVar_replyValue = _extractReplyValueOrThrow(
pigeonVar_replyList,
pigeonVar_channelName,
isNullValid: false,
)!;
return pigeonVar_replyValue as bool;
}
}

Expand Down
117 changes: 70 additions & 47 deletions packages/pigeon/lib/src/dart/dart_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ class DartGenerator extends StructuredGenerator<InternalDartOptions> {
EnumeratedType customType,
int nonSerializedClassCount,
) {
indent.writeln('case ${customType.offset(nonSerializedClassCount)}: ');
indent.writeln('case ${customType.offset(nonSerializedClassCount)}:');
indent.nest(1, () {
if (customType.type == CustomTypes.customClass) {
if (customType.offset(nonSerializedClassCount) ==
Expand Down Expand Up @@ -1116,7 +1116,7 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger;
required String dartPackageName,
}) {
if (root.containsHostApi || root.containsProxyApi) {
_writeCreateConnectionError(indent);
_writeExtractReplyValueOrThrow(indent);
}
if (root.containsFlutterApi ||
root.containsProxyApi ||
Expand Down Expand Up @@ -1173,15 +1173,38 @@ bool _deepEquals(Object? a, Object? b) {
''');
}

void _writeCreateConnectionError(Indent indent) {
static void _writeExtractReplyValueOrThrow(Indent indent) {
indent.newln();
indent.format('''
PlatformException _createConnectionError(String channelName) {
\treturn PlatformException(
\t\tcode: 'channel-error',
\t\tmessage: 'Unable to establish connection on channel: "\$channelName".',
\t);
}''');
Object? _extractReplyValueOrThrow(
\t\tList<Object?>? replyList,
\t\tString channelName, {
\t\trequired bool isNullValid,
}) {
\tif (replyList == null) {
\t\tthrow PlatformException(
\t\t\tcode: 'channel-error',
\t\t\tmessage: 'Unable to establish connection on channel: "\$channelName".',
\t\t);
\t} else if (replyList.length > 1) {
\t\tthrow PlatformException(
\t\t\tcode: replyList[0]! as String,
\t\t\tmessage: replyList[1] as String?,
\t\t\tdetails: replyList[2],
Comment thread
srawlins marked this conversation as resolved.
\t\t);''');
// On iOS we can return nil from functions to accommodate error
// handling. Returning a nil value and not returning an error is an
// exception.
indent.format('''
\t} else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) {
\t\tthrow PlatformException(
\t\t\tcode: 'null-error',
\t\t\tmessage: 'Host platform returned null value for non-null return value.',
\t\t);
\t}
\treturn replyList.firstOrNull;
}
''');
}

void _writeCodecOverflowUtilities(Indent indent, List<EnumeratedType> types) {
Expand Down Expand Up @@ -1298,22 +1321,6 @@ if (wrapped == null) {
indent.writeln('binaryMessenger: ${varNamePrefix}binaryMessenger,');
},
);
final String returnTypeName = _makeGenericTypeArguments(returnType);
final String genericCastCall = _makeGenericCastCall(returnType);
const accessor = '${varNamePrefix}replyList[0]';
// Avoid warnings from pointlessly casting to `Object?`.
final nullablyTypedAccessor = returnTypeName == 'Object'
? accessor
: '($accessor as $returnTypeName?)';
final nullHandler = returnType.isNullable
? (genericCastCall.isEmpty ? '' : '?')
: '!';
var returnStatement = 'return';
if (!returnType.isVoid) {
returnStatement =
'$returnStatement $nullablyTypedAccessor$nullHandler$genericCastCall';
}
returnStatement = '$returnStatement;';

const sendFutureVar = '${varNamePrefix}sendFuture';
indent.writeln(
Expand All @@ -1329,29 +1336,45 @@ if (wrapped == null) {

indent.format('''
final ${varNamePrefix}replyList = await $sendFutureVar as List<Object?>?;
if (${varNamePrefix}replyList == null) {
\tthrow _createConnectionError(${varNamePrefix}channelName);
} else if (${varNamePrefix}replyList.length > 1) {
\tthrow PlatformException(
\t\tcode: ${varNamePrefix}replyList[0]! as String,
\t\tmessage: ${varNamePrefix}replyList[1] as String?,
\t\tdetails: ${varNamePrefix}replyList[2],
\t);''');
// On iOS we can return nil from functions to accommodate error
// handling. Returning a nil value and not returning an error is an
// exception.
if (!returnType.isNullable && !returnType.isVoid) {
indent.format('''
} else if (${varNamePrefix}replyList[0] == null) {
\tthrow PlatformException(
\t\tcode: 'null-error',
\t\tmessage: 'Host platform returned null value for non-null return value.',
\t);''');
''');
final validateCall =
'''
_extractReplyValueOrThrow(
\t\t${varNamePrefix}replyList,
\t\t${varNamePrefix}channelName,
\t\tisNullValid: ${returnType.isNullable || returnType.isVoid},
)
''';
if (returnType.isVoid) {
indent.format('$validateCall;');
} else {
const accessor = '${varNamePrefix}replyValue';
if (returnType.isNullable) {
indent.format('final Object? $accessor = $validateCall;');
} else {
indent.format('final Object $accessor = $validateCall!;');
}
String returnTypeName = _makeGenericTypeArguments(returnType);
if (returnType.isNullable) {
returnTypeName = '$returnTypeName?';
}
final String genericCastCall = _makeGenericCastCall(returnType);

if (genericCastCall.isEmpty) {
final castedAccessor = returnType.baseName == 'Object'
? accessor
: '$accessor as $returnTypeName';
indent.format('return $castedAccessor;');
} else {
final nullablyTypedAccessor = returnType.baseName == 'Object'
? accessor
: '($accessor as $returnTypeName)';
final nullHandler = returnType.isNullable ? '?' : '';
indent.format(
'return $nullablyTypedAccessor$nullHandler$genericCastCall;',
);
}
}
indent.format('''
} else {
\t$returnStatement
}''');

if (!insideAsyncMethod) {
indent.dec();
Expand Down
2 changes: 1 addition & 1 deletion packages/pigeon/lib/src/generator_tools.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import 'generator.dart';
/// The current version of pigeon.
///
/// This must match the version in pubspec.yaml.
const String pigeonVersion = '26.1.8';
const String pigeonVersion = '26.1.9';

/// Read all the content from [stdin] to a String.
String readStdin() {
Expand Down
Loading
Loading