Skip to content
Draft
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
6 changes: 6 additions & 0 deletions packages/pigeon/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 27.0.0

* **BREAKING CHANGE**: Adds support for acronyms in snake_case conversion in generators. This may change the generated output for symbols containing acronyms.
* Refactors response handling across all generators to use a single `wrapResponse` method instead of `wrapResult` and `wrapError`.
* Cleans up repeated code and adds an error class and prologue to the base `Generator` class.

## 26.3.4

* [kotlin] Updates generated error class to inherit from `RuntimeException`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,38 @@ static int pigeonDeepHashCode(Object value) {
return value.hashCode();
}

@NonNull
protected static ArrayList<Object> wrapResponse(
@Nullable Object result, @Nullable Throwable error) {
ArrayList<Object> response = new ArrayList<>();
if (error != null) {
if (error instanceof FlutterError) {
FlutterError flutterError = (FlutterError) error;
response.add(flutterError.code);
response.add(flutterError.getMessage());
response.add(flutterError.details);
} else {
response.add(error.toString());
response.add(error.getClass().getSimpleName());
response.add(
"Cause: " + error.getCause() + ", Stacktrace: " + Log.getStackTraceString(error));
}
} else {
response.add(result);
}
return response;
}

@NonNull
protected static FlutterError createConnectionError(@NonNull String channelName) {
return new FlutterError(
"channel-error", "Unable to establish connection on channel: " + channelName + ".", "");
}

@Target(METHOD)
@Retention(CLASS)
@interface CanIgnoreReturnValue {}

/** Error class for passing custom error details to Flutter via a thrown PlatformException. */
public static class FlutterError extends RuntimeException {

Expand All @@ -201,33 +233,6 @@ public FlutterError(@NonNull String code, @Nullable String message, @Nullable Ob
}
}

@NonNull
protected static ArrayList<Object> wrapError(@NonNull Throwable exception) {
ArrayList<Object> errorList = new ArrayList<>(3);
if (exception instanceof FlutterError) {
FlutterError error = (FlutterError) exception;
errorList.add(error.code);
errorList.add(error.getMessage());
errorList.add(error.details);
} else {
errorList.add(exception.toString());
errorList.add(exception.getClass().getSimpleName());
errorList.add(
"Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception));
}
return errorList;
}

@NonNull
protected static FlutterError createConnectionError(@NonNull String channelName) {
return new FlutterError(
"channel-error", "Unable to establish connection on channel: " + channelName + ".", "");
}

@Target(METHOD)
@Retention(CLASS)
@interface CanIgnoreReturnValue {}

public enum Code {
ONE(0),
TWO(1);
Expand Down Expand Up @@ -472,14 +477,12 @@ static void setUp(
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<>();
try {
String output = api.getHostLanguage();
wrapped.add(0, output);
reply.reply(wrapResponse(output, null));
} catch (Throwable exception) {
wrapped = wrapError(exception);
reply.reply(wrapResponse(null, exception));
}
reply.reply(wrapped);
});
} else {
channel.setMessageHandler(null);
Expand All @@ -495,17 +498,15 @@ static void setUp(
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<>();
ArrayList<Object> args = (ArrayList<Object>) message;
Long aArg = (Long) args.get(0);
Long bArg = (Long) args.get(1);
try {
Long output = api.add(aArg, bArg);
wrapped.add(0, output);
reply.reply(wrapResponse(output, null));
} catch (Throwable exception) {
wrapped = wrapError(exception);
reply.reply(wrapResponse(null, exception));
}
reply.reply(wrapped);
});
} else {
channel.setMessageHandler(null);
Expand All @@ -521,19 +522,16 @@ static void setUp(
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<>();
ArrayList<Object> args = (ArrayList<Object>) message;
MessageData messageArg = (MessageData) args.get(0);
Result<Boolean> resultCallback =
new Result<Boolean>() {
public void success(Boolean result) {
wrapped.add(0, result);
reply.reply(wrapped);
reply.reply(wrapResponse(result, null));
}

public void error(Throwable error) {
ArrayList<Object> wrappedError = wrapError(error);
reply.reply(wrappedError);
reply.reply(wrapResponse(null, error));
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@ private object MessagesPigeonUtils {
"channel-error", "Unable to establish connection on channel: '$channelName'.", "")
}

fun wrapResult(result: Any?): List<Any?> {
return listOf(result)
}

fun wrapError(exception: Throwable): List<Any?> {
return if (exception is FlutterError) {
listOf(exception.code, exception.message, exception.details)
fun wrapResponse(result: Any?, error: Throwable?): List<Any?> {
return if (error != null) {
if (error is FlutterError) {
listOf(error.code, error.message, error.details)
} else {
listOf(
error.javaClass.simpleName,
error.toString(),
"Cause: " + error.cause + ", Stacktrace: " + Log.getStackTraceString(error))
}
} else {
listOf(
exception.javaClass.simpleName,
exception.toString(),
"Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception))
listOf(result)
}
}

Expand Down Expand Up @@ -312,9 +312,9 @@ interface ExampleHostApi {
channel.setMessageHandler { _, reply ->
val wrapped: List<Any?> =
try {
listOf(api.getHostLanguage())
MessagesPigeonUtils.wrapResponse(api.getHostLanguage(), null)
} catch (exception: Throwable) {
MessagesPigeonUtils.wrapError(exception)
MessagesPigeonUtils.wrapResponse(null, exception)
}
reply.reply(wrapped)
}
Expand All @@ -335,9 +335,9 @@ interface ExampleHostApi {
val bArg = args[1] as Long
val wrapped: List<Any?> =
try {
listOf(api.add(aArg, bArg))
MessagesPigeonUtils.wrapResponse(api.add(aArg, bArg), null)
} catch (exception: Throwable) {
MessagesPigeonUtils.wrapError(exception)
MessagesPigeonUtils.wrapResponse(null, exception)
}
reply.reply(wrapped)
}
Expand All @@ -358,10 +358,10 @@ interface ExampleHostApi {
api.sendMessage(messageArg) { result: Result<Boolean> ->
val error = result.exceptionOrNull()
if (error != null) {
reply.reply(MessagesPigeonUtils.wrapError(error))
reply.reply(MessagesPigeonUtils.wrapResponse(null, error))
} else {
val data = result.getOrNull()
reply.reply(MessagesPigeonUtils.wrapResult(data))
reply.reply(MessagesPigeonUtils.wrapResponse(data, null))
}
}
}
Expand Down
90 changes: 45 additions & 45 deletions packages/pigeon/example/app/ios/Runner/Messages.g.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,48 +14,30 @@ import Foundation
#error("Unsupported platform.")
#endif

/// Error class for passing custom error details to Dart side.
final class PigeonError: Error {
let code: String
let message: String?
let details: Sendable?

init(code: String, message: String?, details: Sendable?) {
self.code = code
self.message = message
self.details = details
}

var localizedDescription: String {
return
"PigeonError(code: \(code), message: \(message ?? "<nil>"), details: \(details ?? "<nil>")"
}
}

private func wrapResult(_ result: Any?) -> [Any?] {
return [result]
}

private func wrapError(_ error: Any) -> [Any?] {
if let pigeonError = error as? PigeonError {
return [
pigeonError.code,
pigeonError.message,
pigeonError.details,
]
}
if let flutterError = error as? FlutterError {
private func wrapResponse(_ result: Any?, _ error: Any?) -> [Any?] {
if let error = error {
if let pigeonError = error as? PigeonError {
return [
pigeonError.code,
pigeonError.message,
pigeonError.details,
]
}
if let flutterError = error as? FlutterError {
return [
flutterError.code,
flutterError.message,
flutterError.details,
]
}
return [
flutterError.code,
flutterError.message,
flutterError.details,
"\(error)",
"\(Swift.type(of: error))",
"Stacktrace: \(Thread.callStackSymbols)",
]
} else {
return [result]
}
return [
"\(error)",
"\(Swift.type(of: error))",
"Stacktrace: \(Thread.callStackSymbols)",
]
}

private func createConnectionError(withChannelName channelName: String) -> PigeonError {
Expand Down Expand Up @@ -182,6 +164,24 @@ func deepHashMessages(value: Any?, hasher: inout Hasher) {
}
}

/// Error class for passing custom error details to Dart side.
final class PigeonError: Error {
let code: String
let message: String?
let details: Sendable?

init(code: String, message: String?, details: Sendable?) {
self.code = code
self.message = message
self.details = details
}

var localizedDescription: String {
return
"PigeonError(code: \(code), message: \(message ?? "<nil>"), details: \(details ?? "<nil>")"
}
}

enum Code: Int {
case one = 0
case two = 1
Expand Down Expand Up @@ -302,9 +302,9 @@ class ExampleHostApiSetup {
getHostLanguageChannel.setMessageHandler { _, reply in
do {
let result = try api.getHostLanguage()
reply(wrapResult(result))
reply(wrapResponse(result, nil))
} catch {
reply(wrapError(error))
reply(wrapResponse(nil, error))
}
}
} else {
Expand All @@ -320,9 +320,9 @@ class ExampleHostApiSetup {
let bArg = args[1] as! Int64
do {
let result = try api.add(aArg, to: bArg)
reply(wrapResult(result))
reply(wrapResponse(result, nil))
} catch {
reply(wrapError(error))
reply(wrapResponse(nil, error))
}
}
} else {
Expand All @@ -338,9 +338,9 @@ class ExampleHostApiSetup {
api.sendMessage(message: messageArg) { result in
switch result {
case .success(let res):
reply(wrapResult(res))
reply(wrapResponse(res, nil))
case .failure(let error):
reply(wrapError(error))
reply(wrapResponse(nil, error))
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion packages/pigeon/example/app/linux/messages.g.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1008,7 +1008,9 @@ pigeon_example_package_message_flutter_api_flutter_method_response_new(
self->error = fl_value_ref(response);
} else {
FlValue* value = fl_value_get_list_value(response, 0);
self->return_value = fl_value_ref(value);
if (value != nullptr) {
self->return_value = fl_value_ref(value);
}
}
return self;
}
Expand Down
Loading
Loading