diff --git a/packages/pigeon/CHANGELOG.md b/packages/pigeon/CHANGELOG.md index 3b9ee79da122..ed0b95a82fa9 100644 --- a/packages/pigeon/CHANGELOG.md +++ b/packages/pigeon/CHANGELOG.md @@ -1,5 +1,7 @@ -## NEXT +## 26.4.0 +* Overrides `toString` (or equivalent) methods on generated data classes. +* [swift] Updates `isNullish` to handle double nested `Any?` values. * Updates minimum supported SDK version to Flutter 3.38/Dart 3.10. ## 26.3.4 @@ -919,7 +921,7 @@ ## 3.0.3 -* Adds ability for generators to do AST validation. This can help generators +* Adds ability for generators to do AST validation. This can help generators without complete implementations to report gaps in coverage. ## 3.0.2 @@ -1082,11 +1084,11 @@ `dart:mirrors` doesn't support null-safe code so there were a class of features we couldn't implement without this migration. * **BREAKING CHANGE** - the `configurePigeon` function has been migrated to a - `@ConfigurePigeon` annotation. See `./pigeons/message.dart` for an example. + `@ConfigurePigeon` annotation. See `./pigeons/message.dart` for an example. The annotation can be attached to anything in the file to take effect. * **BREAKING CHANGE** - Now Pigeon files must be in one file per invocation of - Pigeon. For example, the classes your APIs use must be in the same file as - your APIs. If your Pigeon file imports another source file, it won't actually + Pigeon. For example, the classes your APIs use must be in the same file as + your APIs. If your Pigeon file imports another source file, it won't actually import it. ## 0.2.4 @@ -1108,10 +1110,10 @@ ## 0.2.0 -* **BREAKING CHANGE** - Pigeon files must be null-safe now. That means the +* **BREAKING CHANGE** - Pigeon files must be null-safe now. That means the fields inside of the classes must be declared nullable ( [non-null fields](https://github.com/flutter/flutter/issues/59118) aren't yet - supported). Migration example: + supported). Migration example: ```dart // Version 0.1.x @@ -1127,7 +1129,7 @@ class Foo { } ``` -* **BREAKING CHANGE** - The default output from Pigeon is now null-safe. If you +* **BREAKING CHANGE** - The default output from Pigeon is now null-safe. If you want non-null-safe code you must provide the `--no-dart_null_safety` flag. * The Pigeon source code is now null-safe. * Fixed niladic non-value returning async functions in the Java generator. @@ -1213,7 +1215,7 @@ class Foo { ## 0.1.8 -* Started spawning pigeon_lib in an isolate instead of a subprocess. The +* Started spawning pigeon_lib in an isolate instead of a subprocess. The subprocess could have lead to errors if the dart version on $PATH didn't match the one that comes with flutter. diff --git a/packages/pigeon/CONTRIBUTING.md b/packages/pigeon/CONTRIBUTING.md index 41ead7842651..304d1a8c7906 100644 --- a/packages/pigeon/CONTRIBUTING.md +++ b/packages/pigeon/CONTRIBUTING.md @@ -3,7 +3,7 @@ ## Description Pigeon is a code generation tool that adds type safety to Flutter’s Platform -Channels. This document serves as an overview of how it functions to help +Channels. This document serves as an overview of how it functions to help people who would like to contribute to the project. ## Source Index @@ -32,15 +32,15 @@ Pigeon has 3 types of tests; you'll find them all in * Unit tests - These are the fastest tests that are just typical unit tests, they may be generating code and checking it against a regular expression to - see if it's correct. Example: + see if it's correct. Example: [dart_generator_test.dart](./test/dart_generator_test.dart) * Compilation tests - These tests generate code, then attempt to compile that - code. These are tests are much slower than unit tests, but not as slow as - integration tests. These tests are typically run against the Pigeon files in + code. These are tests are much slower than unit tests, but not as slow as + integration tests. These tests are typically run against the Pigeon files in [pigeons](./pigeons). * Integration tests - These tests generate code, then compile the generated - code, then execute the generated code. It can be thought of as unit-tests run - against the generated code. Examples: [platform_tests](./platform_tests) + code, then execute the generated code. It can be thought of as unit-tests run + against the generated code. Examples: [platform_tests](./platform_tests) For local testing, always use `test.dart` rather than `run_tests.dart`, as `run_tests.dart` is specifically a CI entrypoint. When iterating on a specific diff --git a/packages/pigeon/README.md b/packages/pigeon/README.md index 0e5b91c25128..1029d51f3be9 100644 --- a/packages/pigeon/README.md +++ b/packages/pigeon/README.md @@ -101,7 +101,7 @@ to the api to allow for multiple instances to be created and operate in parallel 1) Custom classes used by APIs are defined as classes with fields of the supported datatypes (see the supported Datatypes section). 1) APIs should be defined as an `abstract class` with either `@HostApi()` or - `@FlutterApi()` as metadata. `@HostApi()` being for procedures that are defined + `@FlutterApi()` as metadata. `@HostApi()` being for procedures that are defined on the host platform and the `@FlutterApi()` for procedures that are defined in Dart. 1) Method declarations on the API classes should have arguments and a return value whose types are defined in the file, are supported datatypes, or are @@ -150,7 +150,7 @@ to the api to allow for multiple instances to be created and operate in parallel ### Calling into Flutter from the host platform Pigeon also supports calling in the opposite direction. The steps are similar -but reversed. For more information look at the annotation `@FlutterApi()` which +but reversed. For more information look at the annotation `@FlutterApi()` which denotes APIs that live in Flutter but are invoked from the host platform. [Example](./example/README.md#FlutterApi_Example). diff --git a/packages/pigeon/example/README.md b/packages/pigeon/example/README.md index b54f7c08737e..8a219371918a 100644 --- a/packages/pigeon/example/README.md +++ b/packages/pigeon/example/README.md @@ -62,7 +62,7 @@ enum Code { one, two } class MessageData { MessageData({required this.code, required this.data}); String? name; - String? description; + String? messageDescription; Code code; Map data; } @@ -107,7 +107,7 @@ Future sendMessage(String messageText) { final message = MessageData( code: Code.one, data: {'header': 'this is a header'}, - description: 'uri text', + messageDescription: 'uri text', ); try { return _api.sendMessage(message); diff --git a/packages/pigeon/example/app/android/app/src/main/java/io/flutter/plugins/Messages.java b/packages/pigeon/example/app/android/app/src/main/java/io/flutter/plugins/Messages.java index b649738648ab..75a676627eca 100644 --- a/packages/pigeon/example/app/android/app/src/main/java/io/flutter/plugins/Messages.java +++ b/packages/pigeon/example/app/android/app/src/main/java/io/flutter/plugins/Messages.java @@ -251,14 +251,14 @@ public void setName(@Nullable String setterArg) { this.name = setterArg; } - private @Nullable String description; + private @Nullable String messageDescription; - public @Nullable String getDescription() { - return description; + public @Nullable String getMessageDescription() { + return messageDescription; } - public void setDescription(@Nullable String setterArg) { - this.description = setterArg; + public void setMessageDescription(@Nullable String setterArg) { + this.messageDescription = setterArg; } private @NonNull Code code; @@ -300,17 +300,34 @@ public boolean equals(Object o) { } MessageData that = (MessageData) o; return pigeonDeepEquals(name, that.name) - && pigeonDeepEquals(description, that.description) + && pigeonDeepEquals(messageDescription, that.messageDescription) && pigeonDeepEquals(code, that.code) && pigeonDeepEquals(data, that.data); } @Override public int hashCode() { - Object[] fields = new Object[] {getClass(), name, description, code, data}; + Object[] fields = new Object[] {getClass(), name, messageDescription, code, data}; return pigeonDeepHashCode(fields); } + @Override + public String toString() { + return "MessageData{" + + "name=" + + name + + ", " + + "messageDescription=" + + messageDescription + + ", " + + "code=" + + code + + ", " + + "data=" + + data + + "}"; + } + public static final class Builder { private @Nullable String name; @@ -321,11 +338,11 @@ public static final class Builder { return this; } - private @Nullable String description; + private @Nullable String messageDescription; @CanIgnoreReturnValue - public @NonNull Builder setDescription(@Nullable String setterArg) { - this.description = setterArg; + public @NonNull Builder setMessageDescription(@Nullable String setterArg) { + this.messageDescription = setterArg; return this; } @@ -348,7 +365,7 @@ public static final class Builder { public @NonNull MessageData build() { MessageData pigeonReturn = new MessageData(); pigeonReturn.setName(name); - pigeonReturn.setDescription(description); + pigeonReturn.setMessageDescription(messageDescription); pigeonReturn.setCode(code); pigeonReturn.setData(data); return pigeonReturn; @@ -359,7 +376,7 @@ public static final class Builder { ArrayList toList() { ArrayList toListResult = new ArrayList<>(4); toListResult.add(name); - toListResult.add(description); + toListResult.add(messageDescription); toListResult.add(code); toListResult.add(data); return toListResult; @@ -369,8 +386,8 @@ ArrayList toList() { MessageData pigeonResult = new MessageData(); Object name = pigeonVar_list.get(0); pigeonResult.setName((String) name); - Object description = pigeonVar_list.get(1); - pigeonResult.setDescription((String) description); + Object messageDescription = pigeonVar_list.get(1); + pigeonResult.setMessageDescription((String) messageDescription); Object code = pigeonVar_list.get(2); pigeonResult.setCode((Code) code); Object data = pigeonVar_list.get(3); diff --git a/packages/pigeon/example/app/android/app/src/main/kotlin/dev/flutter/pigeon_example_app/EventChannelMessages.g.kt b/packages/pigeon/example/app/android/app/src/main/kotlin/dev/flutter/pigeon_example_app/EventChannelMessages.g.kt index 9029c9425018..c2e8d93cf99a 100644 --- a/packages/pigeon/example/app/android/app/src/main/kotlin/dev/flutter/pigeon_example_app/EventChannelMessages.g.kt +++ b/packages/pigeon/example/app/android/app/src/main/kotlin/dev/flutter/pigeon_example_app/EventChannelMessages.g.kt @@ -194,6 +194,10 @@ data class IntEvent(val data: Long) : PlatformEvent() { result = 31 * result + EventChannelMessagesPigeonUtils.deepHash(this.data) return result } + + override fun toString(): String { + return "IntEvent(data=$data)" + } } /** Generated class from Pigeon that represents data sent in messages. */ @@ -227,6 +231,10 @@ data class StringEvent(val data: String) : PlatformEvent() { result = 31 * result + EventChannelMessagesPigeonUtils.deepHash(this.data) return result } + + override fun toString(): String { + return "StringEvent(data=$data)" + } } private open class EventChannelMessagesPigeonCodec : StandardMessageCodec() { diff --git a/packages/pigeon/example/app/android/app/src/main/kotlin/dev/flutter/pigeon_example_app/Messages.g.kt b/packages/pigeon/example/app/android/app/src/main/kotlin/dev/flutter/pigeon_example_app/Messages.g.kt index 9557d8c13297..e81766320f31 100644 --- a/packages/pigeon/example/app/android/app/src/main/kotlin/dev/flutter/pigeon_example_app/Messages.g.kt +++ b/packages/pigeon/example/app/android/app/src/main/kotlin/dev/flutter/pigeon_example_app/Messages.g.kt @@ -207,24 +207,24 @@ enum class Code(val raw: Int) { /** Generated class from Pigeon that represents data sent in messages. */ data class MessageData( val name: String? = null, - val description: String? = null, + val messageDescription: String? = null, val code: Code, val data: Map ) { companion object { fun fromList(pigeonVar_list: List): MessageData { val name = pigeonVar_list[0] as String? - val description = pigeonVar_list[1] as String? + val messageDescription = pigeonVar_list[1] as String? val code = pigeonVar_list[2] as Code val data = pigeonVar_list[3] as Map - return MessageData(name, description, code, data) + return MessageData(name, messageDescription, code, data) } } fun toList(): List { return listOf( name, - description, + messageDescription, code, data, ) @@ -239,7 +239,7 @@ data class MessageData( } val other = other as MessageData return MessagesPigeonUtils.deepEquals(this.name, other.name) && - MessagesPigeonUtils.deepEquals(this.description, other.description) && + MessagesPigeonUtils.deepEquals(this.messageDescription, other.messageDescription) && MessagesPigeonUtils.deepEquals(this.code, other.code) && MessagesPigeonUtils.deepEquals(this.data, other.data) } @@ -247,11 +247,15 @@ data class MessageData( override fun hashCode(): Int { var result = javaClass.hashCode() result = 31 * result + MessagesPigeonUtils.deepHash(this.name) - result = 31 * result + MessagesPigeonUtils.deepHash(this.description) + result = 31 * result + MessagesPigeonUtils.deepHash(this.messageDescription) result = 31 * result + MessagesPigeonUtils.deepHash(this.code) result = 31 * result + MessagesPigeonUtils.deepHash(this.data) return result } + + override fun toString(): String { + return "MessageData(name=$name, messageDescription=$messageDescription, code=$code, data=$data)" + } } private open class MessagesPigeonCodec : StandardMessageCodec() { diff --git a/packages/pigeon/example/app/ios/Runner/EventChannelMessages.g.swift b/packages/pigeon/example/app/ios/Runner/EventChannelMessages.g.swift index 70cab0a27bec..16d0bad07c6b 100644 --- a/packages/pigeon/example/app/ios/Runner/EventChannelMessages.g.swift +++ b/packages/pigeon/example/app/ios/Runner/EventChannelMessages.g.swift @@ -14,122 +14,132 @@ import Foundation #error("Unsupported platform.") #endif -private func isNullish(_ value: Any?) -> Bool { - return value is NSNull || value == nil -} +enum EventChannelMessagesPigeonInternal { + static func isNullish(_ value: Any?) -> Bool { + guard let innerValue = value else { + return true + } -private func nilOrValue(_ value: Any?) -> T? { - if value is NSNull { return nil } - return value as! T? -} + if case Optional.some(Optional.none) = value { + return true + } -private func doubleEqualsEventChannelMessages(_ lhs: Double, _ rhs: Double) -> Bool { - return (lhs.isNaN && rhs.isNaN) || lhs == rhs -} + return innerValue is NSNull + } + static func doubleEquals(_ lhs: Double, _ rhs: Double) -> Bool { + return (lhs.isNaN && rhs.isNaN) || lhs == rhs + } -private func doubleHashEventChannelMessages(_ value: Double, _ hasher: inout Hasher) { - if value.isNaN { - hasher.combine(0x7FF8_0000_0000_0000) - } else { - // Normalize -0.0 to 0.0 - hasher.combine(value == 0 ? 0 : value) + static func doubleHash(_ value: Double, _ hasher: inout Hasher) { + if value.isNaN { + hasher.combine(0x7FF8_0000_0000_0000) + } else { + // Normalize -0.0 to 0.0 + hasher.combine(value == 0 ? 0 : value) + } } -} -func deepEqualsEventChannelMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { - let cleanLhs = nilOrValue(lhs) as Any? - let cleanRhs = nilOrValue(rhs) as Any? - switch (cleanLhs, cleanRhs) { - case (nil, nil): - return true + static func deepEquals(_ lhs: Any?, _ rhs: Any?) -> Bool { + let cleanLhs = nilOrValue(lhs) as Any? + let cleanRhs = nilOrValue(rhs) as Any? + switch (cleanLhs, cleanRhs) { + case (nil, nil): + return true - case (nil, _), (_, nil): - return false + case (nil, _), (_, nil): + return false - case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs: - return true + case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs: + return true - case is (Void, Void): - return true + case is (Void, Void): + return true - case (let lhsArray, let rhsArray) as ([Any?], [Any?]): - guard lhsArray.count == rhsArray.count else { return false } - for (index, element) in lhsArray.enumerated() { - if !deepEqualsEventChannelMessages(element, rhsArray[index]) { - return false + case (let lhsArray, let rhsArray) as ([Any?], [Any?]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !deepEquals(element, rhsArray[index]) { + return false + } } - } - return true + return true - case (let lhsArray, let rhsArray) as ([Double], [Double]): - guard lhsArray.count == rhsArray.count else { return false } - for (index, element) in lhsArray.enumerated() { - if !doubleEqualsEventChannelMessages(element, rhsArray[index]) { - return false + case (let lhsArray, let rhsArray) as ([Double], [Double]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !doubleEquals(element, rhsArray[index]) { + return false + } } - } - return true - - case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): - guard lhsDictionary.count == rhsDictionary.count else { return false } - for (lhsKey, lhsValue) in lhsDictionary { - var found = false - for (rhsKey, rhsValue) in rhsDictionary { - if deepEqualsEventChannelMessages(lhsKey, rhsKey) { - if deepEqualsEventChannelMessages(lhsValue, rhsValue) { - found = true - break - } else { - return false + return true + + case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): + guard lhsDictionary.count == rhsDictionary.count else { return false } + for (lhsKey, lhsValue) in lhsDictionary { + var found = false + for (rhsKey, rhsValue) in rhsDictionary { + if deepEquals(lhsKey, rhsKey) { + if deepEquals(lhsValue, rhsValue) { + found = true + break + } else { + return false + } } } + if !found { return false } } - if !found { return false } - } - return true + return true - case (let lhs as Double, let rhs as Double): - return doubleEqualsEventChannelMessages(lhs, rhs) + case (let lhs as Double, let rhs as Double): + return doubleEquals(lhs, rhs) - case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable): - return lhsHashable == rhsHashable + case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable): + return lhsHashable == rhsHashable - default: - return false + default: + return false + } } -} -func deepHashEventChannelMessages(value: Any?, hasher: inout Hasher) { - let cleanValue = nilOrValue(value) as Any? - if let cleanValue = cleanValue { - if let doubleValue = cleanValue as? Double { - doubleHashEventChannelMessages(doubleValue, &hasher) - } else if let valueList = cleanValue as? [Any?] { - for item in valueList { - deepHashEventChannelMessages(value: item, hasher: &hasher) - } - } else if let valueList = cleanValue as? [Double] { - for item in valueList { - doubleHashEventChannelMessages(item, &hasher) - } - } else if let valueDict = cleanValue as? [AnyHashable: Any?] { - var result = 0 - for (key, value) in valueDict { - var entryKeyHasher = Hasher() - deepHashEventChannelMessages(value: key, hasher: &entryKeyHasher) - var entryValueHasher = Hasher() - deepHashEventChannelMessages(value: value, hasher: &entryValueHasher) - result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize()) + static func deepHash(value: Any?, hasher: inout Hasher) { + let cleanValue = nilOrValue(value) as Any? + if let cleanValue = cleanValue { + if let doubleValue = cleanValue as? Double { + doubleHash(doubleValue, &hasher) + } else if let valueList = cleanValue as? [Any?] { + for item in valueList { + deepHash(value: item, hasher: &hasher) + } + } else if let valueList = cleanValue as? [Double] { + for item in valueList { + doubleHash(item, &hasher) + } + } else if let valueDict = cleanValue as? [AnyHashable: Any?] { + var result = 0 + for (key, value) in valueDict { + var entryKeyHasher = Hasher() + deepHash(value: key, hasher: &entryKeyHasher) + var entryValueHasher = Hasher() + deepHash(value: value, hasher: &entryValueHasher) + result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize()) + } + hasher.combine(result) + } else if let hashableValue = cleanValue as? AnyHashable { + hasher.combine(hashableValue) + } else { + hasher.combine(String(describing: cleanValue)) } - hasher.combine(result) - } else if let hashableValue = cleanValue as? AnyHashable { - hasher.combine(hashableValue) } else { - hasher.combine(String(describing: cleanValue)) + hasher.combine(0) } - } else { - hasher.combine(0) } + +} + +private func nilOrValue(_ value: Any?) -> T? { + if value is NSNull { return nil } + return value as! T? } /// Generated class from Pigeon that represents data sent in messages. @@ -159,12 +169,16 @@ struct IntEvent: PlatformEvent { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsEventChannelMessages(lhs.data, rhs.data) + return EventChannelMessagesPigeonInternal.deepEquals(lhs.data, rhs.data) } func hash(into hasher: inout Hasher) { hasher.combine("IntEvent") - deepHashEventChannelMessages(value: data, hasher: &hasher) + EventChannelMessagesPigeonInternal.deepHash(value: data, hasher: &hasher) + } + + public var description: String { + return "IntEvent(data: \(String(describing: data)))" } } @@ -189,12 +203,16 @@ struct StringEvent: PlatformEvent { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsEventChannelMessages(lhs.data, rhs.data) + return EventChannelMessagesPigeonInternal.deepEquals(lhs.data, rhs.data) } func hash(into hasher: inout Hasher) { hasher.combine("StringEvent") - deepHashEventChannelMessages(value: data, hasher: &hasher) + EventChannelMessagesPigeonInternal.deepHash(value: data, hasher: &hasher) + } + + public var description: String { + return "StringEvent(data: \(String(describing: data)))" } } diff --git a/packages/pigeon/example/app/ios/Runner/Messages.g.swift b/packages/pigeon/example/app/ios/Runner/Messages.g.swift index f8b12f846c22..0922d9f1dac9 100644 --- a/packages/pigeon/example/app/ios/Runner/Messages.g.swift +++ b/packages/pigeon/example/app/ios/Runner/Messages.g.swift @@ -64,122 +64,132 @@ private func createConnectionError(withChannelName channelName: String) -> Pigeo details: "") } -private func isNullish(_ value: Any?) -> Bool { - return value is NSNull || value == nil -} +enum MessagesPigeonInternal { + static func isNullish(_ value: Any?) -> Bool { + guard let innerValue = value else { + return true + } -private func nilOrValue(_ value: Any?) -> T? { - if value is NSNull { return nil } - return value as! T? -} + if case Optional.some(Optional.none) = value { + return true + } -private func doubleEqualsMessages(_ lhs: Double, _ rhs: Double) -> Bool { - return (lhs.isNaN && rhs.isNaN) || lhs == rhs -} + return innerValue is NSNull + } + static func doubleEquals(_ lhs: Double, _ rhs: Double) -> Bool { + return (lhs.isNaN && rhs.isNaN) || lhs == rhs + } -private func doubleHashMessages(_ value: Double, _ hasher: inout Hasher) { - if value.isNaN { - hasher.combine(0x7FF8_0000_0000_0000) - } else { - // Normalize -0.0 to 0.0 - hasher.combine(value == 0 ? 0 : value) + static func doubleHash(_ value: Double, _ hasher: inout Hasher) { + if value.isNaN { + hasher.combine(0x7FF8_0000_0000_0000) + } else { + // Normalize -0.0 to 0.0 + hasher.combine(value == 0 ? 0 : value) + } } -} -func deepEqualsMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { - let cleanLhs = nilOrValue(lhs) as Any? - let cleanRhs = nilOrValue(rhs) as Any? - switch (cleanLhs, cleanRhs) { - case (nil, nil): - return true + static func deepEquals(_ lhs: Any?, _ rhs: Any?) -> Bool { + let cleanLhs = nilOrValue(lhs) as Any? + let cleanRhs = nilOrValue(rhs) as Any? + switch (cleanLhs, cleanRhs) { + case (nil, nil): + return true - case (nil, _), (_, nil): - return false + case (nil, _), (_, nil): + return false - case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs: - return true + case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs: + return true - case is (Void, Void): - return true + case is (Void, Void): + return true - case (let lhsArray, let rhsArray) as ([Any?], [Any?]): - guard lhsArray.count == rhsArray.count else { return false } - for (index, element) in lhsArray.enumerated() { - if !deepEqualsMessages(element, rhsArray[index]) { - return false + case (let lhsArray, let rhsArray) as ([Any?], [Any?]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !deepEquals(element, rhsArray[index]) { + return false + } } - } - return true + return true - case (let lhsArray, let rhsArray) as ([Double], [Double]): - guard lhsArray.count == rhsArray.count else { return false } - for (index, element) in lhsArray.enumerated() { - if !doubleEqualsMessages(element, rhsArray[index]) { - return false + case (let lhsArray, let rhsArray) as ([Double], [Double]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !doubleEquals(element, rhsArray[index]) { + return false + } } - } - return true - - case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): - guard lhsDictionary.count == rhsDictionary.count else { return false } - for (lhsKey, lhsValue) in lhsDictionary { - var found = false - for (rhsKey, rhsValue) in rhsDictionary { - if deepEqualsMessages(lhsKey, rhsKey) { - if deepEqualsMessages(lhsValue, rhsValue) { - found = true - break - } else { - return false + return true + + case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): + guard lhsDictionary.count == rhsDictionary.count else { return false } + for (lhsKey, lhsValue) in lhsDictionary { + var found = false + for (rhsKey, rhsValue) in rhsDictionary { + if deepEquals(lhsKey, rhsKey) { + if deepEquals(lhsValue, rhsValue) { + found = true + break + } else { + return false + } } } + if !found { return false } } - if !found { return false } - } - return true + return true - case (let lhs as Double, let rhs as Double): - return doubleEqualsMessages(lhs, rhs) + case (let lhs as Double, let rhs as Double): + return doubleEquals(lhs, rhs) - case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable): - return lhsHashable == rhsHashable + case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable): + return lhsHashable == rhsHashable - default: - return false + default: + return false + } } -} -func deepHashMessages(value: Any?, hasher: inout Hasher) { - let cleanValue = nilOrValue(value) as Any? - if let cleanValue = cleanValue { - if let doubleValue = cleanValue as? Double { - doubleHashMessages(doubleValue, &hasher) - } else if let valueList = cleanValue as? [Any?] { - for item in valueList { - deepHashMessages(value: item, hasher: &hasher) - } - } else if let valueList = cleanValue as? [Double] { - for item in valueList { - doubleHashMessages(item, &hasher) - } - } else if let valueDict = cleanValue as? [AnyHashable: Any?] { - var result = 0 - for (key, value) in valueDict { - var entryKeyHasher = Hasher() - deepHashMessages(value: key, hasher: &entryKeyHasher) - var entryValueHasher = Hasher() - deepHashMessages(value: value, hasher: &entryValueHasher) - result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize()) + static func deepHash(value: Any?, hasher: inout Hasher) { + let cleanValue = nilOrValue(value) as Any? + if let cleanValue = cleanValue { + if let doubleValue = cleanValue as? Double { + doubleHash(doubleValue, &hasher) + } else if let valueList = cleanValue as? [Any?] { + for item in valueList { + deepHash(value: item, hasher: &hasher) + } + } else if let valueList = cleanValue as? [Double] { + for item in valueList { + doubleHash(item, &hasher) + } + } else if let valueDict = cleanValue as? [AnyHashable: Any?] { + var result = 0 + for (key, value) in valueDict { + var entryKeyHasher = Hasher() + deepHash(value: key, hasher: &entryKeyHasher) + var entryValueHasher = Hasher() + deepHash(value: value, hasher: &entryValueHasher) + result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize()) + } + hasher.combine(result) + } else if let hashableValue = cleanValue as? AnyHashable { + hasher.combine(hashableValue) + } else { + hasher.combine(String(describing: cleanValue)) } - hasher.combine(result) - } else if let hashableValue = cleanValue as? AnyHashable { - hasher.combine(hashableValue) } else { - hasher.combine(String(describing: cleanValue)) + hasher.combine(0) } - } else { - hasher.combine(0) } + +} + +private func nilOrValue(_ value: Any?) -> T? { + if value is NSNull { return nil } + return value as! T? } enum Code: Int { @@ -188,22 +198,22 @@ enum Code: Int { } /// Generated class from Pigeon that represents data sent in messages. -struct MessageData: Hashable { +struct MessageData: Hashable, CustomStringConvertible { var name: String? = nil - var description: String? = nil + var messageDescription: String? = nil var code: Code var data: [String: String] // swift-format-ignore: AlwaysUseLowerCamelCase static func fromList(_ pigeonVar_list: [Any?]) -> MessageData? { let name: String? = nilOrValue(pigeonVar_list[0]) - let description: String? = nilOrValue(pigeonVar_list[1]) + let messageDescription: String? = nilOrValue(pigeonVar_list[1]) let code = pigeonVar_list[2] as! Code let data = pigeonVar_list[3] as! [String: String] return MessageData( name: name, - description: description, + messageDescription: messageDescription, code: code, data: data ) @@ -211,7 +221,7 @@ struct MessageData: Hashable { func toList() -> [Any?] { return [ name, - description, + messageDescription, code, data, ] @@ -220,17 +230,23 @@ struct MessageData: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsMessages(lhs.name, rhs.name) - && deepEqualsMessages(lhs.description, rhs.description) - && deepEqualsMessages(lhs.code, rhs.code) && deepEqualsMessages(lhs.data, rhs.data) + return MessagesPigeonInternal.deepEquals(lhs.name, rhs.name) + && MessagesPigeonInternal.deepEquals(lhs.messageDescription, rhs.messageDescription) + && MessagesPigeonInternal.deepEquals(lhs.code, rhs.code) + && MessagesPigeonInternal.deepEquals(lhs.data, rhs.data) } func hash(into hasher: inout Hasher) { hasher.combine("MessageData") - deepHashMessages(value: name, hasher: &hasher) - deepHashMessages(value: description, hasher: &hasher) - deepHashMessages(value: code, hasher: &hasher) - deepHashMessages(value: data, hasher: &hasher) + MessagesPigeonInternal.deepHash(value: name, hasher: &hasher) + MessagesPigeonInternal.deepHash(value: messageDescription, hasher: &hasher) + MessagesPigeonInternal.deepHash(value: code, hasher: &hasher) + MessagesPigeonInternal.deepHash(value: data, hasher: &hasher) + } + + public var description: String { + return + "MessageData(name: \(String(describing: name)), messageDescription: \(String(describing: messageDescription)), code: \(String(describing: code)), data: \(String(describing: data)))" } } @@ -349,6 +365,7 @@ class ExampleHostApiSetup { } } } + /// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift. protocol MessageFlutterApiProtocol { func flutterMethod( diff --git a/packages/pigeon/example/app/lib/main.dart b/packages/pigeon/example/app/lib/main.dart index 09f1d7be1373..7c955d5ab100 100644 --- a/packages/pigeon/example/app/lib/main.dart +++ b/packages/pigeon/example/app/lib/main.dart @@ -78,7 +78,7 @@ class _MyHomePageState extends State { final message = MessageData( code: Code.one, data: {'header': 'this is a header'}, - description: 'uri text', + messageDescription: 'uri text', ); try { return _api.sendMessage(message); diff --git a/packages/pigeon/example/app/lib/src/event_channel_messages.g.dart b/packages/pigeon/example/app/lib/src/event_channel_messages.g.dart index 8fdd1c22e5c5..abc02462ac60 100644 --- a/packages/pigeon/example/app/lib/src/event_channel_messages.g.dart +++ b/packages/pigeon/example/app/lib/src/event_channel_messages.g.dart @@ -110,6 +110,11 @@ class IntEvent extends PlatformEvent { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'IntEvent(data: $data)'; + } } class StringEvent extends PlatformEvent { @@ -145,6 +150,11 @@ class StringEvent extends PlatformEvent { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'StringEvent(data: $data)'; + } } class _PigeonCodec extends StandardMessageCodec { diff --git a/packages/pigeon/example/app/lib/src/messages.g.dart b/packages/pigeon/example/app/lib/src/messages.g.dart index 699368ba5b3d..fe2a79c2076e 100644 --- a/packages/pigeon/example/app/lib/src/messages.g.dart +++ b/packages/pigeon/example/app/lib/src/messages.g.dart @@ -119,21 +119,21 @@ enum Code { one, two } class MessageData { MessageData({ this.name, - this.description, + this.messageDescription, required this.code, required this.data, }); String? name; - String? description; + String? messageDescription; Code code; Map data; List _toList() { - return [name, description, code, data]; + return [name, messageDescription, code, data]; } Object encode() { @@ -144,7 +144,7 @@ class MessageData { result as List; return MessageData( name: result[0] as String?, - description: result[1] as String?, + messageDescription: result[1] as String?, code: result[2]! as Code, data: (result[3]! as Map).cast(), ); @@ -160,7 +160,7 @@ class MessageData { return true; } return _deepEquals(name, other.name) && - _deepEquals(description, other.description) && + _deepEquals(messageDescription, other.messageDescription) && _deepEquals(code, other.code) && _deepEquals(data, other.data); } @@ -168,6 +168,11 @@ class MessageData { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'MessageData(name: $name, messageDescription: $messageDescription, code: $code, data: $data)'; + } } class _PigeonCodec extends StandardMessageCodec { @@ -203,8 +208,8 @@ class _PigeonCodec extends StandardMessageCodec { } class ExampleHostApi { - /// Constructor for [ExampleHostApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default + /// Constructor for [ExampleHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. ExampleHostApi({ BinaryMessenger? binaryMessenger, diff --git a/packages/pigeon/example/app/linux/messages.g.cc b/packages/pigeon/example/app/linux/messages.g.cc index f1b0e818d11f..7f97ec2927a5 100644 --- a/packages/pigeon/example/app/linux/messages.g.cc +++ b/packages/pigeon/example/app/linux/messages.g.cc @@ -196,12 +196,102 @@ static guint G_GNUC_UNUSED flpigeon_deep_hash(FlValue* value) { } return 0; } +static gchar* G_GNUC_UNUSED flpigeon_to_string(FlValue* value) { + if (value == nullptr) { + return g_strdup("null"); + } + switch (fl_value_get_type(value)) { + case FL_VALUE_TYPE_NULL: + return g_strdup("null"); + case FL_VALUE_TYPE_BOOL: + return g_strdup(fl_value_get_bool(value) ? "true" : "false"); + case FL_VALUE_TYPE_INT: + return g_strdup_printf("%" G_GINT64_FORMAT, fl_value_get_int(value)); + case FL_VALUE_TYPE_FLOAT: + return g_strdup_printf("%g", fl_value_get_float(value)); + case FL_VALUE_TYPE_STRING: + return g_strdup_printf("\"%s\"", fl_value_get_string(value)); + case FL_VALUE_TYPE_UINT8_LIST: { + GString* str = g_string_new("["); + size_t len = fl_value_get_length(value); + const uint8_t* data = fl_value_get_uint8_list(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%d", data[i]); + } + g_string_append(str, "]"); + return g_string_free(str, FALSE); + } + case FL_VALUE_TYPE_INT32_LIST: { + GString* str = g_string_new("["); + size_t len = fl_value_get_length(value); + const int32_t* data = fl_value_get_int32_list(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%d", data[i]); + } + g_string_append(str, "]"); + return g_string_free(str, FALSE); + } + case FL_VALUE_TYPE_INT64_LIST: { + GString* str = g_string_new("["); + size_t len = fl_value_get_length(value); + const int64_t* data = fl_value_get_int64_list(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%" G_GINT64_FORMAT, data[i]); + } + g_string_append(str, "]"); + return g_string_free(str, FALSE); + } + case FL_VALUE_TYPE_FLOAT_LIST: { + GString* str = g_string_new("["); + size_t len = fl_value_get_length(value); + const double* data = fl_value_get_float_list(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%g", data[i]); + } + g_string_append(str, "]"); + return g_string_free(str, FALSE); + } + case FL_VALUE_TYPE_LIST: { + GString* str = g_string_new("["); + size_t len = fl_value_get_length(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + gchar* item_str = flpigeon_to_string(fl_value_get_list_value(value, i)); + g_string_append(str, item_str); + g_free(item_str); + } + g_string_append(str, "]"); + return g_string_free(str, FALSE); + } + case FL_VALUE_TYPE_MAP: { + GString* str = g_string_new("{"); + size_t len = fl_value_get_length(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + gchar* key_str = flpigeon_to_string(fl_value_get_map_key(value, i)); + gchar* val_str = flpigeon_to_string(fl_value_get_map_value(value, i)); + g_string_append_printf(str, "%s: %s", key_str, val_str); + g_free(key_str); + g_free(val_str); + } + g_string_append(str, "}"); + return g_string_free(str, FALSE); + } + default: + return g_strdup("[custom]"); + } + return g_strdup("null"); +} struct _PigeonExamplePackageMessageData { GObject parent_instance; gchar* name; - gchar* description; + gchar* message_description; PigeonExamplePackageCode code; FlValue* data; }; @@ -213,7 +303,7 @@ static void pigeon_example_package_message_data_dispose(GObject* object) { PigeonExamplePackageMessageData* self = PIGEON_EXAMPLE_PACKAGE_MESSAGE_DATA(object); g_clear_pointer(&self->name, g_free); - g_clear_pointer(&self->description, g_free); + g_clear_pointer(&self->message_description, g_free); g_clear_pointer(&self->data, fl_value_unref); G_OBJECT_CLASS(pigeon_example_package_message_data_parent_class) ->dispose(object); @@ -228,8 +318,8 @@ static void pigeon_example_package_message_data_class_init( } PigeonExamplePackageMessageData* pigeon_example_package_message_data_new( - const gchar* name, const gchar* description, PigeonExamplePackageCode code, - FlValue* data) { + const gchar* name, const gchar* message_description, + PigeonExamplePackageCode code, FlValue* data) { PigeonExamplePackageMessageData* self = PIGEON_EXAMPLE_PACKAGE_MESSAGE_DATA( g_object_new(pigeon_example_package_message_data_get_type(), nullptr)); if (name != nullptr) { @@ -237,10 +327,10 @@ PigeonExamplePackageMessageData* pigeon_example_package_message_data_new( } else { self->name = nullptr; } - if (description != nullptr) { - self->description = g_strdup(description); + if (message_description != nullptr) { + self->message_description = g_strdup(message_description); } else { - self->description = nullptr; + self->message_description = nullptr; } self->code = code; self->data = fl_value_ref(data); @@ -253,10 +343,10 @@ const gchar* pigeon_example_package_message_data_get_name( return self->name; } -const gchar* pigeon_example_package_message_data_get_description( +const gchar* pigeon_example_package_message_data_get_message_description( PigeonExamplePackageMessageData* self) { g_return_val_if_fail(PIGEON_EXAMPLE_PACKAGE_IS_MESSAGE_DATA(self), nullptr); - return self->description; + return self->message_description; } PigeonExamplePackageCode pigeon_example_package_message_data_get_code( @@ -278,9 +368,10 @@ static FlValue* pigeon_example_package_message_data_to_list( fl_value_append_take(values, self->name != nullptr ? fl_value_new_string(self->name) : fl_value_new_null()); - fl_value_append_take(values, self->description != nullptr - ? fl_value_new_string(self->description) - : fl_value_new_null()); + fl_value_append_take(values, + self->message_description != nullptr + ? fl_value_new_string(self->message_description) + : fl_value_new_null()); fl_value_append_take(values, fl_value_new_custom(pigeon_example_package_code_type_id, fl_value_new_int(self->code), @@ -297,9 +388,9 @@ pigeon_example_package_message_data_new_from_list(FlValue* values) { name = fl_value_get_string(value0); } FlValue* value1 = fl_value_get_list_value(values, 1); - const gchar* description = nullptr; + const gchar* message_description = nullptr; if (fl_value_get_type(value1) != FL_VALUE_TYPE_NULL) { - description = fl_value_get_string(value1); + message_description = fl_value_get_string(value1); } FlValue* value2 = fl_value_get_list_value(values, 2); PigeonExamplePackageCode code = static_cast( @@ -307,7 +398,8 @@ pigeon_example_package_message_data_new_from_list(FlValue* values) { const_cast(fl_value_get_custom_value(value2))))); FlValue* value3 = fl_value_get_list_value(values, 3); FlValue* data = value3; - return pigeon_example_package_message_data_new(name, description, code, data); + return pigeon_example_package_message_data_new(name, message_description, + code, data); } gboolean pigeon_example_package_message_data_equals( @@ -321,7 +413,7 @@ gboolean pigeon_example_package_message_data_equals( if (g_strcmp0(a->name, b->name) != 0) { return FALSE; } - if (g_strcmp0(a->description, b->description) != 0) { + if (g_strcmp0(a->message_description, b->message_description) != 0) { return FALSE; } if (a->code != b->code) { @@ -338,13 +430,44 @@ guint pigeon_example_package_message_data_hash( g_return_val_if_fail(PIGEON_EXAMPLE_PACKAGE_IS_MESSAGE_DATA(self), 0); guint result = 0; result = result * 31 + (self->name != nullptr ? g_str_hash(self->name) : 0); - result = result * 31 + - (self->description != nullptr ? g_str_hash(self->description) : 0); + result = result * 31 + (self->message_description != nullptr + ? g_str_hash(self->message_description) + : 0); result = result * 31 + static_cast(self->code); result = result * 31 + flpigeon_deep_hash(self->data); return result; } +gchar* pigeon_example_package_message_data_to_string( + PigeonExamplePackageMessageData* self) { + g_return_val_if_fail(PIGEON_EXAMPLE_PACKAGE_IS_MESSAGE_DATA(self), NULL); + GString* str = g_string_new("MessageData("); + g_string_append(str, "name: "); + if (self->name != nullptr) { + g_string_append_printf(str, "\"%s\"", self->name); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", message_description: "); + if (self->message_description != nullptr) { + g_string_append_printf(str, "\"%s\"", self->message_description); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", code: "); + g_string_append_printf(str, "%d", static_cast(self->code)); + g_string_append(str, ", data: "); + if (self->data != nullptr) { + gchar* val_str = flpigeon_to_string(self->data); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ")"); + return g_string_free(str, FALSE); +} + struct _PigeonExamplePackageMessageCodec { FlStandardMessageCodec parent_instance; }; diff --git a/packages/pigeon/example/app/linux/messages.g.h b/packages/pigeon/example/app/linux/messages.g.h index c03ecb20a01d..45a903dbb4c2 100644 --- a/packages/pigeon/example/app/linux/messages.g.h +++ b/packages/pigeon/example/app/linux/messages.g.h @@ -34,7 +34,7 @@ G_DECLARE_FINAL_TYPE(PigeonExamplePackageMessageData, /** * pigeon_example_package_message_data_new: * name: field in this object. - * description: field in this object. + * message_description: field in this object. * code: field in this object. * data: field in this object. * @@ -43,8 +43,8 @@ G_DECLARE_FINAL_TYPE(PigeonExamplePackageMessageData, * Returns: a new #PigeonExamplePackageMessageData */ PigeonExamplePackageMessageData* pigeon_example_package_message_data_new( - const gchar* name, const gchar* description, PigeonExamplePackageCode code, - FlValue* data); + const gchar* name, const gchar* message_description, + PigeonExamplePackageCode code, FlValue* data); /** * pigeon_example_package_message_data_get_name @@ -58,14 +58,14 @@ const gchar* pigeon_example_package_message_data_get_name( PigeonExamplePackageMessageData* object); /** - * pigeon_example_package_message_data_get_description + * pigeon_example_package_message_data_get_message_description * @object: a #PigeonExamplePackageMessageData. * - * Gets the value of the description field of @object. + * Gets the value of the messageDescription field of @object. * * Returns: the field value. */ -const gchar* pigeon_example_package_message_data_get_description( +const gchar* pigeon_example_package_message_data_get_message_description( PigeonExamplePackageMessageData* object); /** @@ -113,6 +113,17 @@ gboolean pigeon_example_package_message_data_equals( guint pigeon_example_package_message_data_hash( PigeonExamplePackageMessageData* object); +/** + * pigeon_example_package_message_data_to_string: + * @object: a #PigeonExamplePackageMessageData. + * + * Returns a string representation of a #PigeonExamplePackageMessageData object. + * + * Returns: (transfer full): a new string, free with g_free(). + */ +gchar* pigeon_example_package_message_data_to_string( + PigeonExamplePackageMessageData* object); + G_DECLARE_FINAL_TYPE(PigeonExamplePackageMessageCodec, pigeon_example_package_message_codec, PIGEON_EXAMPLE_PACKAGE, MESSAGE_CODEC, diff --git a/packages/pigeon/example/app/macos/Runner/messages.g.h b/packages/pigeon/example/app/macos/Runner/messages.g.h index c44b9361e8b9..3f08b096986f 100644 --- a/packages/pigeon/example/app/macos/Runner/messages.g.h +++ b/packages/pigeon/example/app/macos/Runner/messages.g.h @@ -30,11 +30,11 @@ typedef NS_ENUM(NSUInteger, PGNCode) { /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithName:(nullable NSString *)name - description:(nullable NSString *)description + messageDescription:(nullable NSString *)messageDescription code:(PGNCode)code data:(NSDictionary *)data; @property(nonatomic, copy, nullable) NSString *name; -@property(nonatomic, copy, nullable) NSString *description; +@property(nonatomic, copy, nullable) NSString *messageDescription; @property(nonatomic, assign) PGNCode code; @property(nonatomic, copy) NSDictionary *data; @end diff --git a/packages/pigeon/example/app/macos/Runner/messages.g.m b/packages/pigeon/example/app/macos/Runner/messages.g.m index ed7655039d25..10334a87e855 100644 --- a/packages/pigeon/example/app/macos/Runner/messages.g.m +++ b/packages/pigeon/example/app/macos/Runner/messages.g.m @@ -144,12 +144,12 @@ + (nullable PGNMessageData *)nullableFromList:(NSArray *)list; @implementation PGNMessageData + (instancetype)makeWithName:(nullable NSString *)name - description:(nullable NSString *)description + messageDescription:(nullable NSString *)messageDescription code:(PGNCode)code data:(NSDictionary *)data { PGNMessageData *pigeonResult = [[PGNMessageData alloc] init]; pigeonResult.name = name; - pigeonResult.description = description; + pigeonResult.messageDescription = messageDescription; pigeonResult.code = code; pigeonResult.data = data; return pigeonResult; @@ -157,7 +157,7 @@ + (instancetype)makeWithName:(nullable NSString *)name + (PGNMessageData *)fromList:(NSArray *)list { PGNMessageData *pigeonResult = [[PGNMessageData alloc] init]; pigeonResult.name = GetNullableObjectAtIndex(list, 0); - pigeonResult.description = GetNullableObjectAtIndex(list, 1); + pigeonResult.messageDescription = GetNullableObjectAtIndex(list, 1); PGNCodeBox *boxedPGNCode = GetNullableObjectAtIndex(list, 2); pigeonResult.code = boxedPGNCode.value; pigeonResult.data = GetNullableObjectAtIndex(list, 3); @@ -169,7 +169,7 @@ + (nullable PGNMessageData *)nullableFromList:(NSArray *)list { - (NSArray *)toList { return @[ self.name ?: [NSNull null], - self.description ?: [NSNull null], + self.messageDescription ?: [NSNull null], [[PGNCodeBox alloc] initWithValue:self.code], self.data ?: [NSNull null], ]; @@ -183,18 +183,23 @@ - (BOOL)isEqual:(id)object { } PGNMessageData *other = (PGNMessageData *)object; return FLTPigeonDeepEquals(self.name, other.name) && - FLTPigeonDeepEquals(self.description, other.description) && self.code == other.code && - FLTPigeonDeepEquals(self.data, other.data); + FLTPigeonDeepEquals(self.messageDescription, other.messageDescription) && + self.code == other.code && FLTPigeonDeepEquals(self.data, other.data); } - (NSUInteger)hash { NSUInteger result = [self class].hash; result = result * 31 + FLTPigeonDeepHash(self.name); - result = result * 31 + FLTPigeonDeepHash(self.description); + result = result * 31 + FLTPigeonDeepHash(self.messageDescription); result = result * 31 + @(self.code).hash; result = result * 31 + FLTPigeonDeepHash(self.data); return result; } +- (NSString *)description { + return [NSString + stringWithFormat:@"PGNMessageData(name: %@, messageDescription: %@, code: %ld, data: %@)", + self.name, self.messageDescription, (long)self.code, self.data]; +} @end @interface PGNMessagesPigeonCodecReader : FlutterStandardReader diff --git a/packages/pigeon/example/app/pigeons/messages.dart b/packages/pigeon/example/app/pigeons/messages.dart index 04d58081dbbd..690c71251af2 100644 --- a/packages/pigeon/example/app/pigeons/messages.dart +++ b/packages/pigeon/example/app/pigeons/messages.dart @@ -37,7 +37,7 @@ enum Code { one, two } class MessageData { MessageData({required this.code, required this.data}); String? name; - String? description; + String? messageDescription; Code code; Map data; } diff --git a/packages/pigeon/example/app/windows/runner/messages.g.cpp b/packages/pigeon/example/app/windows/runner/messages.g.cpp index 11453da4e053..54b6525ac5c3 100644 --- a/packages/pigeon/example/app/windows/runner/messages.g.cpp +++ b/packages/pigeon/example/app/windows/runner/messages.g.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include namespace pigeon_example { @@ -238,6 +239,101 @@ size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v) { return result; } +template +std::string PigeonInternalToString(const T& v); + +std::string PigeonInternalToString(const bool& v); + +template +std::string PigeonInternalToString(const std::vector& v); + +template +std::string PigeonInternalToString(const std::map& v); + +template +std::string PigeonInternalToString(const std::optional& v); + +template +std::string PigeonInternalToString(const std::unique_ptr& v); + +std::string PigeonInternalToString(const ::flutter::EncodableValue& v); + +template +std::string PigeonInternalToString(const T& v) { + std::stringstream ss; + if constexpr (std::is_enum_v) { + ss << static_cast(v); + } else { + ss << v; + } + return ss.str(); +} + +std::string PigeonInternalToString(const bool& v) { + return v ? "true" : "false"; +} + +template +std::string PigeonInternalToString(const std::vector& v) { + std::stringstream ss; + ss << "["; + for (size_t i = 0; i < v.size(); ++i) { + if (i > 0) { + ss << ", "; + } + ss << PigeonInternalToString(v[i]); + } + ss << "]"; + return ss.str(); +} + +template +std::string PigeonInternalToString(const std::map& v) { + std::stringstream ss; + ss << "{"; + bool first = true; + for (const auto& kv : v) { + if (!first) { + ss << ", "; + } + first = false; + ss << PigeonInternalToString(kv.first) << ": " + << PigeonInternalToString(kv.second); + } + ss << "}"; + return ss.str(); +} + +template +std::string PigeonInternalToString(const std::optional& v) { + return v ? PigeonInternalToString(*v) : "null"; +} + +template +std::string PigeonInternalToString(const std::unique_ptr& v) { + return v ? PigeonInternalToString(*v) : "null"; +} + +std::string PigeonInternalToString(const ::flutter::EncodableValue& v) { + return std::visit( + [](const auto& val) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + return std::string("null"); + } else if constexpr (std::is_same_v) { + return val ? std::string("true") : std::string("false"); + } else if constexpr (std::is_same_v) { + return "\"" + val + "\""; + } else if constexpr (std::is_same_v) { + return std::string("[custom]"); + } else { + return PigeonInternalToString(val); + } + }, + v); +} + } // namespace // MessageData @@ -245,11 +341,12 @@ MessageData::MessageData(const Code& code, const EncodableMap& data) : code_(code), data_(data) {} MessageData::MessageData(const std::string* name, - const std::string* description, const Code& code, - const EncodableMap& data) + const std::string* message_description, + const Code& code, const EncodableMap& data) : name_(name ? std::optional(*name) : std::nullopt), - description_(description ? std::optional(*description) - : std::nullopt), + message_description_( + message_description ? std::optional(*message_description) + : std::nullopt), code_(code), data_(data) {} @@ -263,17 +360,17 @@ void MessageData::set_name(const std::string_view* value_arg) { void MessageData::set_name(std::string_view value_arg) { name_ = value_arg; } -const std::string* MessageData::description() const { - return description_ ? &(*description_) : nullptr; +const std::string* MessageData::message_description() const { + return message_description_ ? &(*message_description_) : nullptr; } -void MessageData::set_description(const std::string_view* value_arg) { - description_ = +void MessageData::set_message_description(const std::string_view* value_arg) { + message_description_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void MessageData::set_description(std::string_view value_arg) { - description_ = value_arg; +void MessageData::set_message_description(std::string_view value_arg) { + message_description_ = value_arg; } const Code& MessageData::code() const { return code_; } @@ -288,8 +385,8 @@ EncodableList MessageData::ToEncodableList() const { EncodableList list; list.reserve(4); list.push_back(name_ ? EncodableValue(*name_) : EncodableValue()); - list.push_back(description_ ? EncodableValue(*description_) - : EncodableValue()); + list.push_back(message_description_ ? EncodableValue(*message_description_) + : EncodableValue()); list.push_back(CustomEncodableValue(code_)); list.push_back(EncodableValue(data_)); return list; @@ -303,16 +400,18 @@ MessageData MessageData::FromEncodableList(const EncodableList& list) { if (!encodable_name.IsNull()) { decoded.set_name(std::get(encodable_name)); } - auto& encodable_description = list[1]; - if (!encodable_description.IsNull()) { - decoded.set_description(std::get(encodable_description)); + auto& encodable_message_description = list[1]; + if (!encodable_message_description.IsNull()) { + decoded.set_message_description( + std::get(encodable_message_description)); } return decoded; } bool MessageData::operator==(const MessageData& other) const { return PigeonInternalDeepEquals(name_, other.name_) && - PigeonInternalDeepEquals(description_, other.description_) && + PigeonInternalDeepEquals(message_description_, + other.message_description_) && PigeonInternalDeepEquals(code_, other.code_) && PigeonInternalDeepEquals(data_, other.data_); } @@ -324,12 +423,34 @@ bool MessageData::operator!=(const MessageData& other) const { size_t MessageData::Hash() const { size_t result = 1; result = result * 31 + PigeonInternalDeepHash(name_); - result = result * 31 + PigeonInternalDeepHash(description_); + result = result * 31 + PigeonInternalDeepHash(message_description_); result = result * 31 + PigeonInternalDeepHash(code_); result = result * 31 + PigeonInternalDeepHash(data_); return result; } +std::ostream& operator<<(std::ostream& os, const MessageData& obj) { + os << "MessageData("; + os << "name: "; + if (obj.name_.has_value()) { + os << PigeonInternalToString(*obj.name_); + } else { + os << "null"; + } + os << ", message_description: "; + if (obj.message_description_.has_value()) { + os << PigeonInternalToString(*obj.message_description_); + } else { + os << "null"; + } + os << ", code: "; + os << PigeonInternalToString(obj.code_); + os << ", data: "; + os << PigeonInternalToString(obj.data_); + os << ")"; + return os; +} + size_t PigeonInternalDeepHash(const MessageData& v) { return v.Hash(); } PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} diff --git a/packages/pigeon/example/app/windows/runner/messages.g.h b/packages/pigeon/example/app/windows/runner/messages.g.h index b23312baccff..2ad87b1205df 100644 --- a/packages/pigeon/example/app/windows/runner/messages.g.h +++ b/packages/pigeon/example/app/windows/runner/messages.g.h @@ -13,6 +13,7 @@ #include #include +#include #include namespace pigeon_example { @@ -68,16 +69,17 @@ class MessageData { explicit MessageData(const Code& code, const ::flutter::EncodableMap& data); // Constructs an object setting all fields. - explicit MessageData(const std::string* name, const std::string* description, - const Code& code, const ::flutter::EncodableMap& data); + explicit MessageData(const std::string* name, + const std::string* message_description, const Code& code, + const ::flutter::EncodableMap& data); const std::string* name() const; void set_name(const std::string_view* value_arg); void set_name(std::string_view value_arg); - const std::string* description() const; - void set_description(const std::string_view* value_arg); - void set_description(std::string_view value_arg); + const std::string* message_description() const; + void set_message_description(const std::string_view* value_arg); + void set_message_description(std::string_view value_arg); const Code& code() const; void set_code(const Code& value_arg); @@ -90,6 +92,8 @@ class MessageData { /// Returns a hash code value for the object. This method is supported for the /// benefit of hash tables. size_t Hash() const; + /// Stream output operator for formatted string representation. + friend std::ostream& operator<<(std::ostream& os, const MessageData& obj); private: static MessageData FromEncodableList(const ::flutter::EncodableList& list); @@ -98,7 +102,7 @@ class MessageData { friend class MessageFlutterApi; friend class PigeonInternalCodecSerializer; std::optional name_; - std::optional description_; + std::optional message_description_; Code code_; ::flutter::EncodableMap data_; }; diff --git a/packages/pigeon/lib/src/cpp/cpp_generator.dart b/packages/pigeon/lib/src/cpp/cpp_generator.dart index ffaf56787d66..2572da2be586 100644 --- a/packages/pigeon/lib/src/cpp/cpp_generator.dart +++ b/packages/pigeon/lib/src/cpp/cpp_generator.dart @@ -225,6 +225,7 @@ class CppHeaderGenerator extends StructuredGenerator { 'map', 'string', 'optional', + 'ostream', ]); indent.newln(); if (generatorOptions.namespace != null) { @@ -483,6 +484,12 @@ class CppHeaderGenerator extends StructuredGenerator { returnType: 'size_t', isConst: true, ); + indent.writeln( + '/// Stream output operator for formatted string representation.', + ); + indent.writeln( + 'friend std::ostream& operator<<(std::ostream& os, const ${classDefinition.name}& obj);', + ); }); _writeAccessBlock(indent, _ClassAccess.private, () { @@ -966,6 +973,7 @@ class CppSourceGenerator extends StructuredGenerator { 'map', 'string', 'optional', + 'sstream', ]); indent.newln(); } @@ -1017,6 +1025,7 @@ class CppSourceGenerator extends StructuredGenerator { indent.writeln('namespace {'); _writeDeepEquals(indent); _writeDeepHash(indent); + _writeDeepToString(indent); indent.writeln('} // namespace'); } @@ -1133,6 +1142,44 @@ class CppSourceGenerator extends StructuredGenerator { }, ); + _writeFunctionDefinition( + indent, + 'operator<<', + returnType: 'std::ostream&', + parameters: [ + 'std::ostream& os', + 'const ${classDefinition.name}& obj', + ], + body: () { + indent.writeln('os << "${classDefinition.name}(";'); + enumerate(orderedFields, (int index, final NamedType field) { + final name = 'obj.${_makeInstanceVariableName(field)}'; + final comma = index == 0 ? '' : ', '; + indent.writeln('os << "$comma${_makeVariableName(field)}: ";'); + if (field.type.isNullable) { + indent.writeScoped('if ($name.has_value()) {', '}', () { + if (field.type.isClass) { + indent.writeln('os << *$name;'); + } else { + indent.writeln('os << PigeonInternalToString(*$name);'); + } + }); + indent.writeScoped('else {', '}', () { + indent.writeln('os << "null";'); + }); + } else { + if (field.type.isClass) { + indent.writeln('os << $name;'); + } else { + indent.writeln('os << PigeonInternalToString($name);'); + } + } + }); + indent.writeln('os << ")";'); + indent.writeln('return os;'); + }, + ); + _writeFunctionDefinition( indent, 'PigeonInternalDeepHash', @@ -1345,6 +1392,103 @@ size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v) { '''); } + void _writeDeepToString(Indent indent) { + indent.format(r''' +template +std::string PigeonInternalToString(const T& v); + +std::string PigeonInternalToString(const bool& v); + +template +std::string PigeonInternalToString(const std::vector& v); + +template +std::string PigeonInternalToString(const std::map& v); + +template +std::string PigeonInternalToString(const std::optional& v); + +template +std::string PigeonInternalToString(const std::unique_ptr& v); + +std::string PigeonInternalToString(const ::flutter::EncodableValue& v); + +template +std::string PigeonInternalToString(const T& v) { + std::stringstream ss; + if constexpr (std::is_enum_v) { + ss << static_cast(v); + } else { + ss << v; + } + return ss.str(); +} + +std::string PigeonInternalToString(const bool& v) { + return v ? "true" : "false"; +} + +template +std::string PigeonInternalToString(const std::vector& v) { + std::stringstream ss; + ss << "["; + for (size_t i = 0; i < v.size(); ++i) { + if (i > 0) { + ss << ", "; + } + ss << PigeonInternalToString(v[i]); + } + ss << "]"; + return ss.str(); +} + +template +std::string PigeonInternalToString(const std::map& v) { + std::stringstream ss; + ss << "{"; + bool first = true; + for (const auto& kv : v) { + if (!first) { + ss << ", "; + } + first = false; + ss << PigeonInternalToString(kv.first) << ": " << PigeonInternalToString(kv.second); + } + ss << "}"; + return ss.str(); +} + +template +std::string PigeonInternalToString(const std::optional& v) { + return v ? PigeonInternalToString(*v) : "null"; +} + +template +std::string PigeonInternalToString(const std::unique_ptr& v) { + return v ? PigeonInternalToString(*v) : "null"; +} + +std::string PigeonInternalToString(const ::flutter::EncodableValue& v) { + return std::visit( + [](const auto& val) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + return std::string("null"); + } else if constexpr (std::is_same_v) { + return val ? std::string("true") : std::string("false"); + } else if constexpr (std::is_same_v) { + return "\"" + val + "\""; + } else if constexpr (std::is_same_v) { + return std::string("[custom]"); + } else { + return PigeonInternalToString(val); + } + }, + v); +} +'''); + } + @override void writeClassEncode( InternalCppOptions generatorOptions, diff --git a/packages/pigeon/lib/src/dart/dart_generator.dart b/packages/pigeon/lib/src/dart/dart_generator.dart index 435df247c0c2..2b8366c11252 100644 --- a/packages/pigeon/lib/src/dart/dart_generator.dart +++ b/packages/pigeon/lib/src/dart/dart_generator.dart @@ -398,6 +398,20 @@ class DartGenerator extends StructuredGenerator { indent.writeln( 'int get hashCode => _deepHash([runtimeType, ..._toList()]);', ); + + indent.newln(); + indent.writeln('@override'); + indent.writeScoped('String toString() {', '}', () { + final Iterable fields = getFieldsInSerializationOrder( + classDefinition, + ); + final Iterable fieldStrings = fields.map((NamedType field) { + return '${field.name}: \$${field.name}'; + }); + indent.writeln( + "return '${classDefinition.name}(${fieldStrings.join(', ')})';", + ); + }); } @override @@ -645,8 +659,8 @@ class DartGenerator extends StructuredGenerator { indent.write('class ${api.name} '); indent.addScoped('{', '}', () { indent.format(''' -/// Constructor for [${api.name}]. The [binaryMessenger] named argument is -/// available for dependency injection. If it is left null, the default +/// Constructor for [${api.name}]. The [binaryMessenger] named argument is +/// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. ${api.name}({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) : ${varNamePrefix}binaryMessenger = binaryMessenger, @@ -1272,7 +1286,7 @@ Object? _extractReplyValueOrThrow( \t\t\tdetails: replyList[2], \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 + // handling. Returning a nil value and not returning an error is an // exception. indent.format(''' \t} else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { diff --git a/packages/pigeon/lib/src/functional.dart b/packages/pigeon/lib/src/functional.dart index 01a9cf8b30a0..7ef3bf0da6dc 100644 --- a/packages/pigeon/lib/src/functional.dart +++ b/packages/pigeon/lib/src/functional.dart @@ -24,7 +24,7 @@ void enumerate(Iterable iterable, void Function(int, T) func) { } } -/// A [map] function that takes in 2 iterables. The [Iterable]s must be of +/// A [map] function that takes in 2 iterables. The [Iterable]s must be of /// equal length. Iterable map2( Iterable ts, @@ -41,7 +41,7 @@ Iterable map2( } } -/// A [map] function that takes in 3 iterables. The [Iterable]s must be of +/// A [map] function that takes in 3 iterables. The [Iterable]s must be of /// equal length. Iterable map3( Iterable ts, diff --git a/packages/pigeon/lib/src/generator_tools.dart b/packages/pigeon/lib/src/generator_tools.dart index 55874a95684a..0902718890dc 100644 --- a/packages/pigeon/lib/src/generator_tools.dart +++ b/packages/pigeon/lib/src/generator_tools.dart @@ -15,7 +15,7 @@ import 'generator.dart'; /// The current version of pigeon. /// /// This must match the version in pubspec.yaml. -const String pigeonVersion = '26.3.4'; +const String pigeonVersion = '26.4.0'; /// Default plugin package name. const String defaultPluginPackageName = 'dev.flutter.pigeon'; diff --git a/packages/pigeon/lib/src/gobject/gobject_generator.dart b/packages/pigeon/lib/src/gobject/gobject_generator.dart index 0906c005d78a..0cb022c17498 100644 --- a/packages/pigeon/lib/src/gobject/gobject_generator.dart +++ b/packages/pigeon/lib/src/gobject/gobject_generator.dart @@ -5,6 +5,7 @@ import 'package:path/path.dart' as path; import '../ast.dart'; +import '../functional.dart'; import '../generator.dart'; import '../generator_tools.dart'; @@ -352,6 +353,17 @@ class GObjectHeaderGenerator 'Returns: the hash code.', ], _docCommentSpec); indent.writeln('guint ${methodPrefix}_hash($className* object);'); + + indent.newln(); + addDocumentationComments(indent, [ + '${methodPrefix}_to_string:', + '@object: a #$className.', + '', + 'Returns a string representation of a #$className object.', + '', + 'Returns: (transfer full): a new string, free with g_free().', + ], _docCommentSpec); + indent.writeln('gchar* ${methodPrefix}_to_string($className* object);'); } @override @@ -851,6 +863,7 @@ class GObjectSourceGenerator _writeHashHelpers(indent); _writeDeepEquals(indent); _writeDeepHash(indent); + _writeDeepToString(indent); } @override @@ -1346,6 +1359,162 @@ class GObjectSourceGenerator } indent.writeln('return result;'); }); + + indent.newln(); + indent.writeScoped('gchar* ${methodPrefix}_to_string($className* self) {', '}', () { + indent.writeln('g_return_val_if_fail($testMacro(self), NULL);'); + indent.writeln( + 'GString* str = g_string_new("${classDefinition.name}(");', + ); + + enumerate(classDefinition.fields, (int index, final NamedType field) { + final String fieldName = _getFieldName(field.name); + final comma = index == 0 ? '' : ', '; + indent.writeln( + 'g_string_append(str, "$comma${_getFieldName(field.name)}: ");', + ); + + if (field.type.isClass) { + final String fieldMethodPrefix = _getMethodPrefix( + module, + field.type.baseName, + ); + _writeAppendValueOrNull( + indent, + fieldName: fieldName, + nonNullBuilder: () { + indent.writeln( + 'gchar* field_str = ${fieldMethodPrefix}_to_string(self->$fieldName);', + ); + indent.writeln('g_string_append(str, field_str);'); + indent.writeln('g_free(field_str);'); + }, + ); + } else if (field.type.baseName == 'String') { + _writeAppendValueOrNull( + indent, + fieldName: fieldName, + nonNullBuilder: () { + indent.writeln( + 'g_string_append_printf(str, "\\"%s\\"", self->$fieldName);', + ); + }, + ); + } else if (field.type.isEnum) { + if (field.type.isNullable) { + _writeAppendValueOrNull( + indent, + fieldName: fieldName, + nonNullBuilder: () { + indent.writeln( + 'g_string_append_printf(str, "%d", static_cast(*self->$fieldName));', + ); + }, + ); + } else { + indent.writeln( + 'g_string_append_printf(str, "%d", static_cast(self->$fieldName));', + ); + } + } else if (_isNumericListType(field.type)) { + _writeAppendValueOrNull( + indent, + fieldName: fieldName, + nonNullBuilder: () { + indent.writeln('g_string_append(str, "[");'); + indent.writeln('size_t len = self->${fieldName}_length;'); + final String elementTypeName = _getType( + module, + field.type, + isElementType: true, + ); + indent.writeln( + 'const $elementTypeName* data = self->$fieldName;', + ); + indent.writeScoped('for (size_t i = 0; i < len; i++) {', '}', () { + indent.writeln('if (i > 0) g_string_append(str, ", ");'); + if (field.type.baseName == 'Int64List') { + indent.writeln( + 'g_string_append_printf(str, "%" G_GINT64_FORMAT, data[i]);', + ); + } else if (field.type.baseName == 'Float32List' || + field.type.baseName == 'Float64List') { + indent.writeln('g_string_append_printf(str, "%g", data[i]);'); + } else { + indent.writeln( + 'g_string_append_printf(str, "%d", static_cast(data[i]));', + ); + } + }); + indent.writeln('g_string_append(str, "]");'); + }, + ); + } else if (field.type.baseName == 'bool') { + if (field.type.isNullable) { + _writeAppendValueOrNull( + indent, + fieldName: fieldName, + nonNullBuilder: () { + indent.writeln( + 'g_string_append(str, *self->$fieldName ? "true" : "false");', + ); + }, + ); + } else { + indent.writeln( + 'g_string_append(str, self->$fieldName ? "true" : "false");', + ); + } + } else if (field.type.baseName == 'int') { + if (field.type.isNullable) { + _writeAppendValueOrNull( + indent, + fieldName: fieldName, + nonNullBuilder: () { + indent.writeln( + 'g_string_append_printf(str, "%" G_GINT64_FORMAT, *self->$fieldName);', + ); + }, + ); + } else { + indent.writeln( + 'g_string_append_printf(str, "%" G_GINT64_FORMAT, self->$fieldName);', + ); + } + } else if (field.type.baseName == 'double') { + if (field.type.isNullable) { + _writeAppendValueOrNull( + indent, + fieldName: fieldName, + nonNullBuilder: () { + indent.writeln( + 'g_string_append_printf(str, "%g", *self->$fieldName);', + ); + }, + ); + } else { + indent.writeln( + 'g_string_append_printf(str, "%g", self->$fieldName);', + ); + } + } else { + _writeAppendValueOrNull( + indent, + fieldName: fieldName, + nonNullBuilder: () { + indent.writeln( + 'gchar* val_str = flpigeon_to_string(self->$fieldName);', + ); + indent.writeln('g_string_append(str, val_str);'); + indent.writeln('g_free(val_str);'); + }, + ); + } + }); + + indent.writeln('g_string_append(str, ")");'); + indent.writeln('return g_string_free(str, FALSE);'); + }); } @override @@ -3096,3 +3265,109 @@ void _writeDeepHash(Indent indent) { }, ); } + +void _writeDeepToString(Indent indent) { + indent.format(r''' +static gchar* G_GNUC_UNUSED flpigeon_to_string(FlValue* value) { + if (value == nullptr) { + return g_strdup("null"); + } + switch (fl_value_get_type(value)) { + case FL_VALUE_TYPE_NULL: + return g_strdup("null"); + case FL_VALUE_TYPE_BOOL: + return g_strdup(fl_value_get_bool(value) ? "true" : "false"); + case FL_VALUE_TYPE_INT: + return g_strdup_printf("%" G_GINT64_FORMAT, fl_value_get_int(value)); + case FL_VALUE_TYPE_FLOAT: + return g_strdup_printf("%g", fl_value_get_float(value)); + case FL_VALUE_TYPE_STRING: + return g_strdup_printf("\"%s\"", fl_value_get_string(value)); + case FL_VALUE_TYPE_UINT8_LIST: { + GString* str = g_string_new("["); + size_t len = fl_value_get_length(value); + const uint8_t* data = fl_value_get_uint8_list(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%d", data[i]); + } + g_string_append(str, "]"); + return g_string_free(str, FALSE); + } + case FL_VALUE_TYPE_INT32_LIST: { + GString* str = g_string_new("["); + size_t len = fl_value_get_length(value); + const int32_t* data = fl_value_get_int32_list(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%d", data[i]); + } + g_string_append(str, "]"); + return g_string_free(str, FALSE); + } + case FL_VALUE_TYPE_INT64_LIST: { + GString* str = g_string_new("["); + size_t len = fl_value_get_length(value); + const int64_t* data = fl_value_get_int64_list(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%" G_GINT64_FORMAT, data[i]); + } + g_string_append(str, "]"); + return g_string_free(str, FALSE); + } + case FL_VALUE_TYPE_FLOAT_LIST: { + GString* str = g_string_new("["); + size_t len = fl_value_get_length(value); + const double* data = fl_value_get_float_list(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%g", data[i]); + } + g_string_append(str, "]"); + return g_string_free(str, FALSE); + } + case FL_VALUE_TYPE_LIST: { + GString* str = g_string_new("["); + size_t len = fl_value_get_length(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + gchar* item_str = flpigeon_to_string(fl_value_get_list_value(value, i)); + g_string_append(str, item_str); + g_free(item_str); + } + g_string_append(str, "]"); + return g_string_free(str, FALSE); + } + case FL_VALUE_TYPE_MAP: { + GString* str = g_string_new("{"); + size_t len = fl_value_get_length(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + gchar* key_str = flpigeon_to_string(fl_value_get_map_key(value, i)); + gchar* val_str = flpigeon_to_string(fl_value_get_map_value(value, i)); + g_string_append_printf(str, "%s: %s", key_str, val_str); + g_free(key_str); + g_free(val_str); + } + g_string_append(str, "}"); + return g_string_free(str, FALSE); + } + default: + return g_strdup("[custom]"); + } + return g_strdup("null"); +} +'''); +} + +void _writeAppendValueOrNull( + Indent indent, { + required String fieldName, + required void Function() nonNullBuilder, +}) { + indent.writeScoped('if (self->$fieldName != nullptr) {', '}', nonNullBuilder); + indent.writeScoped('else {', '}', () { + indent.writeln('g_string_append(str, "null");'); + }); +} diff --git a/packages/pigeon/lib/src/java/java_generator.dart b/packages/pigeon/lib/src/java/java_generator.dart index 5ef1c93e33cf..a510727e2749 100644 --- a/packages/pigeon/lib/src/java/java_generator.dart +++ b/packages/pigeon/lib/src/java/java_generator.dart @@ -289,6 +289,7 @@ class JavaGenerator extends StructuredGenerator { indent.newln(); } _writeEquality(indent, classDefinition); + _writeToString(indent, classDefinition); _writeClassBuilder(generatorOptions, root, indent, classDefinition); writeClassEncode( @@ -410,6 +411,32 @@ class JavaGenerator extends StructuredGenerator { indent.newln(); } + void _writeToString(Indent indent, Class classDefinition) { + indent.writeln('@Override'); + indent.writeScoped('public String toString() {', '}', () { + final Iterable fieldStrings = classDefinition.fields.map(( + NamedType field, + ) { + final String fieldName = field.name; + if (field.type.baseName == 'Uint8List' || + field.type.baseName == 'Int32List' || + field.type.baseName == 'Int64List' || + field.type.baseName == 'Float64List') { + return '"$fieldName=" + java.util.Arrays.toString($fieldName)'; + } + return '"$fieldName=" + $fieldName'; + }); + if (fieldStrings.isEmpty) { + indent.writeln('return "${classDefinition.name}{}";'); + } else { + indent.writeln( + 'return "${classDefinition.name}{" + ${fieldStrings.join(' + ", " + ')} + "}";', + ); + } + }); + indent.newln(); + } + void _writeDeepEquals(Indent indent) { indent.writeScoped( 'static boolean pigeonDeepEquals(Object a, Object b) {', @@ -1090,41 +1117,46 @@ if (wrapped == null) { indent.writeln('$sendArgument,'); indent.write('channelReply -> '); indent.addScoped('{', '});', () { - indent.writeScoped('if (channelReply instanceof List) {', '} ', () { - indent.writeln( - 'List listReply = (List) channelReply;', - ); - indent.writeScoped('if (listReply.size() > 1) {', '} ', () { + indent.writeScoped( + 'if (channelReply instanceof List) {', + '} ', + () { indent.writeln( - 'result.error(new FlutterError((String) listReply.get(0), (String) listReply.get(1), listReply.get(2)));', - ); - }, addTrailingNewline: false); - if (!func.returnType.isNullable && !func.returnType.isVoid) { - indent.addScoped( - 'else if (listReply.get(0) == null) {', - '} ', - () { - indent.writeln( - 'result.error(new FlutterError("null-error", "Flutter api returned null value for non-null return value.", ""));', - ); - }, - addTrailingNewline: false, + 'List listReply = (List) channelReply;', ); - } - indent.addScoped('else {', '}', () { - if (func.returnType.isVoid) { - indent.writeln('result.success();'); - } else { - const output = 'output'; - final String outputExpression; - indent.writeln('@SuppressWarnings("ConstantConditions")'); - outputExpression = - '${_cast('listReply.get(0)', javaType: returnType)};'; - indent.writeln('$returnType $output = $outputExpression'); - indent.writeln('result.success($output);'); + indent.writeScoped('if (listReply.size() > 1) {', '} ', () { + indent.writeln( + 'result.error(new FlutterError((String) listReply.get(0), (String) listReply.get(1), listReply.get(2)));', + ); + }, addTrailingNewline: false); + if (!func.returnType.isNullable && !func.returnType.isVoid) { + indent.addScoped( + 'else if (listReply.get(0) == null) {', + '} ', + () { + indent.writeln( + 'result.error(new FlutterError("null-error", "Flutter api returned null value for non-null return value.", ""));', + ); + }, + addTrailingNewline: false, + ); } - }); - }, addTrailingNewline: false); + indent.addScoped('else {', '}', () { + if (func.returnType.isVoid) { + indent.writeln('result.success();'); + } else { + const output = 'output'; + final String outputExpression; + indent.writeln('@SuppressWarnings("ConstantConditions")'); + outputExpression = + '${_cast('listReply.get(0)', javaType: returnType)};'; + indent.writeln('$returnType $output = $outputExpression'); + indent.writeln('result.success($output);'); + } + }); + }, + addTrailingNewline: false, + ); indent.addScoped(' else {', '} ', () { indent.writeln( 'result.error(createConnectionError(channelName));', diff --git a/packages/pigeon/lib/src/kotlin/kotlin_generator.dart b/packages/pigeon/lib/src/kotlin/kotlin_generator.dart index 41e6a880f0a2..e26ab8515c8d 100644 --- a/packages/pigeon/lib/src/kotlin/kotlin_generator.dart +++ b/packages/pigeon/lib/src/kotlin/kotlin_generator.dart @@ -333,6 +333,13 @@ class KotlinGenerator extends StructuredGenerator { classDefinition, dartPackageName: dartPackageName, ); + writeClassToString( + generatorOptions, + root, + indent, + classDefinition, + dartPackageName: dartPackageName, + ); }); } @@ -390,6 +397,34 @@ class KotlinGenerator extends StructuredGenerator { }); } + /// Writes the `toString` method for a class. + void writeClassToString( + InternalKotlinOptions generatorOptions, + Root root, + Indent indent, + Class classDefinition, { + required String dartPackageName, + }) { + indent.writeScoped('override fun toString(): String {', '}', () { + final Iterable fieldStrings = classDefinition.fields.map(( + NamedType field, + ) { + final String name = field.name; + if (field.type.baseName == 'Uint8List' || + field.type.baseName == 'Int32List' || + field.type.baseName == 'Int64List' || + field.type.baseName == 'Float64List') { + final nullSafe = field.type.isNullable ? '?' : ''; + return '$name=\${$name$nullSafe.contentToString()}'; + } + return '$name=\$$name'; + }); + indent.writeln( + 'return "${classDefinition.name}(${fieldStrings.join(', ')})"', + ); + }); + } + void _writeDataClassSignature( Indent indent, Class classDefinition, { diff --git a/packages/pigeon/lib/src/kotlin/templates.dart b/packages/pigeon/lib/src/kotlin/templates.dart index f8afe99fe980..ad9b752c175f 100644 --- a/packages/pigeon/lib/src/kotlin/templates.dart +++ b/packages/pigeon/lib/src/kotlin/templates.dart @@ -37,7 +37,7 @@ String instanceManagerTemplate(InternalKotlinOptions options) { */ @Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate") class ${kotlinInstanceManagerClassName(options)}(private val finalizationListener: $_finalizationListenerClassName) { - /** Interface for listening when a weak reference of an instance is removed from the manager. */ + /** Interface for listening when a weak reference of an instance is removed from the manager. */ interface $_finalizationListenerClassName { fun onFinalize(identifier: Long) } diff --git a/packages/pigeon/lib/src/objc/objc_generator.dart b/packages/pigeon/lib/src/objc/objc_generator.dart index af0ad6d1ea2a..966488c1a9b8 100644 --- a/packages/pigeon/lib/src/objc/objc_generator.dart +++ b/packages/pigeon/lib/src/objc/objc_generator.dart @@ -617,6 +617,7 @@ class ObjcSourceGenerator extends StructuredGenerator { dartPackageName: dartPackageName, ); _writeObjcEquality(generatorOptions, indent, classDefinition); + _writeObjcDescription(generatorOptions, indent, classDefinition); indent.writeln('@end'); indent.newln(); } @@ -686,6 +687,63 @@ class ObjcSourceGenerator extends StructuredGenerator { }); } + void _writeObjcDescription( + InternalObjcOptions languageOptions, + Indent indent, + Class classDefinition, + ) { + final String className = _className( + languageOptions.prefix, + classDefinition.name, + ); + indent.writeScoped('- (NSString *)description {', '}', () { + final Iterable fieldLabels = classDefinition.fields.map(( + NamedType field, + ) { + if (_usesPrimitive(field.type)) { + if (field.type.isEnum) { + return '${field.name}: %ld'; + } + switch (field.type.baseName) { + case 'bool': + return '${field.name}: %@'; + case 'int': + return '${field.name}: %ld'; + case 'double': + return '${field.name}: %f'; + } + } + return '${field.name}: %@'; + }); + final formatString = '$className(${fieldLabels.join(', ')})'; + + final Iterable fieldValues = classDefinition.fields.map(( + NamedType field, + ) { + if (_usesPrimitive(field.type)) { + if (field.type.isEnum) { + return '(long)self.${field.name}'; + } + switch (field.type.baseName) { + case 'bool': + return 'self.${field.name} ? @"true" : @"false"'; + case 'int': + return '(long)self.${field.name}'; + case 'double': + return 'self.${field.name}'; + } + } + return 'self.${field.name}'; + }); + + final String args = [ + '@"$formatString"', + ...fieldValues, + ].join(', '); + indent.writeln('return [NSString stringWithFormat:$args];'); + }); + } + @override void writeClassEncode( InternalObjcOptions generatorOptions, @@ -1913,7 +1971,7 @@ String _capitalize(String str) => str.isEmpty ? '' : str[0].toUpperCase() + str.substring(1); /// Returns the components of the objc selector that will be generated from -/// [func], ie the strings between the semicolons. [lastSelectorComponent] is +/// [func], ie the strings between the semicolons. [lastSelectorComponent] is /// the last component of the selector aka the label of the last parameter which /// isn't included in [func]. /// Example: @@ -1945,13 +2003,13 @@ Iterable _getSelectorComponents( } } -/// Generates the objc source code method signature for [func]. [returnType] is +/// Generates the objc source code method signature for [func]. [returnType] is /// the return value of method, this may not match the return value in [func] -/// since [func] may be asynchronous. The function requires you specify a +/// since [func] may be asynchronous. The function requires you specify a /// [lastArgType] and [lastArgName] for arguments that aren't represented in -/// [func]. This is typically used for passing in 'error' or 'completion' +/// [func]. This is typically used for passing in 'error' or 'completion' /// arguments that don't exist in the pigeon file but are required in the objc -/// output. [argNameFunc] is the function used to generate the argument name +/// output. [argNameFunc] is the function used to generate the argument name /// [func.parameters]. String _makeObjcSignature({ required Method func, diff --git a/packages/pigeon/lib/src/pigeon_cl.dart b/packages/pigeon/lib/src/pigeon_cl.dart index 75504154bfcd..78e39f672d73 100644 --- a/packages/pigeon/lib/src/pigeon_cl.dart +++ b/packages/pigeon/lib/src/pigeon_cl.dart @@ -5,7 +5,7 @@ import 'dart:async'; import 'pigeon_lib.dart'; -/// This is the main entrypoint for the command-line tool. [args] are the +/// This is the main entrypoint for the command-line tool. [args] are the /// command line arguments and there is an optional [packageConfig] to /// accommodate users that want to integrate pigeon with other build systems. /// [sdkPath] for specifying an optional Dart SDK path. diff --git a/packages/pigeon/lib/src/pigeon_lib.dart b/packages/pigeon/lib/src/pigeon_lib.dart index fd6b6c827b2b..9c38d8068d3c 100644 --- a/packages/pigeon/lib/src/pigeon_lib.dart +++ b/packages/pigeon/lib/src/pigeon_lib.dart @@ -110,7 +110,7 @@ class HostApi { /// to specify where to generate the test file. /// /// Prefer to use a mock of the real [HostApi] with a mocking library for unit - /// tests. Generating this Dart handler is sometimes useful in integration + /// tests. Generating this Dart handler is sometimes useful in integration /// testing. /// /// Defaults to `null` in which case no handler will be generated. @@ -629,7 +629,7 @@ ${_argParser.usage}'''; /// Convert command-line arguments to [PigeonOptions]. static PigeonOptions parseArgs(List args) { // Note: This function shouldn't perform any logic, just translate the args - // to PigeonOptions. Synthesized values inside of the PigeonOption should + // to PigeonOptions. Synthesized values inside of the PigeonOption should // get set in the `run` function to accommodate users that are using the // `configurePigeon` function. final ArgResults results = _argParser.parse(args); @@ -691,8 +691,8 @@ ${_argParser.usage}'''; } } - /// The 'main' entrypoint used by the command-line tool. [args] are the - /// command-line arguments. The optional parameter [adapters] allows you to + /// The 'main' entrypoint used by the command-line tool. [args] are the + /// command-line arguments. The optional parameter [adapters] allows you to /// customize the generators that pigeon will use. The optional parameter /// [sdkPath] allows you to specify the Dart SDK path. static Future run( @@ -704,8 +704,8 @@ ${_argParser.usage}'''; return runWithOptions(options, adapters: adapters, sdkPath: sdkPath); } - /// The 'main' entrypoint used by external packages. [options] is - /// used when running the code generator. The optional parameter [adapters] allows you to + /// The 'main' entrypoint used by external packages. [options] is + /// used when running the code generator. The optional parameter [adapters] allows you to /// customize the generators that pigeon will use. The optional parameter /// [sdkPath] allows you to specify the Dart SDK path. static Future runWithOptions( diff --git a/packages/pigeon/lib/src/pigeon_lib_internal.dart b/packages/pigeon/lib/src/pigeon_lib_internal.dart index 617a901f37cc..0b68a9e92e32 100644 --- a/packages/pigeon/lib/src/pigeon_lib_internal.dart +++ b/packages/pigeon/lib/src/pigeon_lib_internal.dart @@ -505,7 +505,22 @@ class SwiftGeneratorAdapter implements GeneratorAdapter { ); @override - List validate(InternalPigeonOptions options, Root root) => []; + List validate(InternalPigeonOptions options, Root root) { + final errors = []; + for (final Class classDefinition in root.classes) { + for (final NamedType field in classDefinition.fields) { + if (field.name == 'description') { + errors.add( + Error( + message: + 'Field "description" is not allowed in class "${classDefinition.name}" because it conflicts with Swift\'s NSObject/CustomStringConvertible.description property.', + ), + ); + } + } + } + return errors; + } } /// A [GeneratorAdapter] that generates C++ source code. diff --git a/packages/pigeon/lib/src/swift/swift_generator.dart b/packages/pigeon/lib/src/swift/swift_generator.dart index 45b968ed4d10..29d0341d9589 100644 --- a/packages/pigeon/lib/src/swift/swift_generator.dart +++ b/packages/pigeon/lib/src/swift/swift_generator.dart @@ -423,8 +423,8 @@ class SwiftGenerator extends StructuredGenerator { final extendsString = classDefinition.superClass != null ? ': ${classDefinition.superClass!.name}' : hashable - ? ': Hashable' - : ''; + ? ': Hashable, CustomStringConvertible' + : ': CustomStringConvertible'; if (classDefinition.isSwiftClass) { indent.write( '${privateString}class ${classDefinition.name}$extendsString ', @@ -593,6 +593,14 @@ if (wrapped == nil) { classDefinition, dartPackageName: dartPackageName, ); + indent.newln(); + writeClassToString( + generatorOptions, + root, + indent, + classDefinition, + dartPackageName: dartPackageName, + ); }); } @@ -682,7 +690,7 @@ if (wrapped == nil) { final String comparisons = fields .map( (NamedType field) => - 'deepEquals${generatorOptions.fileSpecificClassNameComponent ?? ''}(lhs.${field.name}, rhs.${field.name})', + '${generatorOptions.fileSpecificClassNameComponent ?? ''}PigeonInternal.deepEquals(lhs.${field.name}, rhs.${field.name})', ) .join(' && '); indent.writeln('return $comparisons'); @@ -698,12 +706,40 @@ if (wrapped == nil) { ); for (final field in fields) { indent.writeln( - 'deepHash${generatorOptions.fileSpecificClassNameComponent ?? ''}(value: ${field.name}, hasher: &hasher)', + '${generatorOptions.fileSpecificClassNameComponent ?? ''}PigeonInternal.deepHash(value: ${field.name}, hasher: &hasher)', ); } }); } + /// Writes the `CustomStringConvertible` conformance for a class. + void writeClassToString( + InternalSwiftOptions generatorOptions, + Root root, + Indent indent, + Class classDefinition, { + required String dartPackageName, + }) { + final overrideString = + (classDefinition.superClass != null && classDefinition.isSwiftClass) + ? 'override ' + : ''; + indent.writeScoped( + '${overrideString}public var description: String {', + '}', + () { + final Iterable fieldStrings = classDefinition.fields.map(( + NamedType field, + ) { + return '${field.name}: \\(String(describing: ${field.name}))'; + }); + indent.writeln( + 'return "${classDefinition.name}(${fieldStrings.join(', ')})"', + ); + }, + ); + } + @override void writeClassDecode( InternalSwiftOptions generatorOptions, @@ -799,6 +835,7 @@ if (wrapped == nil) { AstFlutterApi api, { required String dartPackageName, }) { + indent.newln(); const generatedComments = [ ' Generated protocol from Pigeon that represents Flutter messages that can be called from Swift.', ]; @@ -1431,12 +1468,19 @@ if (wrapped == nil) { } } - void _writeIsNullish(Indent indent) { - indent.newln(); - indent.write('private func isNullish(_ value: Any?) -> Bool '); - indent.addScoped('{', '}', () { - indent.writeln('return value is NSNull || value == nil'); - }); + void _writeIsNullish(InternalSwiftOptions generatorOptions, Indent indent) { + indent.format(''' +static func isNullish(_ value: Any?) -> Bool { + guard let innerValue = value else { + return true + } + + if case Optional.some(Optional.none) = value { + return true + } + + return innerValue is NSNull +}'''); } void _writeWrapResult(Indent indent) { @@ -1507,20 +1551,12 @@ private func nilOrValue(_ value: Any?) -> T? { } void _writeDeepEquals(InternalSwiftOptions generatorOptions, Indent indent) { - final deepEqualsName = - 'deepEquals${generatorOptions.fileSpecificClassNameComponent ?? ''}'; - final deepHashName = - 'deepHash${generatorOptions.fileSpecificClassNameComponent ?? ''}'; - final doubleEqualsName = - 'doubleEquals${generatorOptions.fileSpecificClassNameComponent ?? ''}'; - final doubleHashName = - 'doubleHash${generatorOptions.fileSpecificClassNameComponent ?? ''}'; indent.format(''' -private func $doubleEqualsName(_ lhs: Double, _ rhs: Double) -> Bool { +static func doubleEquals(_ lhs: Double, _ rhs: Double) -> Bool { return (lhs.isNaN && rhs.isNaN) || lhs == rhs } -private func $doubleHashName(_ value: Double, _ hasher: inout Hasher) { +static func doubleHash(_ value: Double, _ hasher: inout Hasher) { if value.isNaN { hasher.combine(0x7FF8000000000000) } else { @@ -1529,7 +1565,7 @@ private func $doubleHashName(_ value: Double, _ hasher: inout Hasher) { } } -func $deepEqualsName(_ lhs: Any?, _ rhs: Any?) -> Bool { +static func deepEquals(_ lhs: Any?, _ rhs: Any?) -> Bool { let cleanLhs = nilOrValue(lhs) as Any? let cleanRhs = nilOrValue(rhs) as Any? switch (cleanLhs, cleanRhs) { @@ -1548,7 +1584,7 @@ func $deepEqualsName(_ lhs: Any?, _ rhs: Any?) -> Bool { case (let lhsArray, let rhsArray) as ([Any?], [Any?]): guard lhsArray.count == rhsArray.count else { return false } for (index, element) in lhsArray.enumerated() { - if !$deepEqualsName(element, rhsArray[index]) { + if !deepEquals(element, rhsArray[index]) { return false } } @@ -1557,7 +1593,7 @@ func $deepEqualsName(_ lhs: Any?, _ rhs: Any?) -> Bool { case (let lhsArray, let rhsArray) as ([Double], [Double]): guard lhsArray.count == rhsArray.count else { return false } for (index, element) in lhsArray.enumerated() { - if !$doubleEqualsName(element, rhsArray[index]) { + if !doubleEquals(element, rhsArray[index]) { return false } } @@ -1568,8 +1604,8 @@ func $deepEqualsName(_ lhs: Any?, _ rhs: Any?) -> Bool { for (lhsKey, lhsValue) in lhsDictionary { var found = false for (rhsKey, rhsValue) in rhsDictionary { - if $deepEqualsName(lhsKey, rhsKey) { - if $deepEqualsName(lhsValue, rhsValue) { + if deepEquals(lhsKey, rhsKey) { + if deepEquals(lhsValue, rhsValue) { found = true break } else { @@ -1582,7 +1618,7 @@ func $deepEqualsName(_ lhs: Any?, _ rhs: Any?) -> Bool { return true case (let lhs as Double, let rhs as Double): - return $doubleEqualsName(lhs, rhs) + return doubleEquals(lhs, rhs) case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable): return lhsHashable == rhsHashable @@ -1592,26 +1628,26 @@ func $deepEqualsName(_ lhs: Any?, _ rhs: Any?) -> Bool { } } -func $deepHashName(value: Any?, hasher: inout Hasher) { +static func deepHash(value: Any?, hasher: inout Hasher) { let cleanValue = nilOrValue(value) as Any? if let cleanValue = cleanValue { if let doubleValue = cleanValue as? Double { - $doubleHashName(doubleValue, &hasher) + doubleHash(doubleValue, &hasher) } else if let valueList = cleanValue as? [Any?] { for item in valueList { - $deepHashName(value: item, hasher: &hasher) + deepHash(value: item, hasher: &hasher) } } else if let valueList = cleanValue as? [Double] { for item in valueList { - $doubleHashName(item, &hasher) + doubleHash(item, &hasher) } } else if let valueDict = cleanValue as? [AnyHashable: Any?] { var result = 0 for (key, value) in valueDict { var entryKeyHasher = Hasher() - $deepHashName(value: key, hasher: &entryKeyHasher) + deepHash(value: key, hasher: &entryKeyHasher) var entryValueHasher = Hasher() - $deepHashName(value: value, hasher: &entryValueHasher) + deepHash(value: value, hasher: &entryValueHasher) result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize()) } hasher.combine(result) @@ -1627,6 +1663,22 @@ func $deepHashName(value: Any?, hasher: inout Hasher) { '''); } + void _writePigeonInternal( + InternalSwiftOptions generatorOptions, + Root root, + Indent indent, + ) { + indent.newln(); + final String uniqueComponent = + generatorOptions.fileSpecificClassNameComponent ?? ''; + indent.writeScoped('enum ${uniqueComponent}PigeonInternal {', '}', () { + _writeIsNullish(generatorOptions, indent); + if (root.classes.isNotEmpty) { + _writeDeepEquals(generatorOptions, indent); + } + }); + } + @override void writeGeneralUtilities( InternalSwiftOptions generatorOptions, @@ -1646,11 +1698,8 @@ func $deepHashName(value: Any?, hasher: inout Hasher) { _writeCreateConnectionError(generatorOptions, indent); } - _writeIsNullish(indent); + _writePigeonInternal(generatorOptions, root, indent); _writeNilOrValue(indent); - if (root.classes.isNotEmpty) { - _writeDeepEquals(generatorOptions, indent); - } } @override diff --git a/packages/pigeon/pigeons/core_tests.dart b/packages/pigeon/pigeons/core_tests.dart index f55c0bbfd519..6c45528ff6fc 100644 --- a/packages/pigeon/pigeons/core_tests.dart +++ b/packages/pigeon/pigeons/core_tests.dart @@ -334,6 +334,26 @@ abstract class HostIntegrationCoreApi { @SwiftFunction('echo(_:)') List echoList(List list); + /// Returns the passed list, to test serialization and deserialization. + @ObjCSelector('echoStringList:') + @SwiftFunction('echo(stringList:)') + List echoStringList(List stringList); + + /// Returns the passed list, to test serialization and deserialization. + @ObjCSelector('echoIntList:') + @SwiftFunction('echo(intList:)') + List echoIntList(List intList); + + /// Returns the passed list, to test serialization and deserialization. + @ObjCSelector('echoDoubleList:') + @SwiftFunction('echo(doubleList:)') + List echoDoubleList(List doubleList); + + /// Returns the passed list, to test serialization and deserialization. + @ObjCSelector('echoBoolList:') + @SwiftFunction('echo(boolList:)') + List echoBoolList(List boolList); + /// Returns the passed list, to test serialization and deserialization. @ObjCSelector('echoEnumList:') @SwiftFunction('echo(enumList:)') diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/AlternateLanguageTestPlugin.java b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/AlternateLanguageTestPlugin.java index 5c46688a6d95..5622b4b3f2a3 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/AlternateLanguageTestPlugin.java +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/AlternateLanguageTestPlugin.java @@ -134,6 +134,26 @@ public void throwErrorFromVoid() { return list; } + @Override + public @NonNull List echoStringList(@NonNull List stringList) { + return stringList; + } + + @Override + public @NonNull List echoIntList(@NonNull List intList) { + return intList; + } + + @Override + public @NonNull List echoDoubleList(@NonNull List doubleList) { + return doubleList; + } + + @Override + public @NonNull List echoBoolList(@NonNull List boolList) { + return boolList; + } + @Override public @NonNull List echoEnumList(@NonNull List enumList) { return enumList; diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/CoreTests.java b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/CoreTests.java index a21588a5c9df..da1de3d6a4da 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/CoreTests.java +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/CoreTests.java @@ -285,6 +285,11 @@ public int hashCode() { return pigeonDeepHashCode(fields); } + @Override + public String toString() { + return "UnusedClass{" + "aField=" + aField + "}"; + } + public static final class Builder { private @Nullable Object aField; @@ -766,6 +771,95 @@ public int hashCode() { return pigeonDeepHashCode(fields); } + @Override + public String toString() { + return "AllTypes{" + + "aBool=" + + aBool + + ", " + + "anInt=" + + anInt + + ", " + + "anInt64=" + + anInt64 + + ", " + + "aDouble=" + + aDouble + + ", " + + "aByteArray=" + + java.util.Arrays.toString(aByteArray) + + ", " + + "a4ByteArray=" + + java.util.Arrays.toString(a4ByteArray) + + ", " + + "a8ByteArray=" + + java.util.Arrays.toString(a8ByteArray) + + ", " + + "aFloatArray=" + + java.util.Arrays.toString(aFloatArray) + + ", " + + "anEnum=" + + anEnum + + ", " + + "anotherEnum=" + + anotherEnum + + ", " + + "aString=" + + aString + + ", " + + "anObject=" + + anObject + + ", " + + "list=" + + list + + ", " + + "stringList=" + + stringList + + ", " + + "intList=" + + intList + + ", " + + "doubleList=" + + doubleList + + ", " + + "boolList=" + + boolList + + ", " + + "enumList=" + + enumList + + ", " + + "objectList=" + + objectList + + ", " + + "listList=" + + listList + + ", " + + "mapList=" + + mapList + + ", " + + "map=" + + map + + ", " + + "stringMap=" + + stringMap + + ", " + + "intMap=" + + intMap + + ", " + + "enumMap=" + + enumMap + + ", " + + "objectMap=" + + objectMap + + ", " + + "listMap=" + + listMap + + ", " + + "mapMap=" + + mapMap + + "}"; + } + public static final class Builder { private @Nullable Boolean aBool; @@ -1520,6 +1614,104 @@ public int hashCode() { return pigeonDeepHashCode(fields); } + @Override + public String toString() { + return "AllNullableTypes{" + + "aNullableBool=" + + aNullableBool + + ", " + + "aNullableInt=" + + aNullableInt + + ", " + + "aNullableInt64=" + + aNullableInt64 + + ", " + + "aNullableDouble=" + + aNullableDouble + + ", " + + "aNullableByteArray=" + + java.util.Arrays.toString(aNullableByteArray) + + ", " + + "aNullable4ByteArray=" + + java.util.Arrays.toString(aNullable4ByteArray) + + ", " + + "aNullable8ByteArray=" + + java.util.Arrays.toString(aNullable8ByteArray) + + ", " + + "aNullableFloatArray=" + + java.util.Arrays.toString(aNullableFloatArray) + + ", " + + "aNullableEnum=" + + aNullableEnum + + ", " + + "anotherNullableEnum=" + + anotherNullableEnum + + ", " + + "aNullableString=" + + aNullableString + + ", " + + "aNullableObject=" + + aNullableObject + + ", " + + "allNullableTypes=" + + allNullableTypes + + ", " + + "list=" + + list + + ", " + + "stringList=" + + stringList + + ", " + + "intList=" + + intList + + ", " + + "doubleList=" + + doubleList + + ", " + + "boolList=" + + boolList + + ", " + + "enumList=" + + enumList + + ", " + + "objectList=" + + objectList + + ", " + + "listList=" + + listList + + ", " + + "mapList=" + + mapList + + ", " + + "recursiveClassList=" + + recursiveClassList + + ", " + + "map=" + + map + + ", " + + "stringMap=" + + stringMap + + ", " + + "intMap=" + + intMap + + ", " + + "enumMap=" + + enumMap + + ", " + + "objectMap=" + + objectMap + + ", " + + "listMap=" + + listMap + + ", " + + "mapMap=" + + mapMap + + ", " + + "recursiveClassMap=" + + recursiveClassMap + + "}"; + } + public static final class Builder { private @Nullable Boolean aNullableBool; @@ -2276,6 +2468,95 @@ public int hashCode() { return pigeonDeepHashCode(fields); } + @Override + public String toString() { + return "AllNullableTypesWithoutRecursion{" + + "aNullableBool=" + + aNullableBool + + ", " + + "aNullableInt=" + + aNullableInt + + ", " + + "aNullableInt64=" + + aNullableInt64 + + ", " + + "aNullableDouble=" + + aNullableDouble + + ", " + + "aNullableByteArray=" + + java.util.Arrays.toString(aNullableByteArray) + + ", " + + "aNullable4ByteArray=" + + java.util.Arrays.toString(aNullable4ByteArray) + + ", " + + "aNullable8ByteArray=" + + java.util.Arrays.toString(aNullable8ByteArray) + + ", " + + "aNullableFloatArray=" + + java.util.Arrays.toString(aNullableFloatArray) + + ", " + + "aNullableEnum=" + + aNullableEnum + + ", " + + "anotherNullableEnum=" + + anotherNullableEnum + + ", " + + "aNullableString=" + + aNullableString + + ", " + + "aNullableObject=" + + aNullableObject + + ", " + + "list=" + + list + + ", " + + "stringList=" + + stringList + + ", " + + "intList=" + + intList + + ", " + + "doubleList=" + + doubleList + + ", " + + "boolList=" + + boolList + + ", " + + "enumList=" + + enumList + + ", " + + "objectList=" + + objectList + + ", " + + "listList=" + + listList + + ", " + + "mapList=" + + mapList + + ", " + + "map=" + + map + + ", " + + "stringMap=" + + stringMap + + ", " + + "intMap=" + + intMap + + ", " + + "enumMap=" + + enumMap + + ", " + + "objectMap=" + + objectMap + + ", " + + "listMap=" + + listMap + + ", " + + "mapMap=" + + mapMap + + "}"; + } + public static final class Builder { private @Nullable Boolean aNullableBool; @@ -2762,6 +3043,32 @@ public int hashCode() { return pigeonDeepHashCode(fields); } + @Override + public String toString() { + return "AllClassesWrapper{" + + "allNullableTypes=" + + allNullableTypes + + ", " + + "allNullableTypesWithoutRecursion=" + + allNullableTypesWithoutRecursion + + ", " + + "allTypes=" + + allTypes + + ", " + + "classList=" + + classList + + ", " + + "nullableClassList=" + + nullableClassList + + ", " + + "classMap=" + + classMap + + ", " + + "nullableClassMap=" + + nullableClassMap + + "}"; + } + public static final class Builder { private @Nullable AllNullableTypes allNullableTypes; @@ -2905,6 +3212,11 @@ public int hashCode() { return pigeonDeepHashCode(fields); } + @Override + public String toString() { + return "TestMessage{" + "testList=" + testList + "}"; + } + public static final class Builder { private @Nullable List testList; @@ -3086,6 +3398,22 @@ public interface HostIntegrationCoreApi { @NonNull List echoList(@NonNull List list); + /** Returns the passed list, to test serialization and deserialization. */ + @NonNull + List echoStringList(@NonNull List stringList); + + /** Returns the passed list, to test serialization and deserialization. */ + @NonNull + List echoIntList(@NonNull List intList); + + /** Returns the passed list, to test serialization and deserialization. */ + @NonNull + List echoDoubleList(@NonNull List doubleList); + + /** Returns the passed list, to test serialization and deserialization. */ + @NonNull + List echoBoolList(@NonNull List boolList); + /** Returns the passed list, to test serialization and deserialization. */ @NonNull List echoEnumList(@NonNull List enumList); @@ -3929,6 +4257,106 @@ static void setUp( channel.setMessageHandler(null); } } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoStringList" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList<>(); + ArrayList args = (ArrayList) message; + List stringListArg = (List) args.get(0); + try { + List output = api.echoStringList(stringListArg); + wrapped.add(0, output); + } catch (Throwable exception) { + wrapped = wrapError(exception); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoIntList" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList<>(); + ArrayList args = (ArrayList) message; + List intListArg = (List) args.get(0); + try { + List output = api.echoIntList(intListArg); + wrapped.add(0, output); + } catch (Throwable exception) { + wrapped = wrapError(exception); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoDoubleList" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList<>(); + ArrayList args = (ArrayList) message; + List doubleListArg = (List) args.get(0); + try { + List output = api.echoDoubleList(doubleListArg); + wrapped.add(0, output); + } catch (Throwable exception) { + wrapped = wrapError(exception); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoBoolList" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList<>(); + ArrayList args = (ArrayList) message; + List boolListArg = (List) args.get(0); + try { + List output = api.echoBoolList(boolListArg); + wrapped.add(0, output); + } catch (Throwable exception) { + wrapped = wrapError(exception); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } { BasicMessageChannel channel = new BasicMessageChannel<>( diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/AllDatatypesTest.java b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/DataClassMethodsTest.java similarity index 83% rename from packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/AllDatatypesTest.java rename to packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/DataClassMethodsTest.java index 5671cc465163..7b0c28355014 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/AllDatatypesTest.java +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/DataClassMethodsTest.java @@ -19,7 +19,7 @@ import java.util.Map; import org.junit.Test; -public class AllDatatypesTest { +public class DataClassMethodsTest { void compareAllTypes(AllTypes firstTypes, AllTypes secondTypes) { assertEquals(firstTypes == null, secondTypes == null); @@ -267,6 +267,63 @@ public void error(Throwable error) { assertTrue(didCall[0]); } + @Test + public void testToStringFullOutput() { + final List genericList = Arrays.asList(new Object[] {"hello", 1, true, false, null}); + final List> listList = new ArrayList<>(Arrays.asList()); + final List> mapList = new ArrayList<>(Arrays.asList()); + final Map> listMap = new HashMap>(); + final Map> mapMap = new HashMap>(); + listList.add(genericList); + mapList.add(makeMap("hello", 1234)); + listMap.put(1L, genericList); + mapMap.put(1L, makeMap("hello", 1234)); + AllTypes allEverything = + new AllTypes.Builder() + .setABool(false) + .setAnInt(1234L) + .setAnInt64(4321L) + .setADouble(2.0) + .setAString("hello") + .setAByteArray(new byte[] {1, 2, 3, 4}) + .setA4ByteArray(new int[] {1, 2, 3, 4}) + .setA8ByteArray(new long[] {1, 2, 3, 4}) + .setAFloatArray(new double[] {0.5, 0.25, 1.5, 1.25}) + .setAnEnum(CoreTests.AnEnum.ONE) + .setAnotherEnum(CoreTests.AnotherEnum.JUST_IN_CASE) + .setAnObject(0) + .setList(genericList) + .setBoolList(Arrays.asList(new Boolean[] {true, false})) + .setDoubleList(Arrays.asList(new Double[] {0.5, 0.25, 1.5, 1.25})) + .setIntList(Arrays.asList(new Long[] {1l, 2l, 3l, 4l})) + .setStringList(Arrays.asList(new String[] {"string", "another one"})) + .setObjectList(genericList) + .setEnumList( + Arrays.asList( + new CoreTests.AnEnum[] {CoreTests.AnEnum.ONE, CoreTests.AnEnum.FORTY_TWO})) + .setListList(listList) + .setMapList(mapList) + .setMap(makeMap("hello", 1234)) + .setIntMap(makeMap(1L, 0L)) + .setStringMap(makeMap("hello", "you")) + .setObjectMap(makeMap("E", 4321)) + .setEnumMap(makeMap(CoreTests.AnEnum.ONE, CoreTests.AnEnum.FOUR_HUNDRED_TWENTY_TWO)) + .setListMap(listMap) + .setMapMap(mapMap) + .build(); + assertEquals( + "AllTypes{aBool=false, anInt=1234, anInt64=4321, aDouble=2.0, aByteArray=[1, 2, 3, 4]," + + " a4ByteArray=[1, 2, 3, 4], a8ByteArray=[1, 2, 3, 4], aFloatArray=[0.5, 0.25, 1.5," + + " 1.25], anEnum=ONE, anotherEnum=JUST_IN_CASE, aString=hello, anObject=0," + + " list=[hello, 1, true, false, null], stringList=[string, another one], intList=[1," + + " 2, 3, 4], doubleList=[0.5, 0.25, 1.5, 1.25], boolList=[true, false], enumList=[ONE," + + " FORTY_TWO], objectList=[hello, 1, true, false, null], listList=[[hello, 1, true," + + " false, null]], mapList=[{hello=1234}], map={hello=1234}, stringMap={hello=you}," + + " intMap={1=0}, enumMap={ONE=FOUR_HUNDRED_TWENTY_TWO}, objectMap={E=4321}," + + " listMap={1=[hello, 1, true, false, null]}, mapMap={1={hello=1234}}}", + allEverything.toString()); + } + @Test public void equalityWithNaN() { AllNullableTypes withNaN = diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/darwin/alternate_language_test_plugin/Sources/alternate_language_test_plugin/AlternateLanguageTestPlugin.m b/packages/pigeon/platform_tests/alternate_language_test_plugin/darwin/alternate_language_test_plugin/Sources/alternate_language_test_plugin/AlternateLanguageTestPlugin.m index fdd0a0563ae5..0778fcb4f524 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/darwin/alternate_language_test_plugin/Sources/alternate_language_test_plugin/AlternateLanguageTestPlugin.m +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/darwin/alternate_language_test_plugin/Sources/alternate_language_test_plugin/AlternateLanguageTestPlugin.m @@ -95,6 +95,26 @@ - (nullable id)echoObject:(id)anObject error:(FlutterError *_Nullable *_Nonnull) return list; } +- (nullable NSArray *)echoStringList:(NSArray *)stringList + error:(FlutterError *_Nullable *_Nonnull)error { + return stringList; +} + +- (nullable NSArray *)echoIntList:(NSArray *)intList + error:(FlutterError *_Nullable *_Nonnull)error { + return intList; +} + +- (nullable NSArray *)echoDoubleList:(NSArray *)doubleList + error:(FlutterError *_Nullable *_Nonnull)error { + return doubleList; +} + +- (nullable NSArray *)echoBoolList:(NSArray *)boolList + error:(FlutterError *_Nullable *_Nonnull)error { + return boolList; +} + - (nullable NSArray *)echoEnumList:(NSArray *)enumList error:(FlutterError *_Nullable *_Nonnull)error { return enumList; diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/darwin/alternate_language_test_plugin/Sources/alternate_language_test_plugin/CoreTests.gen.m b/packages/pigeon/platform_tests/alternate_language_test_plugin/darwin/alternate_language_test_plugin/Sources/alternate_language_test_plugin/CoreTests.gen.m index 7c114f8fa47b..9692e443f74f 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/darwin/alternate_language_test_plugin/Sources/alternate_language_test_plugin/CoreTests.gen.m +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/darwin/alternate_language_test_plugin/Sources/alternate_language_test_plugin/CoreTests.gen.m @@ -218,6 +218,9 @@ - (NSUInteger)hash { result = result * 31 + FLTPigeonDeepHash(self.aField); return result; } +- (NSString *)description { + return [NSString stringWithFormat:@"FLTUnusedClass(aField: %@)", self.aField]; +} @end @implementation FLTAllTypes @@ -417,6 +420,21 @@ - (NSUInteger)hash { result = result * 31 + FLTPigeonDeepHash(self.mapMap); return result; } +- (NSString *)description { + return [NSString + stringWithFormat: + @"FLTAllTypes(aBool: %@, anInt: %ld, anInt64: %ld, aDouble: %f, aByteArray: %@, " + @"a4ByteArray: %@, a8ByteArray: %@, aFloatArray: %@, anEnum: %ld, anotherEnum: %ld, " + @"aString: %@, anObject: %@, list: %@, stringList: %@, intList: %@, doubleList: %@, " + @"boolList: %@, enumList: %@, objectList: %@, listList: %@, mapList: %@, map: %@, " + @"stringMap: %@, intMap: %@, enumMap: %@, objectMap: %@, listMap: %@, mapMap: %@)", + self.aBool ? @"true" : @"false", (long)self.anInt, (long)self.anInt64, self.aDouble, + self.aByteArray, self.a4ByteArray, self.a8ByteArray, self.aFloatArray, (long)self.anEnum, + (long)self.anotherEnum, self.aString, self.anObject, self.list, self.stringList, + self.intList, self.doubleList, self.boolList, self.enumList, self.objectList, + self.listList, self.mapList, self.map, self.stringMap, self.intMap, self.enumMap, + self.objectMap, self.listMap, self.mapMap]; +} @end @implementation FLTAllNullableTypes @@ -636,6 +654,26 @@ - (NSUInteger)hash { result = result * 31 + FLTPigeonDeepHash(self.recursiveClassMap); return result; } +- (NSString *)description { + return [NSString + stringWithFormat:@"FLTAllNullableTypes(aNullableBool: %@, aNullableInt: %@, aNullableInt64: " + @"%@, aNullableDouble: %@, aNullableByteArray: %@, aNullable4ByteArray: %@, " + @"aNullable8ByteArray: %@, aNullableFloatArray: %@, aNullableEnum: %@, " + @"anotherNullableEnum: %@, aNullableString: %@, aNullableObject: %@, " + @"allNullableTypes: %@, list: %@, stringList: %@, intList: %@, doubleList: " + @"%@, boolList: %@, enumList: %@, objectList: %@, listList: %@, mapList: " + @"%@, recursiveClassList: %@, map: %@, stringMap: %@, intMap: %@, enumMap: " + @"%@, objectMap: %@, listMap: %@, mapMap: %@, recursiveClassMap: %@)", + self.aNullableBool, self.aNullableInt, self.aNullableInt64, + self.aNullableDouble, self.aNullableByteArray, self.aNullable4ByteArray, + self.aNullable8ByteArray, self.aNullableFloatArray, self.aNullableEnum, + self.anotherNullableEnum, self.aNullableString, self.aNullableObject, + self.allNullableTypes, self.list, self.stringList, self.intList, + self.doubleList, self.boolList, self.enumList, self.objectList, + self.listList, self.mapList, self.recursiveClassList, self.map, + self.stringMap, self.intMap, self.enumMap, self.objectMap, self.listMap, + self.mapMap, self.recursiveClassMap]; +} @end @implementation FLTAllNullableTypesWithoutRecursion @@ -838,6 +876,24 @@ - (NSUInteger)hash { result = result * 31 + FLTPigeonDeepHash(self.mapMap); return result; } +- (NSString *)description { + return [NSString + stringWithFormat: + @"FLTAllNullableTypesWithoutRecursion(aNullableBool: %@, aNullableInt: %@, " + @"aNullableInt64: %@, aNullableDouble: %@, aNullableByteArray: %@, aNullable4ByteArray: " + @"%@, aNullable8ByteArray: %@, aNullableFloatArray: %@, aNullableEnum: %@, " + @"anotherNullableEnum: %@, aNullableString: %@, aNullableObject: %@, list: %@, " + @"stringList: %@, intList: %@, doubleList: %@, boolList: %@, enumList: %@, objectList: " + @"%@, listList: %@, mapList: %@, map: %@, stringMap: %@, intMap: %@, enumMap: %@, " + @"objectMap: %@, listMap: %@, mapMap: %@)", + self.aNullableBool, self.aNullableInt, self.aNullableInt64, self.aNullableDouble, + self.aNullableByteArray, self.aNullable4ByteArray, self.aNullable8ByteArray, + self.aNullableFloatArray, self.aNullableEnum, self.anotherNullableEnum, + self.aNullableString, self.aNullableObject, self.list, self.stringList, self.intList, + self.doubleList, self.boolList, self.enumList, self.objectList, self.listList, + self.mapList, self.map, self.stringMap, self.intMap, self.enumMap, self.objectMap, + self.listMap, self.mapMap]; +} @end @implementation FLTAllClassesWrapper @@ -917,6 +973,15 @@ - (NSUInteger)hash { result = result * 31 + FLTPigeonDeepHash(self.nullableClassMap); return result; } +- (NSString *)description { + return + [NSString stringWithFormat:@"FLTAllClassesWrapper(allNullableTypes: %@, " + @"allNullableTypesWithoutRecursion: %@, allTypes: %@, classList: " + @"%@, nullableClassList: %@, classMap: %@, nullableClassMap: %@)", + self.allNullableTypes, self.allNullableTypesWithoutRecursion, + self.allTypes, self.classList, self.nullableClassList, + self.classMap, self.nullableClassMap]; +} @end @implementation FLTTestMessage @@ -954,6 +1019,9 @@ - (NSUInteger)hash { result = result * 31 + FLTPigeonDeepHash(self.testList); return result; } +- (NSString *)description { + return [NSString stringWithFormat:@"FLTTestMessage(testList: %@)", self.testList]; +} @end @interface FLTCoreTestsPigeonCodecReader : FlutterStandardReader @@ -1353,6 +1421,106 @@ void SetUpFLTHostIntegrationCoreApiWithSuffix(id binaryM } } /// Returns the passed list, to test serialization and deserialization. + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.pigeon_integration_tests." + @"HostIntegrationCoreApi.echoStringList", + messageChannelSuffix] + binaryMessenger:binaryMessenger + codec:FLTGetCoreTestsCodec()]; + if (api) { + NSCAssert( + [api respondsToSelector:@selector(echoStringList:error:)], + @"FLTHostIntegrationCoreApi api (%@) doesn't respond to @selector(echoStringList:error:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + NSArray *arg_stringList = GetNullableObjectAtIndex(args, 0); + FlutterError *error; + NSArray *output = [api echoStringList:arg_stringList error:&error]; + callback(wrapResult(output, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + /// Returns the passed list, to test serialization and deserialization. + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.pigeon_integration_tests." + @"HostIntegrationCoreApi.echoIntList", + messageChannelSuffix] + binaryMessenger:binaryMessenger + codec:FLTGetCoreTestsCodec()]; + if (api) { + NSCAssert( + [api respondsToSelector:@selector(echoIntList:error:)], + @"FLTHostIntegrationCoreApi api (%@) doesn't respond to @selector(echoIntList:error:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + NSArray *arg_intList = GetNullableObjectAtIndex(args, 0); + FlutterError *error; + NSArray *output = [api echoIntList:arg_intList error:&error]; + callback(wrapResult(output, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + /// Returns the passed list, to test serialization and deserialization. + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.pigeon_integration_tests." + @"HostIntegrationCoreApi.echoDoubleList", + messageChannelSuffix] + binaryMessenger:binaryMessenger + codec:FLTGetCoreTestsCodec()]; + if (api) { + NSCAssert( + [api respondsToSelector:@selector(echoDoubleList:error:)], + @"FLTHostIntegrationCoreApi api (%@) doesn't respond to @selector(echoDoubleList:error:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + NSArray *arg_doubleList = GetNullableObjectAtIndex(args, 0); + FlutterError *error; + NSArray *output = [api echoDoubleList:arg_doubleList error:&error]; + callback(wrapResult(output, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + /// Returns the passed list, to test serialization and deserialization. + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.pigeon_integration_tests." + @"HostIntegrationCoreApi.echoBoolList", + messageChannelSuffix] + binaryMessenger:binaryMessenger + codec:FLTGetCoreTestsCodec()]; + if (api) { + NSCAssert( + [api respondsToSelector:@selector(echoBoolList:error:)], + @"FLTHostIntegrationCoreApi api (%@) doesn't respond to @selector(echoBoolList:error:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + NSArray *arg_boolList = GetNullableObjectAtIndex(args, 0); + FlutterError *error; + NSArray *output = [api echoBoolList:arg_boolList error:&error]; + callback(wrapResult(output, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + /// Returns the passed list, to test serialization and deserialization. { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] initWithName:[NSString stringWithFormat:@"%@%@", diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/darwin/alternate_language_test_plugin/Sources/alternate_language_test_plugin/include/alternate_language_test_plugin/CoreTests.gen.h b/packages/pigeon/platform_tests/alternate_language_test_plugin/darwin/alternate_language_test_plugin/Sources/alternate_language_test_plugin/include/alternate_language_test_plugin/CoreTests.gen.h index 2b620a11104a..03be8ebb358d 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/darwin/alternate_language_test_plugin/Sources/alternate_language_test_plugin/include/alternate_language_test_plugin/CoreTests.gen.h +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/darwin/alternate_language_test_plugin/Sources/alternate_language_test_plugin/include/alternate_language_test_plugin/CoreTests.gen.h @@ -336,6 +336,26 @@ NSObject *FLTGetCoreTestsCodec(void); /// Returns the passed list, to test serialization and deserialization. /// /// @return `nil` only when `error != nil`. +- (nullable NSArray *)echoStringList:(NSArray *)stringList + error:(FlutterError *_Nullable *_Nonnull)error; +/// Returns the passed list, to test serialization and deserialization. +/// +/// @return `nil` only when `error != nil`. +- (nullable NSArray *)echoIntList:(NSArray *)intList + error:(FlutterError *_Nullable *_Nonnull)error; +/// Returns the passed list, to test serialization and deserialization. +/// +/// @return `nil` only when `error != nil`. +- (nullable NSArray *)echoDoubleList:(NSArray *)doubleList + error:(FlutterError *_Nullable *_Nonnull)error; +/// Returns the passed list, to test serialization and deserialization. +/// +/// @return `nil` only when `error != nil`. +- (nullable NSArray *)echoBoolList:(NSArray *)boolList + error:(FlutterError *_Nullable *_Nonnull)error; +/// Returns the passed list, to test serialization and deserialization. +/// +/// @return `nil` only when `error != nil`. - (nullable NSArray *)echoEnumList:(NSArray *)enumList error:(FlutterError *_Nullable *_Nonnull)error; /// Returns the passed list, to test serialization and deserialization. diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/AllDatatypesTest.m b/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/DataClassMethodsTest.m similarity index 92% rename from packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/AllDatatypesTest.m rename to packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/DataClassMethodsTest.m index 4e5b5b196f5a..dbe11c1a5aa7 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/AllDatatypesTest.m +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/DataClassMethodsTest.m @@ -10,11 +10,11 @@ #import "EchoMessenger.h" /////////////////////////////////////////////////////////////////////////////////////////// -@interface AllDatatypesTest : XCTestCase +@interface DataClassMethodsTest : XCTestCase @end /////////////////////////////////////////////////////////////////////////////////////////// -@implementation AllDatatypesTest +@implementation DataClassMethodsTest - (void)testAllNull { FLTAllNullableTypes *everything = [[FLTAllNullableTypes alloc] init]; @@ -114,6 +114,24 @@ - (void)testAllEquals { [self waitForExpectations:@[ expectation ] timeout:1.0]; } +- (void)testDescriptionFullOutput { + FLTAllNullableTypes *everything = [[FLTAllNullableTypes alloc] init]; + everything.aNullableBool = @NO; + everything.aNullableInt = @(1); + everything.aNullableDouble = @(2.0); + everything.aNullableString = @"123"; + everything.list = @[ @"string", @1 ]; + everything.stringMap = @{@"hello" : @"you", @"goodbye" : @"world"}; + + NSString *desc = everything.description; + XCTAssertTrue([desc hasPrefix:@"FLTAllNullableTypes("]); + XCTAssertTrue([desc containsString:@"aNullableBool: "]); + XCTAssertTrue([desc containsString:@"aNullableInt: "]); + XCTAssertTrue([desc containsString:@"aNullableDouble: "]); + XCTAssertTrue([desc containsString:@"123"]); + XCTAssertTrue([desc containsString:@"stringMap: "]); +} + - (void)testEquality { FLTAllNullableTypes *everything1 = [[FLTAllNullableTypes alloc] init]; everything1.aNullableBool = @NO; diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/integration_tests.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/integration_tests.dart index 55afaa5ac235..9ed43123a701 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/integration_tests.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/integration_tests.dart @@ -3265,75 +3265,87 @@ void runPigeonIntegrationTests(TargetGenerator targetGenerator) { TargetGenerator.swift, ]; - testWidgets('event channel sends continuous ints', (_) async { - final Stream events = streamInts(); - final List listEvents = await events.toList(); - for (final value in listEvents) { - expect(listEvents[value], value); - } - }, skip: !eventChannelSupported.contains(targetGenerator)); - - testWidgets('event channel handles extended sealed classes', (_) async { - final completer = Completer(); - var count = 0; - final Stream events = streamEvents(); - events.listen((PlatformEvent event) { - switch (event) { - case IntEvent(): - expect(event.value, 1); - expect(count, 0); - count++; - case StringEvent(): - expect(event.value, 'string'); - expect(count, 1); - count++; - case BoolEvent(): - expect(event.value, false); - expect(count, 2); - count++; - case DoubleEvent(): - expect(event.value, 3.14); - expect(count, 3); - count++; - case ObjectsEvent(): - expect(event.value, true); - expect(count, 4); - count++; - case EnumEvent(): - expect(event.value, EventEnum.fortyTwo); - expect(count, 5); - count++; - case ClassEvent(): - expect(event.value.aNullableInt, 0); - expect(count, 6); - count++; - completer.complete(); + testWidgets( + 'event channel sends continuous ints', + (_) async { + final Stream events = streamInts(); + final List listEvents = await events.toList(); + for (final value in listEvents) { + expect(listEvents[value], value); } - }); - await completer.future; - }, skip: !eventChannelSupported.contains(targetGenerator)); - - testWidgets('event channels handle multiple instances', (_) async { - final completer1 = Completer(); - final completer2 = Completer(); - final Stream events1 = streamConsistentNumbers(instanceName: '1'); - final Stream events2 = streamConsistentNumbers(instanceName: '2'); - - events1 - .listen((int event) { - expect(event, 1); - }) - .onDone(() => completer1.complete()); - - events2 - .listen((int event) { - expect(event, 2); - }) - .onDone(() => completer2.complete()); - - await completer1.future; - await completer2.future; - }, skip: !eventChannelSupported.contains(targetGenerator)); + }, + skip: !eventChannelSupported.contains(targetGenerator), + ); + + testWidgets( + 'event channel handles extended sealed classes', + (_) async { + final completer = Completer(); + var count = 0; + final Stream events = streamEvents(); + events.listen((PlatformEvent event) { + switch (event) { + case IntEvent(): + expect(event.value, 1); + expect(count, 0); + count++; + case StringEvent(): + expect(event.value, 'string'); + expect(count, 1); + count++; + case BoolEvent(): + expect(event.value, false); + expect(count, 2); + count++; + case DoubleEvent(): + expect(event.value, 3.14); + expect(count, 3); + count++; + case ObjectsEvent(): + expect(event.value, true); + expect(count, 4); + count++; + case EnumEvent(): + expect(event.value, EventEnum.fortyTwo); + expect(count, 5); + count++; + case ClassEvent(): + expect(event.value.aNullableInt, 0); + expect(count, 6); + count++; + completer.complete(); + } + }); + await completer.future; + }, + skip: !eventChannelSupported.contains(targetGenerator), + ); + + testWidgets( + 'event channels handle multiple instances', + (_) async { + final completer1 = Completer(); + final completer2 = Completer(); + final Stream events1 = streamConsistentNumbers(instanceName: '1'); + final Stream events2 = streamConsistentNumbers(instanceName: '2'); + + events1 + .listen((int event) { + expect(event, 1); + }) + .onDone(() => completer1.complete()); + + events2 + .listen((int event) { + expect(event, 2); + }) + .onDone(() => completer2.complete()); + + await completer1.future; + await completer2.future; + }, + skip: !eventChannelSupported.contains(targetGenerator), + ); } class _FlutterApiTestImplementation implements FlutterIntegrationCoreApi { diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/background_platform_channels.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/background_platform_channels.gen.dart index d6e49a4b33b3..1ba37b3eae22 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/background_platform_channels.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/background_platform_channels.gen.dart @@ -41,8 +41,8 @@ class _PigeonCodec extends StandardMessageCodec { } class BackgroundApi2Host { - /// Constructor for [BackgroundApi2Host]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default + /// Constructor for [BackgroundApi2Host]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. BackgroundApi2Host({ BinaryMessenger? binaryMessenger, diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/core_tests.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/core_tests.gen.dart index 482368add83b..c2cd765ca02f 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/core_tests.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/core_tests.gen.dart @@ -152,6 +152,11 @@ class UnusedClass { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'UnusedClass(aField: $aField)'; + } } /// A class containing all supported types. @@ -358,6 +363,11 @@ class AllTypes { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'AllTypes(aBool: $aBool, anInt: $anInt, anInt64: $anInt64, aDouble: $aDouble, aByteArray: $aByteArray, a4ByteArray: $a4ByteArray, a8ByteArray: $a8ByteArray, aFloatArray: $aFloatArray, anEnum: $anEnum, anotherEnum: $anotherEnum, aString: $aString, anObject: $anObject, list: $list, stringList: $stringList, intList: $intList, doubleList: $doubleList, boolList: $boolList, enumList: $enumList, objectList: $objectList, listList: $listList, mapList: $mapList, map: $map, stringMap: $stringMap, intMap: $intMap, enumMap: $enumMap, objectMap: $objectMap, listMap: $listMap, mapMap: $mapMap)'; + } } /// A class containing all supported nullable types. @@ -585,6 +595,11 @@ class AllNullableTypes { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'AllNullableTypes(aNullableBool: $aNullableBool, aNullableInt: $aNullableInt, aNullableInt64: $aNullableInt64, aNullableDouble: $aNullableDouble, aNullableByteArray: $aNullableByteArray, aNullable4ByteArray: $aNullable4ByteArray, aNullable8ByteArray: $aNullable8ByteArray, aNullableFloatArray: $aNullableFloatArray, aNullableEnum: $aNullableEnum, anotherNullableEnum: $anotherNullableEnum, aNullableString: $aNullableString, aNullableObject: $aNullableObject, allNullableTypes: $allNullableTypes, list: $list, stringList: $stringList, intList: $intList, doubleList: $doubleList, boolList: $boolList, enumList: $enumList, objectList: $objectList, listList: $listList, mapList: $mapList, recursiveClassList: $recursiveClassList, map: $map, stringMap: $stringMap, intMap: $intMap, enumMap: $enumMap, objectMap: $objectMap, listMap: $listMap, mapMap: $mapMap, recursiveClassMap: $recursiveClassMap)'; + } } /// The primary purpose for this class is to ensure coverage of Swift structs @@ -795,6 +810,11 @@ class AllNullableTypesWithoutRecursion { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'AllNullableTypesWithoutRecursion(aNullableBool: $aNullableBool, aNullableInt: $aNullableInt, aNullableInt64: $aNullableInt64, aNullableDouble: $aNullableDouble, aNullableByteArray: $aNullableByteArray, aNullable4ByteArray: $aNullable4ByteArray, aNullable8ByteArray: $aNullable8ByteArray, aNullableFloatArray: $aNullableFloatArray, aNullableEnum: $aNullableEnum, anotherNullableEnum: $anotherNullableEnum, aNullableString: $aNullableString, aNullableObject: $aNullableObject, list: $list, stringList: $stringList, intList: $intList, doubleList: $doubleList, boolList: $boolList, enumList: $enumList, objectList: $objectList, listList: $listList, mapList: $mapList, map: $map, stringMap: $stringMap, intMap: $intMap, enumMap: $enumMap, objectMap: $objectMap, listMap: $listMap, mapMap: $mapMap)'; + } } /// A class for testing nested class handling. @@ -883,6 +903,11 @@ class AllClassesWrapper { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'AllClassesWrapper(allNullableTypes: $allNullableTypes, allNullableTypesWithoutRecursion: $allNullableTypesWithoutRecursion, allTypes: $allTypes, classList: $classList, nullableClassList: $nullableClassList, classMap: $classMap, nullableClassMap: $nullableClassMap)'; + } } /// A data class containing a List, used in unit tests. @@ -919,6 +944,11 @@ class TestMessage { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'TestMessage(testList: $testList)'; + } } class _PigeonCodec extends StandardMessageCodec { @@ -987,8 +1017,8 @@ class _PigeonCodec extends StandardMessageCodec { /// The core interface that each host language plugin must implement in /// platform_test integration tests. class HostIntegrationCoreApi { - /// Constructor for [HostIntegrationCoreApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default + /// Constructor for [HostIntegrationCoreApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. HostIntegrationCoreApi({ BinaryMessenger? binaryMessenger, @@ -1258,6 +1288,94 @@ class HostIntegrationCoreApi { return pigeonVar_replyValue! as List; } + /// Returns the passed list, to test serialization and deserialization. + Future> echoStringList(List stringList) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoStringList$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [stringList], + ); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as List).cast(); + } + + /// Returns the passed list, to test serialization and deserialization. + Future> echoIntList(List intList) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoIntList$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [intList], + ); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as List).cast(); + } + + /// Returns the passed list, to test serialization and deserialization. + Future> echoDoubleList(List doubleList) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoDoubleList$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [doubleList], + ); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as List).cast(); + } + + /// Returns the passed list, to test serialization and deserialization. + Future> echoBoolList(List boolList) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoBoolList$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [boolList], + ); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as List).cast(); + } + /// Returns the passed list, to test serialization and deserialization. Future> echoEnumList(List enumList) async { final pigeonVar_channelName = @@ -6123,8 +6241,8 @@ abstract class FlutterIntegrationCoreApi { /// An API that can be implemented for minimal, compile-only tests. class HostTrivialApi { - /// Constructor for [HostTrivialApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default + /// Constructor for [HostTrivialApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. HostTrivialApi({ BinaryMessenger? binaryMessenger, @@ -6160,8 +6278,8 @@ class HostTrivialApi { /// A simple API implemented in some unit tests. class HostSmallApi { - /// Constructor for [HostSmallApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default + /// Constructor for [HostSmallApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. HostSmallApi({ BinaryMessenger? binaryMessenger, diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/enum.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/enum.gen.dart index 202b98268626..3e577db1832f 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/enum.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/enum.gen.dart @@ -165,6 +165,11 @@ class DataWithEnum { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'DataWithEnum(state: $state)'; + } } class _PigeonCodec extends StandardMessageCodec { @@ -201,8 +206,8 @@ class _PigeonCodec extends StandardMessageCodec { /// This comment is to test api documentation comments. class EnumApi2Host { - /// Constructor for [EnumApi2Host]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default + /// Constructor for [EnumApi2Host]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. EnumApi2Host({ BinaryMessenger? binaryMessenger, diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/event_channel_tests.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/event_channel_tests.gen.dart index 4734c4b0cdb0..41bbc7ef8351 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/event_channel_tests.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/event_channel_tests.gen.dart @@ -306,6 +306,11 @@ class EventAllNullableTypes { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'EventAllNullableTypes(aNullableBool: $aNullableBool, aNullableInt: $aNullableInt, aNullableInt64: $aNullableInt64, aNullableDouble: $aNullableDouble, aNullableByteArray: $aNullableByteArray, aNullable4ByteArray: $aNullable4ByteArray, aNullable8ByteArray: $aNullable8ByteArray, aNullableFloatArray: $aNullableFloatArray, aNullableEnum: $aNullableEnum, anotherNullableEnum: $anotherNullableEnum, aNullableString: $aNullableString, aNullableObject: $aNullableObject, allNullableTypes: $allNullableTypes, list: $list, stringList: $stringList, intList: $intList, doubleList: $doubleList, boolList: $boolList, enumList: $enumList, objectList: $objectList, listList: $listList, mapList: $mapList, recursiveClassList: $recursiveClassList, map: $map, stringMap: $stringMap, intMap: $intMap, enumMap: $enumMap, objectMap: $objectMap, listMap: $listMap, mapMap: $mapMap, recursiveClassMap: $recursiveClassMap)'; + } } sealed class PlatformEvent {} @@ -343,6 +348,11 @@ class IntEvent extends PlatformEvent { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'IntEvent(value: $value)'; + } } class StringEvent extends PlatformEvent { @@ -378,6 +388,11 @@ class StringEvent extends PlatformEvent { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'StringEvent(value: $value)'; + } } class BoolEvent extends PlatformEvent { @@ -413,6 +428,11 @@ class BoolEvent extends PlatformEvent { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'BoolEvent(value: $value)'; + } } class DoubleEvent extends PlatformEvent { @@ -448,6 +468,11 @@ class DoubleEvent extends PlatformEvent { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'DoubleEvent(value: $value)'; + } } class ObjectsEvent extends PlatformEvent { @@ -483,6 +508,11 @@ class ObjectsEvent extends PlatformEvent { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'ObjectsEvent(value: $value)'; + } } class EnumEvent extends PlatformEvent { @@ -518,6 +548,11 @@ class EnumEvent extends PlatformEvent { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'EnumEvent(value: $value)'; + } } class ClassEvent extends PlatformEvent { @@ -553,6 +588,11 @@ class ClassEvent extends PlatformEvent { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'ClassEvent(value: $value)'; + } } class _PigeonCodec extends StandardMessageCodec { diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/flutter_unittests.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/flutter_unittests.gen.dart index 3fe4b498ee2d..940a8df6993f 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/flutter_unittests.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/flutter_unittests.gen.dart @@ -134,6 +134,11 @@ class FlutterSearchRequest { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'FlutterSearchRequest(query: $query)'; + } } class FlutterSearchReply { @@ -174,6 +179,11 @@ class FlutterSearchReply { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'FlutterSearchReply(result: $result, error: $error)'; + } } class FlutterSearchRequests { @@ -209,6 +219,11 @@ class FlutterSearchRequests { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'FlutterSearchRequests(requests: $requests)'; + } } class FlutterSearchReplies { @@ -244,6 +259,11 @@ class FlutterSearchReplies { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'FlutterSearchReplies(replies: $replies)'; + } } class _PigeonCodec extends StandardMessageCodec { @@ -288,8 +308,8 @@ class _PigeonCodec extends StandardMessageCodec { } class Api { - /// Constructor for [Api]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default + /// Constructor for [Api]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. Api({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) : pigeonVar_binaryMessenger = binaryMessenger, diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/message.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/message.gen.dart index 9013d5973196..08b51cf0867d 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/message.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/message.gen.dart @@ -173,6 +173,11 @@ class MessageSearchRequest { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'MessageSearchRequest(query: $query, anInt: $anInt, aBool: $aBool)'; + } } /// This comment is to test class documentation comments. @@ -224,6 +229,11 @@ class MessageSearchReply { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'MessageSearchReply(result: $result, error: $error, state: $state)'; + } } /// This comment is to test class documentation comments. @@ -261,6 +271,11 @@ class MessageNested { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'MessageNested(request: $request)'; + } } class _PigeonCodec extends StandardMessageCodec { @@ -309,8 +324,8 @@ class _PigeonCodec extends StandardMessageCodec { /// /// This comment also tests multiple line comments. class MessageApi { - /// Constructor for [MessageApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default + /// Constructor for [MessageApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. MessageApi({ BinaryMessenger? binaryMessenger, @@ -371,8 +386,8 @@ class MessageApi { /// This comment is to test api documentation comments. class MessageNestedApi { - /// Constructor for [MessageNestedApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default + /// Constructor for [MessageNestedApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. MessageNestedApi({ BinaryMessenger? binaryMessenger, diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/multiple_arity.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/multiple_arity.gen.dart index 7b2ebf15d84e..f431295f9022 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/multiple_arity.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/multiple_arity.gen.dart @@ -74,8 +74,8 @@ class _PigeonCodec extends StandardMessageCodec { } class MultipleArityHostApi { - /// Constructor for [MultipleArityHostApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default + /// Constructor for [MultipleArityHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. MultipleArityHostApi({ BinaryMessenger? binaryMessenger, diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/non_null_fields.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/non_null_fields.gen.dart index 476917a52f9f..0af20b35e5cb 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/non_null_fields.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/non_null_fields.gen.dart @@ -151,6 +151,11 @@ class NonNullFieldSearchRequest { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'NonNullFieldSearchRequest(query: $query)'; + } } class ExtraData { @@ -192,6 +197,11 @@ class ExtraData { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'ExtraData(detailA: $detailA, detailB: $detailB)'; + } } class NonNullFieldSearchReply { @@ -251,6 +261,11 @@ class NonNullFieldSearchReply { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'NonNullFieldSearchReply(result: $result, error: $error, indices: $indices, extraData: $extraData, type: $type)'; + } } class _PigeonCodec extends StandardMessageCodec { @@ -296,8 +311,8 @@ class _PigeonCodec extends StandardMessageCodec { } class NonNullFieldHostApi { - /// Constructor for [NonNullFieldHostApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default + /// Constructor for [NonNullFieldHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. NonNullFieldHostApi({ BinaryMessenger? binaryMessenger, diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/null_fields.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/null_fields.gen.dart index e861dbaa62ed..a24a07771761 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/null_fields.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/null_fields.gen.dart @@ -156,6 +156,11 @@ class NullFieldsSearchRequest { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'NullFieldsSearchRequest(query: $query, identifier: $identifier)'; + } } class NullFieldsSearchReply { @@ -215,6 +220,11 @@ class NullFieldsSearchReply { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'NullFieldsSearchReply(result: $result, error: $error, indices: $indices, request: $request, type: $type)'; + } } class _PigeonCodec extends StandardMessageCodec { @@ -255,8 +265,8 @@ class _PigeonCodec extends StandardMessageCodec { } class NullFieldsHostApi { - /// Constructor for [NullFieldsHostApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default + /// Constructor for [NullFieldsHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. NullFieldsHostApi({ BinaryMessenger? binaryMessenger, diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/nullable_returns.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/nullable_returns.gen.dart index 2c9c03a02426..a55bcf80b0a2 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/nullable_returns.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/nullable_returns.gen.dart @@ -74,8 +74,8 @@ class _PigeonCodec extends StandardMessageCodec { } class NullableReturnHostApi { - /// Constructor for [NullableReturnHostApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default + /// Constructor for [NullableReturnHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. NullableReturnHostApi({ BinaryMessenger? binaryMessenger, @@ -150,8 +150,8 @@ abstract class NullableReturnFlutterApi { } class NullableArgHostApi { - /// Constructor for [NullableArgHostApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default + /// Constructor for [NullableArgHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. NullableArgHostApi({ BinaryMessenger? binaryMessenger, @@ -230,8 +230,8 @@ abstract class NullableArgFlutterApi { } class NullableCollectionReturnHostApi { - /// Constructor for [NullableCollectionReturnHostApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default + /// Constructor for [NullableCollectionReturnHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. NullableCollectionReturnHostApi({ BinaryMessenger? binaryMessenger, @@ -306,8 +306,8 @@ abstract class NullableCollectionReturnFlutterApi { } class NullableCollectionArgHostApi { - /// Constructor for [NullableCollectionArgHostApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default + /// Constructor for [NullableCollectionArgHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. NullableCollectionArgHostApi({ BinaryMessenger? binaryMessenger, diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/primitive.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/primitive.gen.dart index b86058696a44..618b132d5047 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/primitive.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/primitive.gen.dart @@ -74,8 +74,8 @@ class _PigeonCodec extends StandardMessageCodec { } class PrimitiveHostApi { - /// Constructor for [PrimitiveHostApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default + /// Constructor for [PrimitiveHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. PrimitiveHostApi({ BinaryMessenger? binaryMessenger, diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/test/equality_test.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/test/data_class_methods_test.dart similarity index 79% rename from packages/pigeon/platform_tests/shared_test_plugin_code/test/equality_test.dart rename to packages/pigeon/platform_tests/shared_test_plugin_code/test/data_class_methods_test.dart index 2fb8d597a3fa..6637744fbfe0 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/test/equality_test.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/test/data_class_methods_test.dart @@ -236,5 +236,12 @@ void main() { expect(withMapInList, withDifferentMapInList); }, ); + + test('AllTypes toString full output', () { + expect( + genericAllTypes.toString(), + 'AllTypes(aBool: true, anInt: 42, anInt64: 3000000000, aDouble: 3.14159, aByteArray: [1, 2, 3], a4ByteArray: [4, 5, 6], a8ByteArray: [7, 8, 9], aFloatArray: [2.71828, 3.14159], anEnum: AnEnum.fortyTwo, anotherEnum: AnotherEnum.justInCase, aString: Hello host!, anObject: 1, list: [Thing 1, 2, true, 3.14, null], stringList: [Thing 1, 2, true, 3.14], intList: [1, 2, 3, 4], doubleList: [1.0, 2.99999, 3.0, 3.14], boolList: [true, false, true, false], enumList: [AnEnum.one, AnEnum.two, AnEnum.three, AnEnum.fortyTwo, AnEnum.fourHundredTwentyTwo], objectList: [Thing 1, 2, true, 3.14], listList: [[Thing 1, 2, true, 3.14], [Thing 1, 2, true, 3.14], [1, 2, 3, 4], [1.0, 2.99999, 3.0, 3.14], [true, false, true, false], [AnEnum.one, AnEnum.two, AnEnum.three, AnEnum.fortyTwo, AnEnum.fourHundredTwentyTwo]], mapList: [{a: 1, b: 2.0, c: three, d: false}, {a: 1, b: 2.0, c: three, d: false}, {0.0: 0.0, 1.1: 2.0, 3.0: 0.3, -0.4: -0.2}, {0: 0, 1: 1, 2: 3, 4: -1}, {0: true, 1: false, 2: true}, {AnEnum.one: AnEnum.one, AnEnum.two: AnEnum.two, AnEnum.three: AnEnum.three, AnEnum.fortyTwo: AnEnum.fortyTwo}], map: {a: 1, b: 2.0, c: three, d: false}, stringMap: {a: 1, b: 2.0, c: three, d: false}, intMap: {0: 0, 1: 1, 2: 3, 4: -1}, enumMap: {AnEnum.one: AnEnum.one, AnEnum.two: AnEnum.two, AnEnum.three: AnEnum.three, AnEnum.fortyTwo: AnEnum.fortyTwo}, objectMap: {a: 1, b: 2.0, c: three, d: false}, listMap: {0: [Thing 1, 2, true, 3.14], 1: [Thing 1, 2, true, 3.14], 2: [1.0, 2.99999, 3.0, 3.14], 4: [1, 2, 3, 4], 5: [true, false, true, false], 6: [AnEnum.one, AnEnum.two, AnEnum.three, AnEnum.fortyTwo, AnEnum.fourHundredTwentyTwo]}, mapMap: {0: {a: 1, b: 2.0, c: three, d: false}, 1: {a: 1, b: 2.0, c: three, d: false}, 2: {0.0: 0.0, 1.1: 2.0, 3.0: 0.3, -0.4: -0.2}, 4: {0: 0, 1: 1, 2: 3, 4: -1}, 5: {0: true, 1: false, 2: true}, 6: {AnEnum.one: AnEnum.one, AnEnum.two: AnEnum.two, AnEnum.three: AnEnum.three, AnEnum.fortyTwo: AnEnum.fortyTwo}})', + ); + }); }); } diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/CoreTests.gen.kt b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/CoreTests.gen.kt index 938204b49782..a22c40a3c5f3 100644 --- a/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/CoreTests.gen.kt +++ b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/CoreTests.gen.kt @@ -251,6 +251,10 @@ data class UnusedClass(val aField: Any? = null) { result = 31 * result + CoreTestsPigeonUtils.deepHash(this.aField) return result } + + override fun toString(): String { + return "UnusedClass(aField=$aField)" + } } /** @@ -453,6 +457,10 @@ data class AllTypes( result = 31 * result + CoreTestsPigeonUtils.deepHash(this.mapMap) return result } + + override fun toString(): String { + return "AllTypes(aBool=$aBool, anInt=$anInt, anInt64=$anInt64, aDouble=$aDouble, aByteArray=${aByteArray.contentToString()}, a4ByteArray=${a4ByteArray.contentToString()}, a8ByteArray=${a8ByteArray.contentToString()}, aFloatArray=${aFloatArray.contentToString()}, anEnum=$anEnum, anotherEnum=$anotherEnum, aString=$aString, anObject=$anObject, list=$list, stringList=$stringList, intList=$intList, doubleList=$doubleList, boolList=$boolList, enumList=$enumList, objectList=$objectList, listList=$listList, mapList=$mapList, map=$map, stringMap=$stringMap, intMap=$intMap, enumMap=$enumMap, objectMap=$objectMap, listMap=$listMap, mapMap=$mapMap)" + } } /** @@ -673,6 +681,10 @@ data class AllNullableTypes( result = 31 * result + CoreTestsPigeonUtils.deepHash(this.recursiveClassMap) return result } + + override fun toString(): String { + return "AllNullableTypes(aNullableBool=$aNullableBool, aNullableInt=$aNullableInt, aNullableInt64=$aNullableInt64, aNullableDouble=$aNullableDouble, aNullableByteArray=${aNullableByteArray?.contentToString()}, aNullable4ByteArray=${aNullable4ByteArray?.contentToString()}, aNullable8ByteArray=${aNullable8ByteArray?.contentToString()}, aNullableFloatArray=${aNullableFloatArray?.contentToString()}, aNullableEnum=$aNullableEnum, anotherNullableEnum=$anotherNullableEnum, aNullableString=$aNullableString, aNullableObject=$aNullableObject, allNullableTypes=$allNullableTypes, list=$list, stringList=$stringList, intList=$intList, doubleList=$doubleList, boolList=$boolList, enumList=$enumList, objectList=$objectList, listList=$listList, mapList=$mapList, recursiveClassList=$recursiveClassList, map=$map, stringMap=$stringMap, intMap=$intMap, enumMap=$enumMap, objectMap=$objectMap, listMap=$listMap, mapMap=$mapMap, recursiveClassMap=$recursiveClassMap)" + } } /** @@ -876,6 +888,10 @@ data class AllNullableTypesWithoutRecursion( result = 31 * result + CoreTestsPigeonUtils.deepHash(this.mapMap) return result } + + override fun toString(): String { + return "AllNullableTypesWithoutRecursion(aNullableBool=$aNullableBool, aNullableInt=$aNullableInt, aNullableInt64=$aNullableInt64, aNullableDouble=$aNullableDouble, aNullableByteArray=${aNullableByteArray?.contentToString()}, aNullable4ByteArray=${aNullable4ByteArray?.contentToString()}, aNullable8ByteArray=${aNullable8ByteArray?.contentToString()}, aNullableFloatArray=${aNullableFloatArray?.contentToString()}, aNullableEnum=$aNullableEnum, anotherNullableEnum=$anotherNullableEnum, aNullableString=$aNullableString, aNullableObject=$aNullableObject, list=$list, stringList=$stringList, intList=$intList, doubleList=$doubleList, boolList=$boolList, enumList=$enumList, objectList=$objectList, listList=$listList, mapList=$mapList, map=$map, stringMap=$stringMap, intMap=$intMap, enumMap=$enumMap, objectMap=$objectMap, listMap=$listMap, mapMap=$mapMap)" + } } /** @@ -957,6 +973,10 @@ data class AllClassesWrapper( result = 31 * result + CoreTestsPigeonUtils.deepHash(this.nullableClassMap) return result } + + override fun toString(): String { + return "AllClassesWrapper(allNullableTypes=$allNullableTypes, allNullableTypesWithoutRecursion=$allNullableTypesWithoutRecursion, allTypes=$allTypes, classList=$classList, nullableClassList=$nullableClassList, classMap=$classMap, nullableClassMap=$nullableClassMap)" + } } /** @@ -994,6 +1014,10 @@ data class TestMessage(val testList: List? = null) { result = 31 * result + CoreTestsPigeonUtils.deepHash(this.testList) return result } + + override fun toString(): String { + return "TestMessage(testList=$testList)" + } } private open class CoreTestsPigeonCodec : StandardMessageCodec() { @@ -1100,6 +1124,14 @@ interface HostIntegrationCoreApi { /** Returns the passed list, to test serialization and deserialization. */ fun echoList(list: List): List /** Returns the passed list, to test serialization and deserialization. */ + fun echoStringList(stringList: List): List + /** Returns the passed list, to test serialization and deserialization. */ + fun echoIntList(intList: List): List + /** Returns the passed list, to test serialization and deserialization. */ + fun echoDoubleList(doubleList: List): List + /** Returns the passed list, to test serialization and deserialization. */ + fun echoBoolList(boolList: List): List + /** Returns the passed list, to test serialization and deserialization. */ fun echoEnumList(enumList: List): List /** Returns the passed list, to test serialization and deserialization. */ fun echoClassList(classList: List): List @@ -1817,6 +1849,94 @@ interface HostIntegrationCoreApi { channel.setMessageHandler(null) } } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoStringList$separatedMessageChannelSuffix", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val stringListArg = args[0] as List + val wrapped: List = + try { + listOf(api.echoStringList(stringListArg)) + } catch (exception: Throwable) { + CoreTestsPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoIntList$separatedMessageChannelSuffix", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val intListArg = args[0] as List + val wrapped: List = + try { + listOf(api.echoIntList(intListArg)) + } catch (exception: Throwable) { + CoreTestsPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoDoubleList$separatedMessageChannelSuffix", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val doubleListArg = args[0] as List + val wrapped: List = + try { + listOf(api.echoDoubleList(doubleListArg)) + } catch (exception: Throwable) { + CoreTestsPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoBoolList$separatedMessageChannelSuffix", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val boolListArg = args[0] as List + val wrapped: List = + try { + listOf(api.echoBoolList(boolListArg)) + } catch (exception: Throwable) { + CoreTestsPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } run { val channel = BasicMessageChannel( diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/EventChannelTests.gen.kt b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/EventChannelTests.gen.kt index 9e55d6984836..a9f3d6575308 100644 --- a/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/EventChannelTests.gen.kt +++ b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/EventChannelTests.gen.kt @@ -422,6 +422,10 @@ data class EventAllNullableTypes( result = 31 * result + EventChannelTestsPigeonUtils.deepHash(this.recursiveClassMap) return result } + + override fun toString(): String { + return "EventAllNullableTypes(aNullableBool=$aNullableBool, aNullableInt=$aNullableInt, aNullableInt64=$aNullableInt64, aNullableDouble=$aNullableDouble, aNullableByteArray=${aNullableByteArray?.contentToString()}, aNullable4ByteArray=${aNullable4ByteArray?.contentToString()}, aNullable8ByteArray=${aNullable8ByteArray?.contentToString()}, aNullableFloatArray=${aNullableFloatArray?.contentToString()}, aNullableEnum=$aNullableEnum, anotherNullableEnum=$anotherNullableEnum, aNullableString=$aNullableString, aNullableObject=$aNullableObject, allNullableTypes=$allNullableTypes, list=$list, stringList=$stringList, intList=$intList, doubleList=$doubleList, boolList=$boolList, enumList=$enumList, objectList=$objectList, listList=$listList, mapList=$mapList, recursiveClassList=$recursiveClassList, map=$map, stringMap=$stringMap, intMap=$intMap, enumMap=$enumMap, objectMap=$objectMap, listMap=$listMap, mapMap=$mapMap, recursiveClassMap=$recursiveClassMap)" + } } /** @@ -460,6 +464,10 @@ data class IntEvent(val value: Long) : PlatformEvent() { result = 31 * result + EventChannelTestsPigeonUtils.deepHash(this.value) return result } + + override fun toString(): String { + return "IntEvent(value=$value)" + } } /** Generated class from Pigeon that represents data sent in messages. */ @@ -493,6 +501,10 @@ data class StringEvent(val value: String) : PlatformEvent() { result = 31 * result + EventChannelTestsPigeonUtils.deepHash(this.value) return result } + + override fun toString(): String { + return "StringEvent(value=$value)" + } } /** Generated class from Pigeon that represents data sent in messages. */ @@ -526,6 +538,10 @@ data class BoolEvent(val value: Boolean) : PlatformEvent() { result = 31 * result + EventChannelTestsPigeonUtils.deepHash(this.value) return result } + + override fun toString(): String { + return "BoolEvent(value=$value)" + } } /** Generated class from Pigeon that represents data sent in messages. */ @@ -559,6 +575,10 @@ data class DoubleEvent(val value: Double) : PlatformEvent() { result = 31 * result + EventChannelTestsPigeonUtils.deepHash(this.value) return result } + + override fun toString(): String { + return "DoubleEvent(value=$value)" + } } /** Generated class from Pigeon that represents data sent in messages. */ @@ -592,6 +612,10 @@ data class ObjectsEvent(val value: Any) : PlatformEvent() { result = 31 * result + EventChannelTestsPigeonUtils.deepHash(this.value) return result } + + override fun toString(): String { + return "ObjectsEvent(value=$value)" + } } /** Generated class from Pigeon that represents data sent in messages. */ @@ -625,6 +649,10 @@ data class EnumEvent(val value: EventEnum) : PlatformEvent() { result = 31 * result + EventChannelTestsPigeonUtils.deepHash(this.value) return result } + + override fun toString(): String { + return "EnumEvent(value=$value)" + } } /** Generated class from Pigeon that represents data sent in messages. */ @@ -658,6 +686,10 @@ data class ClassEvent(val value: EventAllNullableTypes) : PlatformEvent() { result = 31 * result + EventChannelTestsPigeonUtils.deepHash(this.value) return result } + + override fun toString(): String { + return "ClassEvent(value=$value)" + } } private open class EventChannelTestsPigeonCodec : StandardMessageCodec() { diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/TestPlugin.kt b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/TestPlugin.kt index ea402e91d7a4..dd42cb4ddb90 100644 --- a/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/TestPlugin.kt +++ b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/TestPlugin.kt @@ -113,6 +113,22 @@ class TestPlugin : FlutterPlugin, HostIntegrationCoreApi { return list } + override fun echoStringList(stringList: List): List { + return stringList + } + + override fun echoIntList(intList: List): List { + return intList + } + + override fun echoDoubleList(doubleList: List): List { + return doubleList + } + + override fun echoBoolList(boolList: List): List { + return boolList + } + override fun echoEnumList(enumList: List): List { return enumList } diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/AllDatatypesTest.kt b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/DataClassMethodsTest.kt similarity index 89% rename from packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/AllDatatypesTest.kt rename to packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/DataClassMethodsTest.kt index 28a27c985604..ab9a69d91208 100644 --- a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/AllDatatypesTest.kt +++ b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/DataClassMethodsTest.kt @@ -15,7 +15,7 @@ import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue import org.junit.Test -internal class AllDatatypesTest { +internal class DataClassMethodsTest { @Test fun testNullValues() { @@ -292,4 +292,15 @@ internal class AllDatatypesTest { assertEquals(a, b) assertEquals(a.hashCode(), b.hashCode()) } + + @Test + fun `toString full output serialization`() { + // On the JVM/Android, LinkedHashMap and standard Collection string formatting + // are deterministic, preserving insertion order. Thus, exact string snapshotting + // provides safe, complete, and robust validation across all 31 fields. + val everything = getFullyPopulatedAllNullableTypes() + assertEquals( + "AllNullableTypes(aNullableBool=false, aNullableInt=1234, aNullableInt64=null, aNullableDouble=2.0, aNullableByteArray=[1, 2, 3, 4], aNullable4ByteArray=[1, 2, 3, 4], aNullable8ByteArray=[1, 2, 3, 4], aNullableFloatArray=[0.5, 0.25, 1.5, 1.25], aNullableEnum=TWO, anotherNullableEnum=JUST_IN_CASE, aNullableString=hello, aNullableObject=0, allNullableTypes=null, list=[1, 2, 3], stringList=[string, another one], intList=[1, 2], doubleList=[1.1, 2.2], boolList=[true, false], enumList=[ONE, TWO], objectList=[1, 2, 3], listList=[[string, another one], [string, another one]], mapList=[{hello=1234}, {hello=1234}], recursiveClassList=null, map={hello=1234}, stringMap={hello=you}, intMap={1=0}, enumMap={ONE=FORTY_TWO, TWO=FOUR_HUNDRED_TWENTY_TWO}, objectMap={hello=1234}, listMap={1=[string, another one]}, mapMap={1={}}, recursiveClassMap=null)", + everything.toString()) + } } diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/ListTest.kt b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/ListTest.kt index f91c0b747d3c..71b49995d0ee 100644 --- a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/ListTest.kt +++ b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/ListTest.kt @@ -43,4 +43,13 @@ class ListTest { assertTrue(didCall) } + + @Test + fun testToStringSnapshot() { + val msg = TestMessage(listOf("hello", 42)) + val str = msg.toString() + assertTrue(str.startsWith("TestMessage(testList=")) + assertTrue(str.contains("hello")) + assertTrue(str.contains("42")) + } } diff --git a/packages/pigeon/platform_tests/test_plugin/darwin/test_plugin/Sources/test_plugin/CoreTests.gen.swift b/packages/pigeon/platform_tests/test_plugin/darwin/test_plugin/Sources/test_plugin/CoreTests.gen.swift index 606d58783837..a7392aa9686f 100644 --- a/packages/pigeon/platform_tests/test_plugin/darwin/test_plugin/Sources/test_plugin/CoreTests.gen.swift +++ b/packages/pigeon/platform_tests/test_plugin/darwin/test_plugin/Sources/test_plugin/CoreTests.gen.swift @@ -65,122 +65,132 @@ private func createConnectionError(withChannelName channelName: String) -> Pigeo details: "") } -private func isNullish(_ value: Any?) -> Bool { - return value is NSNull || value == nil -} +enum CoreTestsPigeonInternal { + static func isNullish(_ value: Any?) -> Bool { + guard let innerValue = value else { + return true + } -private func nilOrValue(_ value: Any?) -> T? { - if value is NSNull { return nil } - return value as! T? -} + if case Optional.some(Optional.none) = value { + return true + } -private func doubleEqualsCoreTests(_ lhs: Double, _ rhs: Double) -> Bool { - return (lhs.isNaN && rhs.isNaN) || lhs == rhs -} + return innerValue is NSNull + } + static func doubleEquals(_ lhs: Double, _ rhs: Double) -> Bool { + return (lhs.isNaN && rhs.isNaN) || lhs == rhs + } -private func doubleHashCoreTests(_ value: Double, _ hasher: inout Hasher) { - if value.isNaN { - hasher.combine(0x7FF8_0000_0000_0000) - } else { - // Normalize -0.0 to 0.0 - hasher.combine(value == 0 ? 0 : value) + static func doubleHash(_ value: Double, _ hasher: inout Hasher) { + if value.isNaN { + hasher.combine(0x7FF8_0000_0000_0000) + } else { + // Normalize -0.0 to 0.0 + hasher.combine(value == 0 ? 0 : value) + } } -} -func deepEqualsCoreTests(_ lhs: Any?, _ rhs: Any?) -> Bool { - let cleanLhs = nilOrValue(lhs) as Any? - let cleanRhs = nilOrValue(rhs) as Any? - switch (cleanLhs, cleanRhs) { - case (nil, nil): - return true + static func deepEquals(_ lhs: Any?, _ rhs: Any?) -> Bool { + let cleanLhs = nilOrValue(lhs) as Any? + let cleanRhs = nilOrValue(rhs) as Any? + switch (cleanLhs, cleanRhs) { + case (nil, nil): + return true - case (nil, _), (_, nil): - return false + case (nil, _), (_, nil): + return false - case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs: - return true + case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs: + return true - case is (Void, Void): - return true + case is (Void, Void): + return true - case (let lhsArray, let rhsArray) as ([Any?], [Any?]): - guard lhsArray.count == rhsArray.count else { return false } - for (index, element) in lhsArray.enumerated() { - if !deepEqualsCoreTests(element, rhsArray[index]) { - return false + case (let lhsArray, let rhsArray) as ([Any?], [Any?]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !deepEquals(element, rhsArray[index]) { + return false + } } - } - return true + return true - case (let lhsArray, let rhsArray) as ([Double], [Double]): - guard lhsArray.count == rhsArray.count else { return false } - for (index, element) in lhsArray.enumerated() { - if !doubleEqualsCoreTests(element, rhsArray[index]) { - return false + case (let lhsArray, let rhsArray) as ([Double], [Double]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !doubleEquals(element, rhsArray[index]) { + return false + } } - } - return true + return true - case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): - guard lhsDictionary.count == rhsDictionary.count else { return false } - for (lhsKey, lhsValue) in lhsDictionary { - var found = false - for (rhsKey, rhsValue) in rhsDictionary { - if deepEqualsCoreTests(lhsKey, rhsKey) { - if deepEqualsCoreTests(lhsValue, rhsValue) { - found = true - break - } else { - return false + case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): + guard lhsDictionary.count == rhsDictionary.count else { return false } + for (lhsKey, lhsValue) in lhsDictionary { + var found = false + for (rhsKey, rhsValue) in rhsDictionary { + if deepEquals(lhsKey, rhsKey) { + if deepEquals(lhsValue, rhsValue) { + found = true + break + } else { + return false + } } } + if !found { return false } } - if !found { return false } - } - return true + return true + + case (let lhs as Double, let rhs as Double): + return doubleEquals(lhs, rhs) - case (let lhs as Double, let rhs as Double): - return doubleEqualsCoreTests(lhs, rhs) + case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable): + return lhsHashable == rhsHashable - case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable): - return lhsHashable == rhsHashable + default: + return false + } + } - default: - return false + static func deepHash(value: Any?, hasher: inout Hasher) { + let cleanValue = nilOrValue(value) as Any? + if let cleanValue = cleanValue { + if let doubleValue = cleanValue as? Double { + doubleHash(doubleValue, &hasher) + } else if let valueList = cleanValue as? [Any?] { + for item in valueList { + deepHash(value: item, hasher: &hasher) + } + } else if let valueList = cleanValue as? [Double] { + for item in valueList { + doubleHash(item, &hasher) + } + } else if let valueDict = cleanValue as? [AnyHashable: Any?] { + var result = 0 + for (key, value) in valueDict { + var entryKeyHasher = Hasher() + deepHash(value: key, hasher: &entryKeyHasher) + var entryValueHasher = Hasher() + deepHash(value: value, hasher: &entryValueHasher) + result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize()) + } + hasher.combine(result) + } else if let hashableValue = cleanValue as? AnyHashable { + hasher.combine(hashableValue) + } else { + hasher.combine(String(describing: cleanValue)) + } + } else { + hasher.combine(0) + } } + } -func deepHashCoreTests(value: Any?, hasher: inout Hasher) { - let cleanValue = nilOrValue(value) as Any? - if let cleanValue = cleanValue { - if let doubleValue = cleanValue as? Double { - doubleHashCoreTests(doubleValue, &hasher) - } else if let valueList = cleanValue as? [Any?] { - for item in valueList { - deepHashCoreTests(value: item, hasher: &hasher) - } - } else if let valueList = cleanValue as? [Double] { - for item in valueList { - doubleHashCoreTests(item, &hasher) - } - } else if let valueDict = cleanValue as? [AnyHashable: Any?] { - var result = 0 - for (key, value) in valueDict { - var entryKeyHasher = Hasher() - deepHashCoreTests(value: key, hasher: &entryKeyHasher) - var entryValueHasher = Hasher() - deepHashCoreTests(value: value, hasher: &entryValueHasher) - result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize()) - } - hasher.combine(result) - } else if let hashableValue = cleanValue as? AnyHashable { - hasher.combine(hashableValue) - } else { - hasher.combine(String(describing: cleanValue)) - } - } else { - hasher.combine(0) - } +private func nilOrValue(_ value: Any?) -> T? { + if value is NSNull { return nil } + return value as! T? } enum AnEnum: Int { @@ -196,7 +206,7 @@ enum AnotherEnum: Int { } /// Generated class from Pigeon that represents data sent in messages. -struct UnusedClass: Hashable { +struct UnusedClass: Hashable, CustomStringConvertible { var aField: Any? = nil // swift-format-ignore: AlwaysUseLowerCamelCase @@ -216,19 +226,23 @@ struct UnusedClass: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsCoreTests(lhs.aField, rhs.aField) + return CoreTestsPigeonInternal.deepEquals(lhs.aField, rhs.aField) } func hash(into hasher: inout Hasher) { hasher.combine("UnusedClass") - deepHashCoreTests(value: aField, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aField, hasher: &hasher) + } + + public var description: String { + return "UnusedClass(aField: \(String(describing: aField)))" } } /// A class containing all supported types. /// /// Generated class from Pigeon that represents data sent in messages. -struct AllTypes: Hashable { +struct AllTypes: Hashable, CustomStringConvertible { var aBool: Bool var anInt: Int64 var anInt64: Int64 @@ -356,70 +370,78 @@ struct AllTypes: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsCoreTests(lhs.aBool, rhs.aBool) && deepEqualsCoreTests(lhs.anInt, rhs.anInt) - && deepEqualsCoreTests(lhs.anInt64, rhs.anInt64) - && deepEqualsCoreTests(lhs.aDouble, rhs.aDouble) - && deepEqualsCoreTests(lhs.aByteArray, rhs.aByteArray) - && deepEqualsCoreTests(lhs.a4ByteArray, rhs.a4ByteArray) - && deepEqualsCoreTests(lhs.a8ByteArray, rhs.a8ByteArray) - && deepEqualsCoreTests(lhs.aFloatArray, rhs.aFloatArray) - && deepEqualsCoreTests(lhs.anEnum, rhs.anEnum) - && deepEqualsCoreTests(lhs.anotherEnum, rhs.anotherEnum) - && deepEqualsCoreTests(lhs.aString, rhs.aString) - && deepEqualsCoreTests(lhs.anObject, rhs.anObject) && deepEqualsCoreTests(lhs.list, rhs.list) - && deepEqualsCoreTests(lhs.stringList, rhs.stringList) - && deepEqualsCoreTests(lhs.intList, rhs.intList) - && deepEqualsCoreTests(lhs.doubleList, rhs.doubleList) - && deepEqualsCoreTests(lhs.boolList, rhs.boolList) - && deepEqualsCoreTests(lhs.enumList, rhs.enumList) - && deepEqualsCoreTests(lhs.objectList, rhs.objectList) - && deepEqualsCoreTests(lhs.listList, rhs.listList) - && deepEqualsCoreTests(lhs.mapList, rhs.mapList) && deepEqualsCoreTests(lhs.map, rhs.map) - && deepEqualsCoreTests(lhs.stringMap, rhs.stringMap) - && deepEqualsCoreTests(lhs.intMap, rhs.intMap) - && deepEqualsCoreTests(lhs.enumMap, rhs.enumMap) - && deepEqualsCoreTests(lhs.objectMap, rhs.objectMap) - && deepEqualsCoreTests(lhs.listMap, rhs.listMap) - && deepEqualsCoreTests(lhs.mapMap, rhs.mapMap) + return CoreTestsPigeonInternal.deepEquals(lhs.aBool, rhs.aBool) + && CoreTestsPigeonInternal.deepEquals(lhs.anInt, rhs.anInt) + && CoreTestsPigeonInternal.deepEquals(lhs.anInt64, rhs.anInt64) + && CoreTestsPigeonInternal.deepEquals(lhs.aDouble, rhs.aDouble) + && CoreTestsPigeonInternal.deepEquals(lhs.aByteArray, rhs.aByteArray) + && CoreTestsPigeonInternal.deepEquals(lhs.a4ByteArray, rhs.a4ByteArray) + && CoreTestsPigeonInternal.deepEquals(lhs.a8ByteArray, rhs.a8ByteArray) + && CoreTestsPigeonInternal.deepEquals(lhs.aFloatArray, rhs.aFloatArray) + && CoreTestsPigeonInternal.deepEquals(lhs.anEnum, rhs.anEnum) + && CoreTestsPigeonInternal.deepEquals(lhs.anotherEnum, rhs.anotherEnum) + && CoreTestsPigeonInternal.deepEquals(lhs.aString, rhs.aString) + && CoreTestsPigeonInternal.deepEquals(lhs.anObject, rhs.anObject) + && CoreTestsPigeonInternal.deepEquals(lhs.list, rhs.list) + && CoreTestsPigeonInternal.deepEquals(lhs.stringList, rhs.stringList) + && CoreTestsPigeonInternal.deepEquals(lhs.intList, rhs.intList) + && CoreTestsPigeonInternal.deepEquals(lhs.doubleList, rhs.doubleList) + && CoreTestsPigeonInternal.deepEquals(lhs.boolList, rhs.boolList) + && CoreTestsPigeonInternal.deepEquals(lhs.enumList, rhs.enumList) + && CoreTestsPigeonInternal.deepEquals(lhs.objectList, rhs.objectList) + && CoreTestsPigeonInternal.deepEquals(lhs.listList, rhs.listList) + && CoreTestsPigeonInternal.deepEquals(lhs.mapList, rhs.mapList) + && CoreTestsPigeonInternal.deepEquals(lhs.map, rhs.map) + && CoreTestsPigeonInternal.deepEquals(lhs.stringMap, rhs.stringMap) + && CoreTestsPigeonInternal.deepEquals(lhs.intMap, rhs.intMap) + && CoreTestsPigeonInternal.deepEquals(lhs.enumMap, rhs.enumMap) + && CoreTestsPigeonInternal.deepEquals(lhs.objectMap, rhs.objectMap) + && CoreTestsPigeonInternal.deepEquals(lhs.listMap, rhs.listMap) + && CoreTestsPigeonInternal.deepEquals(lhs.mapMap, rhs.mapMap) } func hash(into hasher: inout Hasher) { hasher.combine("AllTypes") - deepHashCoreTests(value: aBool, hasher: &hasher) - deepHashCoreTests(value: anInt, hasher: &hasher) - deepHashCoreTests(value: anInt64, hasher: &hasher) - deepHashCoreTests(value: aDouble, hasher: &hasher) - deepHashCoreTests(value: aByteArray, hasher: &hasher) - deepHashCoreTests(value: a4ByteArray, hasher: &hasher) - deepHashCoreTests(value: a8ByteArray, hasher: &hasher) - deepHashCoreTests(value: aFloatArray, hasher: &hasher) - deepHashCoreTests(value: anEnum, hasher: &hasher) - deepHashCoreTests(value: anotherEnum, hasher: &hasher) - deepHashCoreTests(value: aString, hasher: &hasher) - deepHashCoreTests(value: anObject, hasher: &hasher) - deepHashCoreTests(value: list, hasher: &hasher) - deepHashCoreTests(value: stringList, hasher: &hasher) - deepHashCoreTests(value: intList, hasher: &hasher) - deepHashCoreTests(value: doubleList, hasher: &hasher) - deepHashCoreTests(value: boolList, hasher: &hasher) - deepHashCoreTests(value: enumList, hasher: &hasher) - deepHashCoreTests(value: objectList, hasher: &hasher) - deepHashCoreTests(value: listList, hasher: &hasher) - deepHashCoreTests(value: mapList, hasher: &hasher) - deepHashCoreTests(value: map, hasher: &hasher) - deepHashCoreTests(value: stringMap, hasher: &hasher) - deepHashCoreTests(value: intMap, hasher: &hasher) - deepHashCoreTests(value: enumMap, hasher: &hasher) - deepHashCoreTests(value: objectMap, hasher: &hasher) - deepHashCoreTests(value: listMap, hasher: &hasher) - deepHashCoreTests(value: mapMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aBool, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: anInt, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: anInt64, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aDouble, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aByteArray, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: a4ByteArray, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: a8ByteArray, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aFloatArray, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: anEnum, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: anotherEnum, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aString, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: anObject, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: list, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: stringList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: intList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: doubleList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: boolList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: enumList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: objectList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: listList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: mapList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: map, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: stringMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: intMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: enumMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: objectMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: listMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: mapMap, hasher: &hasher) + } + + public var description: String { + return + "AllTypes(aBool: \(String(describing: aBool)), anInt: \(String(describing: anInt)), anInt64: \(String(describing: anInt64)), aDouble: \(String(describing: aDouble)), aByteArray: \(String(describing: aByteArray)), a4ByteArray: \(String(describing: a4ByteArray)), a8ByteArray: \(String(describing: a8ByteArray)), aFloatArray: \(String(describing: aFloatArray)), anEnum: \(String(describing: anEnum)), anotherEnum: \(String(describing: anotherEnum)), aString: \(String(describing: aString)), anObject: \(String(describing: anObject)), list: \(String(describing: list)), stringList: \(String(describing: stringList)), intList: \(String(describing: intList)), doubleList: \(String(describing: doubleList)), boolList: \(String(describing: boolList)), enumList: \(String(describing: enumList)), objectList: \(String(describing: objectList)), listList: \(String(describing: listList)), mapList: \(String(describing: mapList)), map: \(String(describing: map)), stringMap: \(String(describing: stringMap)), intMap: \(String(describing: intMap)), enumMap: \(String(describing: enumMap)), objectMap: \(String(describing: objectMap)), listMap: \(String(describing: listMap)), mapMap: \(String(describing: mapMap)))" } } /// A class containing all supported nullable types. /// /// Generated class from Pigeon that represents data sent in messages. -class AllNullableTypes: Hashable { +class AllNullableTypes: Hashable, CustomStringConvertible { init( aNullableBool: Bool? = nil, aNullableInt: Int64? = nil, @@ -627,71 +649,77 @@ class AllNullableTypes: Hashable { if lhs === rhs { return true } - return deepEqualsCoreTests(lhs.aNullableBool, rhs.aNullableBool) - && deepEqualsCoreTests(lhs.aNullableInt, rhs.aNullableInt) - && deepEqualsCoreTests(lhs.aNullableInt64, rhs.aNullableInt64) - && deepEqualsCoreTests(lhs.aNullableDouble, rhs.aNullableDouble) - && deepEqualsCoreTests(lhs.aNullableByteArray, rhs.aNullableByteArray) - && deepEqualsCoreTests(lhs.aNullable4ByteArray, rhs.aNullable4ByteArray) - && deepEqualsCoreTests(lhs.aNullable8ByteArray, rhs.aNullable8ByteArray) - && deepEqualsCoreTests(lhs.aNullableFloatArray, rhs.aNullableFloatArray) - && deepEqualsCoreTests(lhs.aNullableEnum, rhs.aNullableEnum) - && deepEqualsCoreTests(lhs.anotherNullableEnum, rhs.anotherNullableEnum) - && deepEqualsCoreTests(lhs.aNullableString, rhs.aNullableString) - && deepEqualsCoreTests(lhs.aNullableObject, rhs.aNullableObject) - && deepEqualsCoreTests(lhs.allNullableTypes, rhs.allNullableTypes) - && deepEqualsCoreTests(lhs.list, rhs.list) - && deepEqualsCoreTests(lhs.stringList, rhs.stringList) - && deepEqualsCoreTests(lhs.intList, rhs.intList) - && deepEqualsCoreTests(lhs.doubleList, rhs.doubleList) - && deepEqualsCoreTests(lhs.boolList, rhs.boolList) - && deepEqualsCoreTests(lhs.enumList, rhs.enumList) - && deepEqualsCoreTests(lhs.objectList, rhs.objectList) - && deepEqualsCoreTests(lhs.listList, rhs.listList) - && deepEqualsCoreTests(lhs.mapList, rhs.mapList) - && deepEqualsCoreTests(lhs.recursiveClassList, rhs.recursiveClassList) - && deepEqualsCoreTests(lhs.map, rhs.map) && deepEqualsCoreTests(lhs.stringMap, rhs.stringMap) - && deepEqualsCoreTests(lhs.intMap, rhs.intMap) - && deepEqualsCoreTests(lhs.enumMap, rhs.enumMap) - && deepEqualsCoreTests(lhs.objectMap, rhs.objectMap) - && deepEqualsCoreTests(lhs.listMap, rhs.listMap) - && deepEqualsCoreTests(lhs.mapMap, rhs.mapMap) - && deepEqualsCoreTests(lhs.recursiveClassMap, rhs.recursiveClassMap) + return CoreTestsPigeonInternal.deepEquals(lhs.aNullableBool, rhs.aNullableBool) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullableInt, rhs.aNullableInt) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullableInt64, rhs.aNullableInt64) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullableDouble, rhs.aNullableDouble) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullableByteArray, rhs.aNullableByteArray) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullable4ByteArray, rhs.aNullable4ByteArray) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullable8ByteArray, rhs.aNullable8ByteArray) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullableFloatArray, rhs.aNullableFloatArray) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullableEnum, rhs.aNullableEnum) + && CoreTestsPigeonInternal.deepEquals(lhs.anotherNullableEnum, rhs.anotherNullableEnum) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullableString, rhs.aNullableString) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullableObject, rhs.aNullableObject) + && CoreTestsPigeonInternal.deepEquals(lhs.allNullableTypes, rhs.allNullableTypes) + && CoreTestsPigeonInternal.deepEquals(lhs.list, rhs.list) + && CoreTestsPigeonInternal.deepEquals(lhs.stringList, rhs.stringList) + && CoreTestsPigeonInternal.deepEquals(lhs.intList, rhs.intList) + && CoreTestsPigeonInternal.deepEquals(lhs.doubleList, rhs.doubleList) + && CoreTestsPigeonInternal.deepEquals(lhs.boolList, rhs.boolList) + && CoreTestsPigeonInternal.deepEquals(lhs.enumList, rhs.enumList) + && CoreTestsPigeonInternal.deepEquals(lhs.objectList, rhs.objectList) + && CoreTestsPigeonInternal.deepEquals(lhs.listList, rhs.listList) + && CoreTestsPigeonInternal.deepEquals(lhs.mapList, rhs.mapList) + && CoreTestsPigeonInternal.deepEquals(lhs.recursiveClassList, rhs.recursiveClassList) + && CoreTestsPigeonInternal.deepEquals(lhs.map, rhs.map) + && CoreTestsPigeonInternal.deepEquals(lhs.stringMap, rhs.stringMap) + && CoreTestsPigeonInternal.deepEquals(lhs.intMap, rhs.intMap) + && CoreTestsPigeonInternal.deepEquals(lhs.enumMap, rhs.enumMap) + && CoreTestsPigeonInternal.deepEquals(lhs.objectMap, rhs.objectMap) + && CoreTestsPigeonInternal.deepEquals(lhs.listMap, rhs.listMap) + && CoreTestsPigeonInternal.deepEquals(lhs.mapMap, rhs.mapMap) + && CoreTestsPigeonInternal.deepEquals(lhs.recursiveClassMap, rhs.recursiveClassMap) } func hash(into hasher: inout Hasher) { hasher.combine("AllNullableTypes") - deepHashCoreTests(value: aNullableBool, hasher: &hasher) - deepHashCoreTests(value: aNullableInt, hasher: &hasher) - deepHashCoreTests(value: aNullableInt64, hasher: &hasher) - deepHashCoreTests(value: aNullableDouble, hasher: &hasher) - deepHashCoreTests(value: aNullableByteArray, hasher: &hasher) - deepHashCoreTests(value: aNullable4ByteArray, hasher: &hasher) - deepHashCoreTests(value: aNullable8ByteArray, hasher: &hasher) - deepHashCoreTests(value: aNullableFloatArray, hasher: &hasher) - deepHashCoreTests(value: aNullableEnum, hasher: &hasher) - deepHashCoreTests(value: anotherNullableEnum, hasher: &hasher) - deepHashCoreTests(value: aNullableString, hasher: &hasher) - deepHashCoreTests(value: aNullableObject, hasher: &hasher) - deepHashCoreTests(value: allNullableTypes, hasher: &hasher) - deepHashCoreTests(value: list, hasher: &hasher) - deepHashCoreTests(value: stringList, hasher: &hasher) - deepHashCoreTests(value: intList, hasher: &hasher) - deepHashCoreTests(value: doubleList, hasher: &hasher) - deepHashCoreTests(value: boolList, hasher: &hasher) - deepHashCoreTests(value: enumList, hasher: &hasher) - deepHashCoreTests(value: objectList, hasher: &hasher) - deepHashCoreTests(value: listList, hasher: &hasher) - deepHashCoreTests(value: mapList, hasher: &hasher) - deepHashCoreTests(value: recursiveClassList, hasher: &hasher) - deepHashCoreTests(value: map, hasher: &hasher) - deepHashCoreTests(value: stringMap, hasher: &hasher) - deepHashCoreTests(value: intMap, hasher: &hasher) - deepHashCoreTests(value: enumMap, hasher: &hasher) - deepHashCoreTests(value: objectMap, hasher: &hasher) - deepHashCoreTests(value: listMap, hasher: &hasher) - deepHashCoreTests(value: mapMap, hasher: &hasher) - deepHashCoreTests(value: recursiveClassMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableBool, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableInt, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableInt64, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableDouble, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableByteArray, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullable4ByteArray, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullable8ByteArray, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableFloatArray, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableEnum, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: anotherNullableEnum, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableString, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableObject, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: allNullableTypes, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: list, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: stringList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: intList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: doubleList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: boolList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: enumList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: objectList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: listList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: mapList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: recursiveClassList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: map, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: stringMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: intMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: enumMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: objectMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: listMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: mapMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: recursiveClassMap, hasher: &hasher) + } + + public var description: String { + return + "AllNullableTypes(aNullableBool: \(String(describing: aNullableBool)), aNullableInt: \(String(describing: aNullableInt)), aNullableInt64: \(String(describing: aNullableInt64)), aNullableDouble: \(String(describing: aNullableDouble)), aNullableByteArray: \(String(describing: aNullableByteArray)), aNullable4ByteArray: \(String(describing: aNullable4ByteArray)), aNullable8ByteArray: \(String(describing: aNullable8ByteArray)), aNullableFloatArray: \(String(describing: aNullableFloatArray)), aNullableEnum: \(String(describing: aNullableEnum)), anotherNullableEnum: \(String(describing: anotherNullableEnum)), aNullableString: \(String(describing: aNullableString)), aNullableObject: \(String(describing: aNullableObject)), allNullableTypes: \(String(describing: allNullableTypes)), list: \(String(describing: list)), stringList: \(String(describing: stringList)), intList: \(String(describing: intList)), doubleList: \(String(describing: doubleList)), boolList: \(String(describing: boolList)), enumList: \(String(describing: enumList)), objectList: \(String(describing: objectList)), listList: \(String(describing: listList)), mapList: \(String(describing: mapList)), recursiveClassList: \(String(describing: recursiveClassList)), map: \(String(describing: map)), stringMap: \(String(describing: stringMap)), intMap: \(String(describing: intMap)), enumMap: \(String(describing: enumMap)), objectMap: \(String(describing: objectMap)), listMap: \(String(describing: listMap)), mapMap: \(String(describing: mapMap)), recursiveClassMap: \(String(describing: recursiveClassMap)))" } } @@ -700,7 +728,7 @@ class AllNullableTypes: Hashable { /// test Swift classes. /// /// Generated class from Pigeon that represents data sent in messages. -struct AllNullableTypesWithoutRecursion: Hashable { +struct AllNullableTypesWithoutRecursion: Hashable, CustomStringConvertible { var aNullableBool: Bool? = nil var aNullableInt: Int64? = nil var aNullableInt64: Int64? = nil @@ -830,65 +858,71 @@ struct AllNullableTypesWithoutRecursion: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsCoreTests(lhs.aNullableBool, rhs.aNullableBool) - && deepEqualsCoreTests(lhs.aNullableInt, rhs.aNullableInt) - && deepEqualsCoreTests(lhs.aNullableInt64, rhs.aNullableInt64) - && deepEqualsCoreTests(lhs.aNullableDouble, rhs.aNullableDouble) - && deepEqualsCoreTests(lhs.aNullableByteArray, rhs.aNullableByteArray) - && deepEqualsCoreTests(lhs.aNullable4ByteArray, rhs.aNullable4ByteArray) - && deepEqualsCoreTests(lhs.aNullable8ByteArray, rhs.aNullable8ByteArray) - && deepEqualsCoreTests(lhs.aNullableFloatArray, rhs.aNullableFloatArray) - && deepEqualsCoreTests(lhs.aNullableEnum, rhs.aNullableEnum) - && deepEqualsCoreTests(lhs.anotherNullableEnum, rhs.anotherNullableEnum) - && deepEqualsCoreTests(lhs.aNullableString, rhs.aNullableString) - && deepEqualsCoreTests(lhs.aNullableObject, rhs.aNullableObject) - && deepEqualsCoreTests(lhs.list, rhs.list) - && deepEqualsCoreTests(lhs.stringList, rhs.stringList) - && deepEqualsCoreTests(lhs.intList, rhs.intList) - && deepEqualsCoreTests(lhs.doubleList, rhs.doubleList) - && deepEqualsCoreTests(lhs.boolList, rhs.boolList) - && deepEqualsCoreTests(lhs.enumList, rhs.enumList) - && deepEqualsCoreTests(lhs.objectList, rhs.objectList) - && deepEqualsCoreTests(lhs.listList, rhs.listList) - && deepEqualsCoreTests(lhs.mapList, rhs.mapList) && deepEqualsCoreTests(lhs.map, rhs.map) - && deepEqualsCoreTests(lhs.stringMap, rhs.stringMap) - && deepEqualsCoreTests(lhs.intMap, rhs.intMap) - && deepEqualsCoreTests(lhs.enumMap, rhs.enumMap) - && deepEqualsCoreTests(lhs.objectMap, rhs.objectMap) - && deepEqualsCoreTests(lhs.listMap, rhs.listMap) - && deepEqualsCoreTests(lhs.mapMap, rhs.mapMap) + return CoreTestsPigeonInternal.deepEquals(lhs.aNullableBool, rhs.aNullableBool) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullableInt, rhs.aNullableInt) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullableInt64, rhs.aNullableInt64) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullableDouble, rhs.aNullableDouble) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullableByteArray, rhs.aNullableByteArray) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullable4ByteArray, rhs.aNullable4ByteArray) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullable8ByteArray, rhs.aNullable8ByteArray) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullableFloatArray, rhs.aNullableFloatArray) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullableEnum, rhs.aNullableEnum) + && CoreTestsPigeonInternal.deepEquals(lhs.anotherNullableEnum, rhs.anotherNullableEnum) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullableString, rhs.aNullableString) + && CoreTestsPigeonInternal.deepEquals(lhs.aNullableObject, rhs.aNullableObject) + && CoreTestsPigeonInternal.deepEquals(lhs.list, rhs.list) + && CoreTestsPigeonInternal.deepEquals(lhs.stringList, rhs.stringList) + && CoreTestsPigeonInternal.deepEquals(lhs.intList, rhs.intList) + && CoreTestsPigeonInternal.deepEquals(lhs.doubleList, rhs.doubleList) + && CoreTestsPigeonInternal.deepEquals(lhs.boolList, rhs.boolList) + && CoreTestsPigeonInternal.deepEquals(lhs.enumList, rhs.enumList) + && CoreTestsPigeonInternal.deepEquals(lhs.objectList, rhs.objectList) + && CoreTestsPigeonInternal.deepEquals(lhs.listList, rhs.listList) + && CoreTestsPigeonInternal.deepEquals(lhs.mapList, rhs.mapList) + && CoreTestsPigeonInternal.deepEquals(lhs.map, rhs.map) + && CoreTestsPigeonInternal.deepEquals(lhs.stringMap, rhs.stringMap) + && CoreTestsPigeonInternal.deepEquals(lhs.intMap, rhs.intMap) + && CoreTestsPigeonInternal.deepEquals(lhs.enumMap, rhs.enumMap) + && CoreTestsPigeonInternal.deepEquals(lhs.objectMap, rhs.objectMap) + && CoreTestsPigeonInternal.deepEquals(lhs.listMap, rhs.listMap) + && CoreTestsPigeonInternal.deepEquals(lhs.mapMap, rhs.mapMap) } func hash(into hasher: inout Hasher) { hasher.combine("AllNullableTypesWithoutRecursion") - deepHashCoreTests(value: aNullableBool, hasher: &hasher) - deepHashCoreTests(value: aNullableInt, hasher: &hasher) - deepHashCoreTests(value: aNullableInt64, hasher: &hasher) - deepHashCoreTests(value: aNullableDouble, hasher: &hasher) - deepHashCoreTests(value: aNullableByteArray, hasher: &hasher) - deepHashCoreTests(value: aNullable4ByteArray, hasher: &hasher) - deepHashCoreTests(value: aNullable8ByteArray, hasher: &hasher) - deepHashCoreTests(value: aNullableFloatArray, hasher: &hasher) - deepHashCoreTests(value: aNullableEnum, hasher: &hasher) - deepHashCoreTests(value: anotherNullableEnum, hasher: &hasher) - deepHashCoreTests(value: aNullableString, hasher: &hasher) - deepHashCoreTests(value: aNullableObject, hasher: &hasher) - deepHashCoreTests(value: list, hasher: &hasher) - deepHashCoreTests(value: stringList, hasher: &hasher) - deepHashCoreTests(value: intList, hasher: &hasher) - deepHashCoreTests(value: doubleList, hasher: &hasher) - deepHashCoreTests(value: boolList, hasher: &hasher) - deepHashCoreTests(value: enumList, hasher: &hasher) - deepHashCoreTests(value: objectList, hasher: &hasher) - deepHashCoreTests(value: listList, hasher: &hasher) - deepHashCoreTests(value: mapList, hasher: &hasher) - deepHashCoreTests(value: map, hasher: &hasher) - deepHashCoreTests(value: stringMap, hasher: &hasher) - deepHashCoreTests(value: intMap, hasher: &hasher) - deepHashCoreTests(value: enumMap, hasher: &hasher) - deepHashCoreTests(value: objectMap, hasher: &hasher) - deepHashCoreTests(value: listMap, hasher: &hasher) - deepHashCoreTests(value: mapMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableBool, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableInt, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableInt64, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableDouble, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableByteArray, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullable4ByteArray, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullable8ByteArray, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableFloatArray, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableEnum, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: anotherNullableEnum, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableString, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: aNullableObject, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: list, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: stringList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: intList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: doubleList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: boolList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: enumList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: objectList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: listList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: mapList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: map, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: stringMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: intMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: enumMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: objectMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: listMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: mapMap, hasher: &hasher) + } + + public var description: String { + return + "AllNullableTypesWithoutRecursion(aNullableBool: \(String(describing: aNullableBool)), aNullableInt: \(String(describing: aNullableInt)), aNullableInt64: \(String(describing: aNullableInt64)), aNullableDouble: \(String(describing: aNullableDouble)), aNullableByteArray: \(String(describing: aNullableByteArray)), aNullable4ByteArray: \(String(describing: aNullable4ByteArray)), aNullable8ByteArray: \(String(describing: aNullable8ByteArray)), aNullableFloatArray: \(String(describing: aNullableFloatArray)), aNullableEnum: \(String(describing: aNullableEnum)), anotherNullableEnum: \(String(describing: anotherNullableEnum)), aNullableString: \(String(describing: aNullableString)), aNullableObject: \(String(describing: aNullableObject)), list: \(String(describing: list)), stringList: \(String(describing: stringList)), intList: \(String(describing: intList)), doubleList: \(String(describing: doubleList)), boolList: \(String(describing: boolList)), enumList: \(String(describing: enumList)), objectList: \(String(describing: objectList)), listList: \(String(describing: listList)), mapList: \(String(describing: mapList)), map: \(String(describing: map)), stringMap: \(String(describing: stringMap)), intMap: \(String(describing: intMap)), enumMap: \(String(describing: enumMap)), objectMap: \(String(describing: objectMap)), listMap: \(String(describing: listMap)), mapMap: \(String(describing: mapMap)))" } } @@ -899,7 +933,7 @@ struct AllNullableTypesWithoutRecursion: Hashable { /// than `AllTypes` when testing doesn't require both (ie. testing null classes). /// /// Generated class from Pigeon that represents data sent in messages. -struct AllClassesWrapper: Hashable { +struct AllClassesWrapper: Hashable, CustomStringConvertible { var allNullableTypes: AllNullableTypes var allNullableTypesWithoutRecursion: AllNullableTypesWithoutRecursion? = nil var allTypes: AllTypes? = nil @@ -945,32 +979,37 @@ struct AllClassesWrapper: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsCoreTests(lhs.allNullableTypes, rhs.allNullableTypes) - && deepEqualsCoreTests( + return CoreTestsPigeonInternal.deepEquals(lhs.allNullableTypes, rhs.allNullableTypes) + && CoreTestsPigeonInternal.deepEquals( lhs.allNullableTypesWithoutRecursion, rhs.allNullableTypesWithoutRecursion) - && deepEqualsCoreTests(lhs.allTypes, rhs.allTypes) - && deepEqualsCoreTests(lhs.classList, rhs.classList) - && deepEqualsCoreTests(lhs.nullableClassList, rhs.nullableClassList) - && deepEqualsCoreTests(lhs.classMap, rhs.classMap) - && deepEqualsCoreTests(lhs.nullableClassMap, rhs.nullableClassMap) + && CoreTestsPigeonInternal.deepEquals(lhs.allTypes, rhs.allTypes) + && CoreTestsPigeonInternal.deepEquals(lhs.classList, rhs.classList) + && CoreTestsPigeonInternal.deepEquals(lhs.nullableClassList, rhs.nullableClassList) + && CoreTestsPigeonInternal.deepEquals(lhs.classMap, rhs.classMap) + && CoreTestsPigeonInternal.deepEquals(lhs.nullableClassMap, rhs.nullableClassMap) } func hash(into hasher: inout Hasher) { hasher.combine("AllClassesWrapper") - deepHashCoreTests(value: allNullableTypes, hasher: &hasher) - deepHashCoreTests(value: allNullableTypesWithoutRecursion, hasher: &hasher) - deepHashCoreTests(value: allTypes, hasher: &hasher) - deepHashCoreTests(value: classList, hasher: &hasher) - deepHashCoreTests(value: nullableClassList, hasher: &hasher) - deepHashCoreTests(value: classMap, hasher: &hasher) - deepHashCoreTests(value: nullableClassMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: allNullableTypes, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: allNullableTypesWithoutRecursion, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: allTypes, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: classList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: nullableClassList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: classMap, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: nullableClassMap, hasher: &hasher) + } + + public var description: String { + return + "AllClassesWrapper(allNullableTypes: \(String(describing: allNullableTypes)), allNullableTypesWithoutRecursion: \(String(describing: allNullableTypesWithoutRecursion)), allTypes: \(String(describing: allTypes)), classList: \(String(describing: classList)), nullableClassList: \(String(describing: nullableClassList)), classMap: \(String(describing: classMap)), nullableClassMap: \(String(describing: nullableClassMap)))" } } /// A data class containing a List, used in unit tests. /// /// Generated class from Pigeon that represents data sent in messages. -struct TestMessage: Hashable { +struct TestMessage: Hashable, CustomStringConvertible { var testList: [Any?]? = nil // swift-format-ignore: AlwaysUseLowerCamelCase @@ -990,12 +1029,16 @@ struct TestMessage: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsCoreTests(lhs.testList, rhs.testList) + return CoreTestsPigeonInternal.deepEquals(lhs.testList, rhs.testList) } func hash(into hasher: inout Hasher) { hasher.combine("TestMessage") - deepHashCoreTests(value: testList, hasher: &hasher) + CoreTestsPigeonInternal.deepHash(value: testList, hasher: &hasher) + } + + public var description: String { + return "TestMessage(testList: \(String(describing: testList)))" } } @@ -1109,6 +1152,14 @@ protocol HostIntegrationCoreApi { /// Returns the passed list, to test serialization and deserialization. func echo(_ list: [Any?]) throws -> [Any?] /// Returns the passed list, to test serialization and deserialization. + func echo(stringList: [String?]) throws -> [String?] + /// Returns the passed list, to test serialization and deserialization. + func echo(intList: [Int64?]) throws -> [Int64?] + /// Returns the passed list, to test serialization and deserialization. + func echo(doubleList: [Double?]) throws -> [Double?] + /// Returns the passed list, to test serialization and deserialization. + func echo(boolList: [Bool?]) throws -> [Bool?] + /// Returns the passed list, to test serialization and deserialization. func echo(enumList: [AnEnum?]) throws -> [AnEnum?] /// Returns the passed list, to test serialization and deserialization. func echo(classList: [AllNullableTypes?]) throws -> [AllNullableTypes?] @@ -1685,6 +1736,82 @@ class HostIntegrationCoreApiSetup { echoListChannel.setMessageHandler(nil) } /// Returns the passed list, to test serialization and deserialization. + let echoStringListChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoStringList\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + echoStringListChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let stringListArg = args[0] as! [String?] + do { + let result = try api.echo(stringList: stringListArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + echoStringListChannel.setMessageHandler(nil) + } + /// Returns the passed list, to test serialization and deserialization. + let echoIntListChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoIntList\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + echoIntListChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let intListArg = args[0] as! [Int64?] + do { + let result = try api.echo(intList: intListArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + echoIntListChannel.setMessageHandler(nil) + } + /// Returns the passed list, to test serialization and deserialization. + let echoDoubleListChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoDoubleList\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + echoDoubleListChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let doubleListArg = args[0] as! [Double?] + do { + let result = try api.echo(doubleList: doubleListArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + echoDoubleListChannel.setMessageHandler(nil) + } + /// Returns the passed list, to test serialization and deserialization. + let echoBoolListChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoBoolList\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + echoBoolListChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let boolListArg = args[0] as! [Bool?] + do { + let result = try api.echo(boolList: boolListArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + echoBoolListChannel.setMessageHandler(nil) + } + /// Returns the passed list, to test serialization and deserialization. let echoEnumListChannel = FlutterBasicMessageChannel( name: "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoEnumList\(channelSuffix)", @@ -4558,6 +4685,7 @@ class HostIntegrationCoreApiSetup { } } } + /// The core interface that the Dart platform_test code implements for host /// integration tests to call into. /// @@ -6253,6 +6381,7 @@ class HostSmallApiSetup { } } } + /// A simple API called in some unit tests. /// /// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift. diff --git a/packages/pigeon/platform_tests/test_plugin/darwin/test_plugin/Sources/test_plugin/EventChannelTests.gen.swift b/packages/pigeon/platform_tests/test_plugin/darwin/test_plugin/Sources/test_plugin/EventChannelTests.gen.swift index da3e19626382..a41edd2fb053 100644 --- a/packages/pigeon/platform_tests/test_plugin/darwin/test_plugin/Sources/test_plugin/EventChannelTests.gen.swift +++ b/packages/pigeon/platform_tests/test_plugin/darwin/test_plugin/Sources/test_plugin/EventChannelTests.gen.swift @@ -33,122 +33,132 @@ final class EventChannelTestsError: Error { } } -private func isNullish(_ value: Any?) -> Bool { - return value is NSNull || value == nil -} +enum EventChannelTestsPigeonInternal { + static func isNullish(_ value: Any?) -> Bool { + guard let innerValue = value else { + return true + } -private func nilOrValue(_ value: Any?) -> T? { - if value is NSNull { return nil } - return value as! T? -} + if case Optional.some(Optional.none) = value { + return true + } -private func doubleEqualsEventChannelTests(_ lhs: Double, _ rhs: Double) -> Bool { - return (lhs.isNaN && rhs.isNaN) || lhs == rhs -} + return innerValue is NSNull + } + static func doubleEquals(_ lhs: Double, _ rhs: Double) -> Bool { + return (lhs.isNaN && rhs.isNaN) || lhs == rhs + } -private func doubleHashEventChannelTests(_ value: Double, _ hasher: inout Hasher) { - if value.isNaN { - hasher.combine(0x7FF8_0000_0000_0000) - } else { - // Normalize -0.0 to 0.0 - hasher.combine(value == 0 ? 0 : value) + static func doubleHash(_ value: Double, _ hasher: inout Hasher) { + if value.isNaN { + hasher.combine(0x7FF8_0000_0000_0000) + } else { + // Normalize -0.0 to 0.0 + hasher.combine(value == 0 ? 0 : value) + } } -} -func deepEqualsEventChannelTests(_ lhs: Any?, _ rhs: Any?) -> Bool { - let cleanLhs = nilOrValue(lhs) as Any? - let cleanRhs = nilOrValue(rhs) as Any? - switch (cleanLhs, cleanRhs) { - case (nil, nil): - return true + static func deepEquals(_ lhs: Any?, _ rhs: Any?) -> Bool { + let cleanLhs = nilOrValue(lhs) as Any? + let cleanRhs = nilOrValue(rhs) as Any? + switch (cleanLhs, cleanRhs) { + case (nil, nil): + return true - case (nil, _), (_, nil): - return false + case (nil, _), (_, nil): + return false - case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs: - return true + case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs: + return true - case is (Void, Void): - return true + case is (Void, Void): + return true - case (let lhsArray, let rhsArray) as ([Any?], [Any?]): - guard lhsArray.count == rhsArray.count else { return false } - for (index, element) in lhsArray.enumerated() { - if !deepEqualsEventChannelTests(element, rhsArray[index]) { - return false + case (let lhsArray, let rhsArray) as ([Any?], [Any?]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !deepEquals(element, rhsArray[index]) { + return false + } } - } - return true + return true - case (let lhsArray, let rhsArray) as ([Double], [Double]): - guard lhsArray.count == rhsArray.count else { return false } - for (index, element) in lhsArray.enumerated() { - if !doubleEqualsEventChannelTests(element, rhsArray[index]) { - return false + case (let lhsArray, let rhsArray) as ([Double], [Double]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !doubleEquals(element, rhsArray[index]) { + return false + } } - } - return true - - case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): - guard lhsDictionary.count == rhsDictionary.count else { return false } - for (lhsKey, lhsValue) in lhsDictionary { - var found = false - for (rhsKey, rhsValue) in rhsDictionary { - if deepEqualsEventChannelTests(lhsKey, rhsKey) { - if deepEqualsEventChannelTests(lhsValue, rhsValue) { - found = true - break - } else { - return false + return true + + case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): + guard lhsDictionary.count == rhsDictionary.count else { return false } + for (lhsKey, lhsValue) in lhsDictionary { + var found = false + for (rhsKey, rhsValue) in rhsDictionary { + if deepEquals(lhsKey, rhsKey) { + if deepEquals(lhsValue, rhsValue) { + found = true + break + } else { + return false + } } } + if !found { return false } } - if !found { return false } - } - return true + return true - case (let lhs as Double, let rhs as Double): - return doubleEqualsEventChannelTests(lhs, rhs) + case (let lhs as Double, let rhs as Double): + return doubleEquals(lhs, rhs) - case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable): - return lhsHashable == rhsHashable + case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable): + return lhsHashable == rhsHashable - default: - return false + default: + return false + } } -} -func deepHashEventChannelTests(value: Any?, hasher: inout Hasher) { - let cleanValue = nilOrValue(value) as Any? - if let cleanValue = cleanValue { - if let doubleValue = cleanValue as? Double { - doubleHashEventChannelTests(doubleValue, &hasher) - } else if let valueList = cleanValue as? [Any?] { - for item in valueList { - deepHashEventChannelTests(value: item, hasher: &hasher) - } - } else if let valueList = cleanValue as? [Double] { - for item in valueList { - doubleHashEventChannelTests(item, &hasher) - } - } else if let valueDict = cleanValue as? [AnyHashable: Any?] { - var result = 0 - for (key, value) in valueDict { - var entryKeyHasher = Hasher() - deepHashEventChannelTests(value: key, hasher: &entryKeyHasher) - var entryValueHasher = Hasher() - deepHashEventChannelTests(value: value, hasher: &entryValueHasher) - result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize()) + static func deepHash(value: Any?, hasher: inout Hasher) { + let cleanValue = nilOrValue(value) as Any? + if let cleanValue = cleanValue { + if let doubleValue = cleanValue as? Double { + doubleHash(doubleValue, &hasher) + } else if let valueList = cleanValue as? [Any?] { + for item in valueList { + deepHash(value: item, hasher: &hasher) + } + } else if let valueList = cleanValue as? [Double] { + for item in valueList { + doubleHash(item, &hasher) + } + } else if let valueDict = cleanValue as? [AnyHashable: Any?] { + var result = 0 + for (key, value) in valueDict { + var entryKeyHasher = Hasher() + deepHash(value: key, hasher: &entryKeyHasher) + var entryValueHasher = Hasher() + deepHash(value: value, hasher: &entryValueHasher) + result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize()) + } + hasher.combine(result) + } else if let hashableValue = cleanValue as? AnyHashable { + hasher.combine(hashableValue) + } else { + hasher.combine(String(describing: cleanValue)) } - hasher.combine(result) - } else if let hashableValue = cleanValue as? AnyHashable { - hasher.combine(hashableValue) } else { - hasher.combine(String(describing: cleanValue)) + hasher.combine(0) } - } else { - hasher.combine(0) } + +} + +private func nilOrValue(_ value: Any?) -> T? { + if value is NSNull { return nil } + return value as! T? } enum EventEnum: Int { @@ -166,7 +176,7 @@ enum AnotherEventEnum: Int { /// A class containing all supported nullable types. /// /// Generated class from Pigeon that represents data sent in messages. -class EventAllNullableTypes: Hashable { +class EventAllNullableTypes: Hashable, CustomStringConvertible { init( aNullableBool: Bool? = nil, aNullableInt: Int64? = nil, @@ -374,72 +384,81 @@ class EventAllNullableTypes: Hashable { if lhs === rhs { return true } - return deepEqualsEventChannelTests(lhs.aNullableBool, rhs.aNullableBool) - && deepEqualsEventChannelTests(lhs.aNullableInt, rhs.aNullableInt) - && deepEqualsEventChannelTests(lhs.aNullableInt64, rhs.aNullableInt64) - && deepEqualsEventChannelTests(lhs.aNullableDouble, rhs.aNullableDouble) - && deepEqualsEventChannelTests(lhs.aNullableByteArray, rhs.aNullableByteArray) - && deepEqualsEventChannelTests(lhs.aNullable4ByteArray, rhs.aNullable4ByteArray) - && deepEqualsEventChannelTests(lhs.aNullable8ByteArray, rhs.aNullable8ByteArray) - && deepEqualsEventChannelTests(lhs.aNullableFloatArray, rhs.aNullableFloatArray) - && deepEqualsEventChannelTests(lhs.aNullableEnum, rhs.aNullableEnum) - && deepEqualsEventChannelTests(lhs.anotherNullableEnum, rhs.anotherNullableEnum) - && deepEqualsEventChannelTests(lhs.aNullableString, rhs.aNullableString) - && deepEqualsEventChannelTests(lhs.aNullableObject, rhs.aNullableObject) - && deepEqualsEventChannelTests(lhs.allNullableTypes, rhs.allNullableTypes) - && deepEqualsEventChannelTests(lhs.list, rhs.list) - && deepEqualsEventChannelTests(lhs.stringList, rhs.stringList) - && deepEqualsEventChannelTests(lhs.intList, rhs.intList) - && deepEqualsEventChannelTests(lhs.doubleList, rhs.doubleList) - && deepEqualsEventChannelTests(lhs.boolList, rhs.boolList) - && deepEqualsEventChannelTests(lhs.enumList, rhs.enumList) - && deepEqualsEventChannelTests(lhs.objectList, rhs.objectList) - && deepEqualsEventChannelTests(lhs.listList, rhs.listList) - && deepEqualsEventChannelTests(lhs.mapList, rhs.mapList) - && deepEqualsEventChannelTests(lhs.recursiveClassList, rhs.recursiveClassList) - && deepEqualsEventChannelTests(lhs.map, rhs.map) - && deepEqualsEventChannelTests(lhs.stringMap, rhs.stringMap) - && deepEqualsEventChannelTests(lhs.intMap, rhs.intMap) - && deepEqualsEventChannelTests(lhs.enumMap, rhs.enumMap) - && deepEqualsEventChannelTests(lhs.objectMap, rhs.objectMap) - && deepEqualsEventChannelTests(lhs.listMap, rhs.listMap) - && deepEqualsEventChannelTests(lhs.mapMap, rhs.mapMap) - && deepEqualsEventChannelTests(lhs.recursiveClassMap, rhs.recursiveClassMap) + return EventChannelTestsPigeonInternal.deepEquals(lhs.aNullableBool, rhs.aNullableBool) + && EventChannelTestsPigeonInternal.deepEquals(lhs.aNullableInt, rhs.aNullableInt) + && EventChannelTestsPigeonInternal.deepEquals(lhs.aNullableInt64, rhs.aNullableInt64) + && EventChannelTestsPigeonInternal.deepEquals(lhs.aNullableDouble, rhs.aNullableDouble) + && EventChannelTestsPigeonInternal.deepEquals(lhs.aNullableByteArray, rhs.aNullableByteArray) + && EventChannelTestsPigeonInternal.deepEquals( + lhs.aNullable4ByteArray, rhs.aNullable4ByteArray) + && EventChannelTestsPigeonInternal.deepEquals( + lhs.aNullable8ByteArray, rhs.aNullable8ByteArray) + && EventChannelTestsPigeonInternal.deepEquals( + lhs.aNullableFloatArray, rhs.aNullableFloatArray) + && EventChannelTestsPigeonInternal.deepEquals(lhs.aNullableEnum, rhs.aNullableEnum) + && EventChannelTestsPigeonInternal.deepEquals( + lhs.anotherNullableEnum, rhs.anotherNullableEnum) + && EventChannelTestsPigeonInternal.deepEquals(lhs.aNullableString, rhs.aNullableString) + && EventChannelTestsPigeonInternal.deepEquals(lhs.aNullableObject, rhs.aNullableObject) + && EventChannelTestsPigeonInternal.deepEquals(lhs.allNullableTypes, rhs.allNullableTypes) + && EventChannelTestsPigeonInternal.deepEquals(lhs.list, rhs.list) + && EventChannelTestsPigeonInternal.deepEquals(lhs.stringList, rhs.stringList) + && EventChannelTestsPigeonInternal.deepEquals(lhs.intList, rhs.intList) + && EventChannelTestsPigeonInternal.deepEquals(lhs.doubleList, rhs.doubleList) + && EventChannelTestsPigeonInternal.deepEquals(lhs.boolList, rhs.boolList) + && EventChannelTestsPigeonInternal.deepEquals(lhs.enumList, rhs.enumList) + && EventChannelTestsPigeonInternal.deepEquals(lhs.objectList, rhs.objectList) + && EventChannelTestsPigeonInternal.deepEquals(lhs.listList, rhs.listList) + && EventChannelTestsPigeonInternal.deepEquals(lhs.mapList, rhs.mapList) + && EventChannelTestsPigeonInternal.deepEquals(lhs.recursiveClassList, rhs.recursiveClassList) + && EventChannelTestsPigeonInternal.deepEquals(lhs.map, rhs.map) + && EventChannelTestsPigeonInternal.deepEquals(lhs.stringMap, rhs.stringMap) + && EventChannelTestsPigeonInternal.deepEquals(lhs.intMap, rhs.intMap) + && EventChannelTestsPigeonInternal.deepEquals(lhs.enumMap, rhs.enumMap) + && EventChannelTestsPigeonInternal.deepEquals(lhs.objectMap, rhs.objectMap) + && EventChannelTestsPigeonInternal.deepEquals(lhs.listMap, rhs.listMap) + && EventChannelTestsPigeonInternal.deepEquals(lhs.mapMap, rhs.mapMap) + && EventChannelTestsPigeonInternal.deepEquals(lhs.recursiveClassMap, rhs.recursiveClassMap) } func hash(into hasher: inout Hasher) { hasher.combine("EventAllNullableTypes") - deepHashEventChannelTests(value: aNullableBool, hasher: &hasher) - deepHashEventChannelTests(value: aNullableInt, hasher: &hasher) - deepHashEventChannelTests(value: aNullableInt64, hasher: &hasher) - deepHashEventChannelTests(value: aNullableDouble, hasher: &hasher) - deepHashEventChannelTests(value: aNullableByteArray, hasher: &hasher) - deepHashEventChannelTests(value: aNullable4ByteArray, hasher: &hasher) - deepHashEventChannelTests(value: aNullable8ByteArray, hasher: &hasher) - deepHashEventChannelTests(value: aNullableFloatArray, hasher: &hasher) - deepHashEventChannelTests(value: aNullableEnum, hasher: &hasher) - deepHashEventChannelTests(value: anotherNullableEnum, hasher: &hasher) - deepHashEventChannelTests(value: aNullableString, hasher: &hasher) - deepHashEventChannelTests(value: aNullableObject, hasher: &hasher) - deepHashEventChannelTests(value: allNullableTypes, hasher: &hasher) - deepHashEventChannelTests(value: list, hasher: &hasher) - deepHashEventChannelTests(value: stringList, hasher: &hasher) - deepHashEventChannelTests(value: intList, hasher: &hasher) - deepHashEventChannelTests(value: doubleList, hasher: &hasher) - deepHashEventChannelTests(value: boolList, hasher: &hasher) - deepHashEventChannelTests(value: enumList, hasher: &hasher) - deepHashEventChannelTests(value: objectList, hasher: &hasher) - deepHashEventChannelTests(value: listList, hasher: &hasher) - deepHashEventChannelTests(value: mapList, hasher: &hasher) - deepHashEventChannelTests(value: recursiveClassList, hasher: &hasher) - deepHashEventChannelTests(value: map, hasher: &hasher) - deepHashEventChannelTests(value: stringMap, hasher: &hasher) - deepHashEventChannelTests(value: intMap, hasher: &hasher) - deepHashEventChannelTests(value: enumMap, hasher: &hasher) - deepHashEventChannelTests(value: objectMap, hasher: &hasher) - deepHashEventChannelTests(value: listMap, hasher: &hasher) - deepHashEventChannelTests(value: mapMap, hasher: &hasher) - deepHashEventChannelTests(value: recursiveClassMap, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: aNullableBool, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: aNullableInt, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: aNullableInt64, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: aNullableDouble, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: aNullableByteArray, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: aNullable4ByteArray, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: aNullable8ByteArray, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: aNullableFloatArray, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: aNullableEnum, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: anotherNullableEnum, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: aNullableString, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: aNullableObject, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: allNullableTypes, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: list, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: stringList, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: intList, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: doubleList, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: boolList, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: enumList, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: objectList, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: listList, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: mapList, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: recursiveClassList, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: map, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: stringMap, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: intMap, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: enumMap, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: objectMap, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: listMap, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: mapMap, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: recursiveClassMap, hasher: &hasher) + } + + public var description: String { + return + "EventAllNullableTypes(aNullableBool: \(String(describing: aNullableBool)), aNullableInt: \(String(describing: aNullableInt)), aNullableInt64: \(String(describing: aNullableInt64)), aNullableDouble: \(String(describing: aNullableDouble)), aNullableByteArray: \(String(describing: aNullableByteArray)), aNullable4ByteArray: \(String(describing: aNullable4ByteArray)), aNullable8ByteArray: \(String(describing: aNullable8ByteArray)), aNullableFloatArray: \(String(describing: aNullableFloatArray)), aNullableEnum: \(String(describing: aNullableEnum)), anotherNullableEnum: \(String(describing: anotherNullableEnum)), aNullableString: \(String(describing: aNullableString)), aNullableObject: \(String(describing: aNullableObject)), allNullableTypes: \(String(describing: allNullableTypes)), list: \(String(describing: list)), stringList: \(String(describing: stringList)), intList: \(String(describing: intList)), doubleList: \(String(describing: doubleList)), boolList: \(String(describing: boolList)), enumList: \(String(describing: enumList)), objectList: \(String(describing: objectList)), listList: \(String(describing: listList)), mapList: \(String(describing: mapList)), recursiveClassList: \(String(describing: recursiveClassList)), map: \(String(describing: map)), stringMap: \(String(describing: stringMap)), intMap: \(String(describing: intMap)), enumMap: \(String(describing: enumMap)), objectMap: \(String(describing: objectMap)), listMap: \(String(describing: listMap)), mapMap: \(String(describing: mapMap)), recursiveClassMap: \(String(describing: recursiveClassMap)))" } } @@ -470,12 +489,16 @@ struct IntEvent: PlatformEvent { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsEventChannelTests(lhs.value, rhs.value) + return EventChannelTestsPigeonInternal.deepEquals(lhs.value, rhs.value) } func hash(into hasher: inout Hasher) { hasher.combine("IntEvent") - deepHashEventChannelTests(value: value, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: value, hasher: &hasher) + } + + public var description: String { + return "IntEvent(value: \(String(describing: value)))" } } @@ -500,12 +523,16 @@ struct StringEvent: PlatformEvent { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsEventChannelTests(lhs.value, rhs.value) + return EventChannelTestsPigeonInternal.deepEquals(lhs.value, rhs.value) } func hash(into hasher: inout Hasher) { hasher.combine("StringEvent") - deepHashEventChannelTests(value: value, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: value, hasher: &hasher) + } + + public var description: String { + return "StringEvent(value: \(String(describing: value)))" } } @@ -530,12 +557,16 @@ struct BoolEvent: PlatformEvent { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsEventChannelTests(lhs.value, rhs.value) + return EventChannelTestsPigeonInternal.deepEquals(lhs.value, rhs.value) } func hash(into hasher: inout Hasher) { hasher.combine("BoolEvent") - deepHashEventChannelTests(value: value, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: value, hasher: &hasher) + } + + public var description: String { + return "BoolEvent(value: \(String(describing: value)))" } } @@ -560,12 +591,16 @@ struct DoubleEvent: PlatformEvent { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsEventChannelTests(lhs.value, rhs.value) + return EventChannelTestsPigeonInternal.deepEquals(lhs.value, rhs.value) } func hash(into hasher: inout Hasher) { hasher.combine("DoubleEvent") - deepHashEventChannelTests(value: value, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: value, hasher: &hasher) + } + + public var description: String { + return "DoubleEvent(value: \(String(describing: value)))" } } @@ -590,12 +625,16 @@ struct ObjectsEvent: PlatformEvent { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsEventChannelTests(lhs.value, rhs.value) + return EventChannelTestsPigeonInternal.deepEquals(lhs.value, rhs.value) } func hash(into hasher: inout Hasher) { hasher.combine("ObjectsEvent") - deepHashEventChannelTests(value: value, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: value, hasher: &hasher) + } + + public var description: String { + return "ObjectsEvent(value: \(String(describing: value)))" } } @@ -620,12 +659,16 @@ struct EnumEvent: PlatformEvent { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsEventChannelTests(lhs.value, rhs.value) + return EventChannelTestsPigeonInternal.deepEquals(lhs.value, rhs.value) } func hash(into hasher: inout Hasher) { hasher.combine("EnumEvent") - deepHashEventChannelTests(value: value, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: value, hasher: &hasher) + } + + public var description: String { + return "EnumEvent(value: \(String(describing: value)))" } } @@ -650,12 +693,16 @@ struct ClassEvent: PlatformEvent { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsEventChannelTests(lhs.value, rhs.value) + return EventChannelTestsPigeonInternal.deepEquals(lhs.value, rhs.value) } func hash(into hasher: inout Hasher) { hasher.combine("ClassEvent") - deepHashEventChannelTests(value: value, hasher: &hasher) + EventChannelTestsPigeonInternal.deepHash(value: value, hasher: &hasher) + } + + public var description: String { + return "ClassEvent(value: \(String(describing: value)))" } } diff --git a/packages/pigeon/platform_tests/test_plugin/darwin/test_plugin/Sources/test_plugin/ProxyApiTests.gen.swift b/packages/pigeon/platform_tests/test_plugin/darwin/test_plugin/Sources/test_plugin/ProxyApiTests.gen.swift index 5eb4b81803ad..c77dc71f58b3 100644 --- a/packages/pigeon/platform_tests/test_plugin/darwin/test_plugin/Sources/test_plugin/ProxyApiTests.gen.swift +++ b/packages/pigeon/platform_tests/test_plugin/darwin/test_plugin/Sources/test_plugin/ProxyApiTests.gen.swift @@ -65,8 +65,18 @@ private func createConnectionError(withChannelName channelName: String) -> Proxy details: "") } -private func isNullish(_ value: Any?) -> Bool { - return value is NSNull || value == nil +enum ProxyApiTestsPigeonInternal { + static func isNullish(_ value: Any?) -> Bool { + guard let innerValue = value else { + return true + } + + if case Optional.some(Optional.none) = value { + return true + } + + return innerValue is NSNull + } } private func nilOrValue(_ value: Any?) -> T? { diff --git a/packages/pigeon/platform_tests/test_plugin/darwin/test_plugin/Sources/test_plugin/TestPlugin.swift b/packages/pigeon/platform_tests/test_plugin/darwin/test_plugin/Sources/test_plugin/TestPlugin.swift index 89d25d32f58e..95d63024e972 100644 --- a/packages/pigeon/platform_tests/test_plugin/darwin/test_plugin/Sources/test_plugin/TestPlugin.swift +++ b/packages/pigeon/platform_tests/test_plugin/darwin/test_plugin/Sources/test_plugin/TestPlugin.swift @@ -132,6 +132,22 @@ public class TestPlugin: NSObject, FlutterPlugin, HostIntegrationCoreApi { return list } + func echo(stringList: [String?]) throws -> [String?] { + return stringList + } + + func echo(intList: [Int64?]) throws -> [Int64?] { + return intList + } + + func echo(doubleList: [Double?]) throws -> [Double?] { + return doubleList + } + + func echo(boolList: [Bool?]) throws -> [Bool?] { + return boolList + } + func echo(enumList: [AnEnum?]) throws -> [AnEnum?] { return enumList } diff --git a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/AllDatatypesTests.swift b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/DataClassMethodsTests.swift similarity index 78% rename from packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/AllDatatypesTests.swift rename to packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/DataClassMethodsTests.swift index e855f673fd29..69360f095190 100644 --- a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/AllDatatypesTests.swift +++ b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/DataClassMethodsTests.swift @@ -8,7 +8,32 @@ import Testing @testable import test_plugin @MainActor -struct AllDatatypesTests { +struct DataClassMethodsTests { + + private let everythingFull = AllNullableTypes( + aNullableBool: true, + aNullableInt: 1, + aNullableDouble: 2.0, + aNullableByteArray: FlutterStandardTypedData(bytes: "1234".data(using: .utf8)!), + aNullable4ByteArray: FlutterStandardTypedData(int32: "1234".data(using: .utf8)!), + aNullable8ByteArray: FlutterStandardTypedData(int64: "12345678".data(using: .utf8)!), + aNullableFloatArray: FlutterStandardTypedData(float64: "12345678".data(using: .utf8)!), + aNullableString: "123", + list: ["string", 2], + stringList: ["string", "another one", nil], + intList: [1, 2], + doubleList: [1.1, 2.2], + boolList: [true, false], + objectList: ["string", 2], + listList: [[true], [false]], + mapList: [["hello": 1234], ["hello": 1234]], + map: ["hello": 1234, "null": nil], + stringMap: ["hello": "you"], + intMap: [1: 0], + objectMap: ["hello": 1234], + listMap: [1234: ["string", 2]], + mapMap: [1234: ["hello": 1234]] + ) @Test func allNull() async throws { @@ -31,30 +56,7 @@ struct AllDatatypesTests { @Test func allEquals() async throws { - let everything = AllNullableTypes( - aNullableBool: true, - aNullableInt: 1, - aNullableDouble: 2.0, - aNullableByteArray: FlutterStandardTypedData(bytes: "1234".data(using: .utf8)!), - aNullable4ByteArray: FlutterStandardTypedData(int32: "1234".data(using: .utf8)!), - aNullable8ByteArray: FlutterStandardTypedData(int64: "12345678".data(using: .utf8)!), - aNullableFloatArray: FlutterStandardTypedData(float64: "12345678".data(using: .utf8)!), - aNullableString: "123", - list: ["string", 2], - stringList: ["string", "another one", nil], - intList: [1, 2], - doubleList: [1.1, 2.2], - boolList: [true, false], - objectList: ["string", 2], - listList: [[true], [false]], - mapList: [["hello": 1234], ["hello": 1234]], - map: ["hello": 1234, "null": nil], - stringMap: ["hello": "you"], - intMap: [1: 0], - objectMap: ["hello": 1234], - listMap: [1234: ["string", 2]], - mapMap: [1234: ["hello": 1234]] - ) + let everything = everythingFull let binaryMessenger = EchoBinaryMessenger(codec: CoreTestsPigeonCodec.shared) let api = FlutterIntegrationCoreApi(binaryMessenger: binaryMessenger) @@ -72,6 +74,63 @@ struct AllDatatypesTests { } } + // We validate individual field outputs rather than asserting against a single exact expected string + // because `AllNullableTypes` contains Swift `Dictionary` properties. Swift hash maps serialize + // key-value pairs in a non-deterministic order across test executions, which would cause + // flaky CI failures if compared to a fixed canonical string. + @Test + func descriptionFullOutput() { + let desc = everythingFull.description + #expect(desc.hasPrefix("AllNullableTypes(")) + #expect(desc.hasSuffix(")")) + + let expectedFields = [ + "aNullableBool:", + "aNullableInt:", + "aNullableInt64:", + "aNullableDouble:", + "aNullableByteArray:", + "aNullable4ByteArray:", + "aNullable8ByteArray:", + "aNullableFloatArray:", + "aNullableEnum:", + "anotherNullableEnum:", + "aNullableString:", + "aNullableObject:", + "allNullableTypes:", + "list:", + "stringList:", + "intList:", + "doubleList:", + "boolList:", + "enumList:", + "objectList:", + "listList:", + "mapList:", + "recursiveClassList:", + "map:", + "stringMap:", + "intMap:", + "enumMap:", + "objectMap:", + "listMap:", + "mapMap:", + "recursiveClassMap:", + ] + + for field in expectedFields { + #expect(desc.contains(field)) + } + + #expect(desc.contains("aNullableBool: Optional(true)")) + #expect(desc.contains("aNullableInt: Optional(1)")) + #expect(desc.contains("aNullableDouble: Optional(2.0)")) + #expect(desc.contains("aNullableString: Optional(\"123\")")) + #expect(desc.contains("list: Optional([")) + #expect(desc.contains("stringList: Optional([")) + #expect(desc.contains("stringMap: Optional([")) + } + private let correctList: [Any?] = ["a", 2, "three"] private let matchingList: [Any?] = ["a", 2, "three"] private let differentList: [Any?] = ["a", 2, "three", 4.0] diff --git a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/IsNullishTests.swift b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/IsNullishTests.swift new file mode 100644 index 000000000000..fc797a060480 --- /dev/null +++ b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/IsNullishTests.swift @@ -0,0 +1,58 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import Testing + +@testable import test_plugin + +struct IsNullishTests { + + @Test + func testNil() { + let value: Any? = nil + #expect(CoreTestsPigeonInternal.isNullish(value) == true) + } + + @Test + func testNSNull() { + let value: Any? = NSNull() + #expect(CoreTestsPigeonInternal.isNullish(value) == true) + } + + @Test + func testNestedNil() { + let inner: Any? = nil + let value: Any? = inner + #expect(CoreTestsPigeonInternal.isNullish(value) == true) + } + + @Test + func testDoubleNestedNil() { + let innerMost: Any? = nil + let inner: Any?? = innerMost + let value: Any? = inner + #expect(CoreTestsPigeonInternal.isNullish(value) == true) + } + + @Test + func testTypedNil() { + let typedNil: String? = nil + let value: Any? = typedNil + #expect(CoreTestsPigeonInternal.isNullish(value) == true) + } + + @Test + func testNestedNSNull() { + let inner: Any? = NSNull() + let value: Any? = inner + #expect(CoreTestsPigeonInternal.isNullish(value) == true) + } + + @Test + func testNonNullValue() { + let value: Any? = "Hello" + #expect(CoreTestsPigeonInternal.isNullish(value) == false) + } +} diff --git a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/ListTests.swift b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/ListTests.swift index a681304291b2..b4c0119c6128 100644 --- a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/ListTests.swift +++ b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/ListTests.swift @@ -31,4 +31,13 @@ struct ListTests { } } + @Test + func descriptionSnapshot() { + let msg = TestMessage(testList: ["hello", 42]) + let desc = msg.description + #expect(desc.hasPrefix("TestMessage(testList: ")) + #expect(desc.contains("hello")) + #expect(desc.contains("42")) + } + } diff --git a/packages/pigeon/platform_tests/test_plugin/linux/CMakeLists.txt b/packages/pigeon/platform_tests/test_plugin/linux/CMakeLists.txt index df18c7756f36..00b9a970f1e7 100644 --- a/packages/pigeon/platform_tests/test_plugin/linux/CMakeLists.txt +++ b/packages/pigeon/platform_tests/test_plugin/linux/CMakeLists.txt @@ -100,7 +100,7 @@ add_executable(${TEST_RUNNER} test/nullable_returns_test.cc test/null_fields_test.cc test/primitive_test.cc - test/equality_test.cc + test/data_class_methods_test.cc # Test utilities. test/utils/fake_host_messenger.cc test/utils/fake_host_messenger.h diff --git a/packages/pigeon/platform_tests/test_plugin/linux/pigeon/core_tests.gen.cc b/packages/pigeon/platform_tests/test_plugin/linux/pigeon/core_tests.gen.cc index 023cd1ed85db..78955faed8f1 100644 --- a/packages/pigeon/platform_tests/test_plugin/linux/pigeon/core_tests.gen.cc +++ b/packages/pigeon/platform_tests/test_plugin/linux/pigeon/core_tests.gen.cc @@ -197,6 +197,96 @@ static guint G_GNUC_UNUSED flpigeon_deep_hash(FlValue* value) { } return 0; } +static gchar* G_GNUC_UNUSED flpigeon_to_string(FlValue* value) { + if (value == nullptr) { + return g_strdup("null"); + } + switch (fl_value_get_type(value)) { + case FL_VALUE_TYPE_NULL: + return g_strdup("null"); + case FL_VALUE_TYPE_BOOL: + return g_strdup(fl_value_get_bool(value) ? "true" : "false"); + case FL_VALUE_TYPE_INT: + return g_strdup_printf("%" G_GINT64_FORMAT, fl_value_get_int(value)); + case FL_VALUE_TYPE_FLOAT: + return g_strdup_printf("%g", fl_value_get_float(value)); + case FL_VALUE_TYPE_STRING: + return g_strdup_printf("\"%s\"", fl_value_get_string(value)); + case FL_VALUE_TYPE_UINT8_LIST: { + GString* str = g_string_new("["); + size_t len = fl_value_get_length(value); + const uint8_t* data = fl_value_get_uint8_list(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%d", data[i]); + } + g_string_append(str, "]"); + return g_string_free(str, FALSE); + } + case FL_VALUE_TYPE_INT32_LIST: { + GString* str = g_string_new("["); + size_t len = fl_value_get_length(value); + const int32_t* data = fl_value_get_int32_list(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%d", data[i]); + } + g_string_append(str, "]"); + return g_string_free(str, FALSE); + } + case FL_VALUE_TYPE_INT64_LIST: { + GString* str = g_string_new("["); + size_t len = fl_value_get_length(value); + const int64_t* data = fl_value_get_int64_list(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%" G_GINT64_FORMAT, data[i]); + } + g_string_append(str, "]"); + return g_string_free(str, FALSE); + } + case FL_VALUE_TYPE_FLOAT_LIST: { + GString* str = g_string_new("["); + size_t len = fl_value_get_length(value); + const double* data = fl_value_get_float_list(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%g", data[i]); + } + g_string_append(str, "]"); + return g_string_free(str, FALSE); + } + case FL_VALUE_TYPE_LIST: { + GString* str = g_string_new("["); + size_t len = fl_value_get_length(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + gchar* item_str = flpigeon_to_string(fl_value_get_list_value(value, i)); + g_string_append(str, item_str); + g_free(item_str); + } + g_string_append(str, "]"); + return g_string_free(str, FALSE); + } + case FL_VALUE_TYPE_MAP: { + GString* str = g_string_new("{"); + size_t len = fl_value_get_length(value); + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + gchar* key_str = flpigeon_to_string(fl_value_get_map_key(value, i)); + gchar* val_str = flpigeon_to_string(fl_value_get_map_value(value, i)); + g_string_append_printf(str, "%s: %s", key_str, val_str); + g_free(key_str); + g_free(val_str); + } + g_string_append(str, "}"); + return g_string_free(str, FALSE); + } + default: + return g_strdup("[custom]"); + } + return g_strdup("null"); +} struct _CoreTestsPigeonTestUnusedClass { GObject parent_instance; @@ -282,6 +372,22 @@ guint core_tests_pigeon_test_unused_class_hash( return result; } +gchar* core_tests_pigeon_test_unused_class_to_string( + CoreTestsPigeonTestUnusedClass* self) { + g_return_val_if_fail(CORE_TESTS_PIGEON_TEST_IS_UNUSED_CLASS(self), NULL); + GString* str = g_string_new("UnusedClass("); + g_string_append(str, "a_field: "); + if (self->a_field != nullptr) { + gchar* val_str = flpigeon_to_string(self->a_field); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ")"); + return g_string_free(str, FALSE); +} + struct _CoreTestsPigeonTestAllTypes { GObject parent_instance; @@ -909,6 +1015,220 @@ guint core_tests_pigeon_test_all_types_hash(CoreTestsPigeonTestAllTypes* self) { return result; } +gchar* core_tests_pigeon_test_all_types_to_string( + CoreTestsPigeonTestAllTypes* self) { + g_return_val_if_fail(CORE_TESTS_PIGEON_TEST_IS_ALL_TYPES(self), NULL); + GString* str = g_string_new("AllTypes("); + g_string_append(str, "a_bool: "); + g_string_append(str, self->a_bool ? "true" : "false"); + g_string_append(str, ", an_int: "); + g_string_append_printf(str, "%" G_GINT64_FORMAT, self->an_int); + g_string_append(str, ", an_int64: "); + g_string_append_printf(str, "%" G_GINT64_FORMAT, self->an_int64); + g_string_append(str, ", a_double: "); + g_string_append_printf(str, "%g", self->a_double); + g_string_append(str, ", a_byte_array: "); + if (self->a_byte_array != nullptr) { + g_string_append(str, "["); + size_t len = self->a_byte_array_length; + const uint8_t* data = self->a_byte_array; + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%d", static_cast(data[i])); + } + g_string_append(str, "]"); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a4_byte_array: "); + if (self->a4_byte_array != nullptr) { + g_string_append(str, "["); + size_t len = self->a4_byte_array_length; + const int32_t* data = self->a4_byte_array; + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%d", static_cast(data[i])); + } + g_string_append(str, "]"); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a8_byte_array: "); + if (self->a8_byte_array != nullptr) { + g_string_append(str, "["); + size_t len = self->a8_byte_array_length; + const int64_t* data = self->a8_byte_array; + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%" G_GINT64_FORMAT, data[i]); + } + g_string_append(str, "]"); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_float_array: "); + if (self->a_float_array != nullptr) { + g_string_append(str, "["); + size_t len = self->a_float_array_length; + const double* data = self->a_float_array; + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%g", data[i]); + } + g_string_append(str, "]"); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", an_enum: "); + g_string_append_printf(str, "%d", static_cast(self->an_enum)); + g_string_append(str, ", another_enum: "); + g_string_append_printf(str, "%d", static_cast(self->another_enum)); + g_string_append(str, ", a_string: "); + if (self->a_string != nullptr) { + g_string_append_printf(str, "\"%s\"", self->a_string); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", an_object: "); + if (self->an_object != nullptr) { + gchar* val_str = flpigeon_to_string(self->an_object); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", list: "); + if (self->list != nullptr) { + gchar* val_str = flpigeon_to_string(self->list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", string_list: "); + if (self->string_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->string_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", int_list: "); + if (self->int_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->int_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", double_list: "); + if (self->double_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->double_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", bool_list: "); + if (self->bool_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->bool_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", enum_list: "); + if (self->enum_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->enum_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", object_list: "); + if (self->object_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->object_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", list_list: "); + if (self->list_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->list_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", map_list: "); + if (self->map_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->map_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", map: "); + if (self->map != nullptr) { + gchar* val_str = flpigeon_to_string(self->map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", string_map: "); + if (self->string_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->string_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", int_map: "); + if (self->int_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->int_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", enum_map: "); + if (self->enum_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->enum_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", object_map: "); + if (self->object_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->object_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", list_map: "); + if (self->list_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->list_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", map_map: "); + if (self->map_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->map_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ")"); + return g_string_free(str, FALSE); +} + struct _CoreTestsPigeonTestAllNullableTypes { GObject parent_instance; @@ -2001,6 +2321,271 @@ guint core_tests_pigeon_test_all_nullable_types_hash( return result; } +gchar* core_tests_pigeon_test_all_nullable_types_to_string( + CoreTestsPigeonTestAllNullableTypes* self) { + g_return_val_if_fail(CORE_TESTS_PIGEON_TEST_IS_ALL_NULLABLE_TYPES(self), + NULL); + GString* str = g_string_new("AllNullableTypes("); + g_string_append(str, "a_nullable_bool: "); + if (self->a_nullable_bool != nullptr) { + g_string_append(str, *self->a_nullable_bool ? "true" : "false"); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_nullable_int: "); + if (self->a_nullable_int != nullptr) { + g_string_append_printf(str, "%" G_GINT64_FORMAT, *self->a_nullable_int); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_nullable_int64: "); + if (self->a_nullable_int64 != nullptr) { + g_string_append_printf(str, "%" G_GINT64_FORMAT, *self->a_nullable_int64); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_nullable_double: "); + if (self->a_nullable_double != nullptr) { + g_string_append_printf(str, "%g", *self->a_nullable_double); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_nullable_byte_array: "); + if (self->a_nullable_byte_array != nullptr) { + g_string_append(str, "["); + size_t len = self->a_nullable_byte_array_length; + const uint8_t* data = self->a_nullable_byte_array; + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%d", static_cast(data[i])); + } + g_string_append(str, "]"); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_nullable4_byte_array: "); + if (self->a_nullable4_byte_array != nullptr) { + g_string_append(str, "["); + size_t len = self->a_nullable4_byte_array_length; + const int32_t* data = self->a_nullable4_byte_array; + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%d", static_cast(data[i])); + } + g_string_append(str, "]"); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_nullable8_byte_array: "); + if (self->a_nullable8_byte_array != nullptr) { + g_string_append(str, "["); + size_t len = self->a_nullable8_byte_array_length; + const int64_t* data = self->a_nullable8_byte_array; + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%" G_GINT64_FORMAT, data[i]); + } + g_string_append(str, "]"); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_nullable_float_array: "); + if (self->a_nullable_float_array != nullptr) { + g_string_append(str, "["); + size_t len = self->a_nullable_float_array_length; + const double* data = self->a_nullable_float_array; + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%g", data[i]); + } + g_string_append(str, "]"); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_nullable_enum: "); + if (self->a_nullable_enum != nullptr) { + g_string_append_printf(str, "%d", static_cast(*self->a_nullable_enum)); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", another_nullable_enum: "); + if (self->another_nullable_enum != nullptr) { + g_string_append_printf(str, "%d", + static_cast(*self->another_nullable_enum)); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_nullable_string: "); + if (self->a_nullable_string != nullptr) { + g_string_append_printf(str, "\"%s\"", self->a_nullable_string); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_nullable_object: "); + if (self->a_nullable_object != nullptr) { + gchar* val_str = flpigeon_to_string(self->a_nullable_object); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", all_nullable_types: "); + if (self->all_nullable_types != nullptr) { + gchar* field_str = core_tests_pigeon_test_all_nullable_types_to_string( + self->all_nullable_types); + g_string_append(str, field_str); + g_free(field_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", list: "); + if (self->list != nullptr) { + gchar* val_str = flpigeon_to_string(self->list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", string_list: "); + if (self->string_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->string_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", int_list: "); + if (self->int_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->int_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", double_list: "); + if (self->double_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->double_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", bool_list: "); + if (self->bool_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->bool_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", enum_list: "); + if (self->enum_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->enum_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", object_list: "); + if (self->object_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->object_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", list_list: "); + if (self->list_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->list_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", map_list: "); + if (self->map_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->map_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", recursive_class_list: "); + if (self->recursive_class_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->recursive_class_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", map: "); + if (self->map != nullptr) { + gchar* val_str = flpigeon_to_string(self->map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", string_map: "); + if (self->string_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->string_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", int_map: "); + if (self->int_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->int_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", enum_map: "); + if (self->enum_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->enum_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", object_map: "); + if (self->object_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->object_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", list_map: "); + if (self->list_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->list_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", map_map: "); + if (self->map_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->map_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", recursive_class_map: "); + if (self->recursive_class_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->recursive_class_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ")"); + return g_string_free(str, FALSE); +} + struct _CoreTestsPigeonTestAllNullableTypesWithoutRecursion { GObject parent_instance; @@ -3060,80 +3645,321 @@ guint core_tests_pigeon_test_all_nullable_types_without_recursion_hash( return result; } -struct _CoreTestsPigeonTestAllClassesWrapper { - GObject parent_instance; - - CoreTestsPigeonTestAllNullableTypes* all_nullable_types; - CoreTestsPigeonTestAllNullableTypesWithoutRecursion* - all_nullable_types_without_recursion; - CoreTestsPigeonTestAllTypes* all_types; - FlValue* class_list; - FlValue* nullable_class_list; - FlValue* class_map; - FlValue* nullable_class_map; -}; - -G_DEFINE_TYPE(CoreTestsPigeonTestAllClassesWrapper, - core_tests_pigeon_test_all_classes_wrapper, G_TYPE_OBJECT) - -static void core_tests_pigeon_test_all_classes_wrapper_dispose( - GObject* object) { - CoreTestsPigeonTestAllClassesWrapper* self = - CORE_TESTS_PIGEON_TEST_ALL_CLASSES_WRAPPER(object); - g_clear_object(&self->all_nullable_types); - g_clear_object(&self->all_nullable_types_without_recursion); - g_clear_object(&self->all_types); - g_clear_pointer(&self->class_list, fl_value_unref); - g_clear_pointer(&self->nullable_class_list, fl_value_unref); - g_clear_pointer(&self->class_map, fl_value_unref); - g_clear_pointer(&self->nullable_class_map, fl_value_unref); - G_OBJECT_CLASS(core_tests_pigeon_test_all_classes_wrapper_parent_class) - ->dispose(object); -} - -static void core_tests_pigeon_test_all_classes_wrapper_init( - CoreTestsPigeonTestAllClassesWrapper* self) {} - -static void core_tests_pigeon_test_all_classes_wrapper_class_init( - CoreTestsPigeonTestAllClassesWrapperClass* klass) { - G_OBJECT_CLASS(klass)->dispose = - core_tests_pigeon_test_all_classes_wrapper_dispose; -} - -CoreTestsPigeonTestAllClassesWrapper* -core_tests_pigeon_test_all_classes_wrapper_new( - CoreTestsPigeonTestAllNullableTypes* all_nullable_types, - CoreTestsPigeonTestAllNullableTypesWithoutRecursion* - all_nullable_types_without_recursion, - CoreTestsPigeonTestAllTypes* all_types, FlValue* class_list, - FlValue* nullable_class_list, FlValue* class_map, - FlValue* nullable_class_map) { - CoreTestsPigeonTestAllClassesWrapper* self = - CORE_TESTS_PIGEON_TEST_ALL_CLASSES_WRAPPER(g_object_new( - core_tests_pigeon_test_all_classes_wrapper_get_type(), nullptr)); - self->all_nullable_types = CORE_TESTS_PIGEON_TEST_ALL_NULLABLE_TYPES( - g_object_ref(all_nullable_types)); - if (all_nullable_types_without_recursion != nullptr) { - self->all_nullable_types_without_recursion = - CORE_TESTS_PIGEON_TEST_ALL_NULLABLE_TYPES_WITHOUT_RECURSION( - g_object_ref(all_nullable_types_without_recursion)); +gchar* core_tests_pigeon_test_all_nullable_types_without_recursion_to_string( + CoreTestsPigeonTestAllNullableTypesWithoutRecursion* self) { + g_return_val_if_fail( + CORE_TESTS_PIGEON_TEST_IS_ALL_NULLABLE_TYPES_WITHOUT_RECURSION(self), + NULL); + GString* str = g_string_new("AllNullableTypesWithoutRecursion("); + g_string_append(str, "a_nullable_bool: "); + if (self->a_nullable_bool != nullptr) { + g_string_append(str, *self->a_nullable_bool ? "true" : "false"); } else { - self->all_nullable_types_without_recursion = nullptr; + g_string_append(str, "null"); } - if (all_types != nullptr) { - self->all_types = CORE_TESTS_PIGEON_TEST_ALL_TYPES(g_object_ref(all_types)); + g_string_append(str, ", a_nullable_int: "); + if (self->a_nullable_int != nullptr) { + g_string_append_printf(str, "%" G_GINT64_FORMAT, *self->a_nullable_int); } else { - self->all_types = nullptr; + g_string_append(str, "null"); } - self->class_list = fl_value_ref(class_list); - if (nullable_class_list != nullptr) { - self->nullable_class_list = fl_value_ref(nullable_class_list); + g_string_append(str, ", a_nullable_int64: "); + if (self->a_nullable_int64 != nullptr) { + g_string_append_printf(str, "%" G_GINT64_FORMAT, *self->a_nullable_int64); } else { - self->nullable_class_list = nullptr; + g_string_append(str, "null"); } - self->class_map = fl_value_ref(class_map); - if (nullable_class_map != nullptr) { - self->nullable_class_map = fl_value_ref(nullable_class_map); + g_string_append(str, ", a_nullable_double: "); + if (self->a_nullable_double != nullptr) { + g_string_append_printf(str, "%g", *self->a_nullable_double); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_nullable_byte_array: "); + if (self->a_nullable_byte_array != nullptr) { + g_string_append(str, "["); + size_t len = self->a_nullable_byte_array_length; + const uint8_t* data = self->a_nullable_byte_array; + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%d", static_cast(data[i])); + } + g_string_append(str, "]"); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_nullable4_byte_array: "); + if (self->a_nullable4_byte_array != nullptr) { + g_string_append(str, "["); + size_t len = self->a_nullable4_byte_array_length; + const int32_t* data = self->a_nullable4_byte_array; + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%d", static_cast(data[i])); + } + g_string_append(str, "]"); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_nullable8_byte_array: "); + if (self->a_nullable8_byte_array != nullptr) { + g_string_append(str, "["); + size_t len = self->a_nullable8_byte_array_length; + const int64_t* data = self->a_nullable8_byte_array; + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%" G_GINT64_FORMAT, data[i]); + } + g_string_append(str, "]"); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_nullable_float_array: "); + if (self->a_nullable_float_array != nullptr) { + g_string_append(str, "["); + size_t len = self->a_nullable_float_array_length; + const double* data = self->a_nullable_float_array; + for (size_t i = 0; i < len; i++) { + if (i > 0) g_string_append(str, ", "); + g_string_append_printf(str, "%g", data[i]); + } + g_string_append(str, "]"); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_nullable_enum: "); + if (self->a_nullable_enum != nullptr) { + g_string_append_printf(str, "%d", static_cast(*self->a_nullable_enum)); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", another_nullable_enum: "); + if (self->another_nullable_enum != nullptr) { + g_string_append_printf(str, "%d", + static_cast(*self->another_nullable_enum)); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_nullable_string: "); + if (self->a_nullable_string != nullptr) { + g_string_append_printf(str, "\"%s\"", self->a_nullable_string); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", a_nullable_object: "); + if (self->a_nullable_object != nullptr) { + gchar* val_str = flpigeon_to_string(self->a_nullable_object); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", list: "); + if (self->list != nullptr) { + gchar* val_str = flpigeon_to_string(self->list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", string_list: "); + if (self->string_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->string_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", int_list: "); + if (self->int_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->int_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", double_list: "); + if (self->double_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->double_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", bool_list: "); + if (self->bool_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->bool_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", enum_list: "); + if (self->enum_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->enum_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", object_list: "); + if (self->object_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->object_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", list_list: "); + if (self->list_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->list_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", map_list: "); + if (self->map_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->map_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", map: "); + if (self->map != nullptr) { + gchar* val_str = flpigeon_to_string(self->map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", string_map: "); + if (self->string_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->string_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", int_map: "); + if (self->int_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->int_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", enum_map: "); + if (self->enum_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->enum_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", object_map: "); + if (self->object_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->object_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", list_map: "); + if (self->list_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->list_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", map_map: "); + if (self->map_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->map_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ")"); + return g_string_free(str, FALSE); +} + +struct _CoreTestsPigeonTestAllClassesWrapper { + GObject parent_instance; + + CoreTestsPigeonTestAllNullableTypes* all_nullable_types; + CoreTestsPigeonTestAllNullableTypesWithoutRecursion* + all_nullable_types_without_recursion; + CoreTestsPigeonTestAllTypes* all_types; + FlValue* class_list; + FlValue* nullable_class_list; + FlValue* class_map; + FlValue* nullable_class_map; +}; + +G_DEFINE_TYPE(CoreTestsPigeonTestAllClassesWrapper, + core_tests_pigeon_test_all_classes_wrapper, G_TYPE_OBJECT) + +static void core_tests_pigeon_test_all_classes_wrapper_dispose( + GObject* object) { + CoreTestsPigeonTestAllClassesWrapper* self = + CORE_TESTS_PIGEON_TEST_ALL_CLASSES_WRAPPER(object); + g_clear_object(&self->all_nullable_types); + g_clear_object(&self->all_nullable_types_without_recursion); + g_clear_object(&self->all_types); + g_clear_pointer(&self->class_list, fl_value_unref); + g_clear_pointer(&self->nullable_class_list, fl_value_unref); + g_clear_pointer(&self->class_map, fl_value_unref); + g_clear_pointer(&self->nullable_class_map, fl_value_unref); + G_OBJECT_CLASS(core_tests_pigeon_test_all_classes_wrapper_parent_class) + ->dispose(object); +} + +static void core_tests_pigeon_test_all_classes_wrapper_init( + CoreTestsPigeonTestAllClassesWrapper* self) {} + +static void core_tests_pigeon_test_all_classes_wrapper_class_init( + CoreTestsPigeonTestAllClassesWrapperClass* klass) { + G_OBJECT_CLASS(klass)->dispose = + core_tests_pigeon_test_all_classes_wrapper_dispose; +} + +CoreTestsPigeonTestAllClassesWrapper* +core_tests_pigeon_test_all_classes_wrapper_new( + CoreTestsPigeonTestAllNullableTypes* all_nullable_types, + CoreTestsPigeonTestAllNullableTypesWithoutRecursion* + all_nullable_types_without_recursion, + CoreTestsPigeonTestAllTypes* all_types, FlValue* class_list, + FlValue* nullable_class_list, FlValue* class_map, + FlValue* nullable_class_map) { + CoreTestsPigeonTestAllClassesWrapper* self = + CORE_TESTS_PIGEON_TEST_ALL_CLASSES_WRAPPER(g_object_new( + core_tests_pigeon_test_all_classes_wrapper_get_type(), nullptr)); + self->all_nullable_types = CORE_TESTS_PIGEON_TEST_ALL_NULLABLE_TYPES( + g_object_ref(all_nullable_types)); + if (all_nullable_types_without_recursion != nullptr) { + self->all_nullable_types_without_recursion = + CORE_TESTS_PIGEON_TEST_ALL_NULLABLE_TYPES_WITHOUT_RECURSION( + g_object_ref(all_nullable_types_without_recursion)); + } else { + self->all_nullable_types_without_recursion = nullptr; + } + if (all_types != nullptr) { + self->all_types = CORE_TESTS_PIGEON_TEST_ALL_TYPES(g_object_ref(all_types)); + } else { + self->all_types = nullptr; + } + self->class_list = fl_value_ref(class_list); + if (nullable_class_list != nullptr) { + self->nullable_class_list = fl_value_ref(nullable_class_list); + } else { + self->nullable_class_list = nullptr; + } + self->class_map = fl_value_ref(class_map); + if (nullable_class_map != nullptr) { + self->nullable_class_map = fl_value_ref(nullable_class_map); } else { self->nullable_class_map = nullptr; } @@ -3315,6 +4141,75 @@ guint core_tests_pigeon_test_all_classes_wrapper_hash( return result; } +gchar* core_tests_pigeon_test_all_classes_wrapper_to_string( + CoreTestsPigeonTestAllClassesWrapper* self) { + g_return_val_if_fail(CORE_TESTS_PIGEON_TEST_IS_ALL_CLASSES_WRAPPER(self), + NULL); + GString* str = g_string_new("AllClassesWrapper("); + g_string_append(str, "all_nullable_types: "); + if (self->all_nullable_types != nullptr) { + gchar* field_str = core_tests_pigeon_test_all_nullable_types_to_string( + self->all_nullable_types); + g_string_append(str, field_str); + g_free(field_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", all_nullable_types_without_recursion: "); + if (self->all_nullable_types_without_recursion != nullptr) { + gchar* field_str = + core_tests_pigeon_test_all_nullable_types_without_recursion_to_string( + self->all_nullable_types_without_recursion); + g_string_append(str, field_str); + g_free(field_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", all_types: "); + if (self->all_types != nullptr) { + gchar* field_str = + core_tests_pigeon_test_all_types_to_string(self->all_types); + g_string_append(str, field_str); + g_free(field_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", class_list: "); + if (self->class_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->class_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", nullable_class_list: "); + if (self->nullable_class_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->nullable_class_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", class_map: "); + if (self->class_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->class_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ", nullable_class_map: "); + if (self->nullable_class_map != nullptr) { + gchar* val_str = flpigeon_to_string(self->nullable_class_map); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ")"); + return g_string_free(str, FALSE); +} + struct _CoreTestsPigeonTestTestMessage { GObject parent_instance; @@ -3399,6 +4294,22 @@ guint core_tests_pigeon_test_test_message_hash( return result; } +gchar* core_tests_pigeon_test_test_message_to_string( + CoreTestsPigeonTestTestMessage* self) { + g_return_val_if_fail(CORE_TESTS_PIGEON_TEST_IS_TEST_MESSAGE(self), NULL); + GString* str = g_string_new("TestMessage("); + g_string_append(str, "test_list: "); + if (self->test_list != nullptr) { + gchar* val_str = flpigeon_to_string(self->test_list); + g_string_append(str, val_str); + g_free(val_str); + } else { + g_string_append(str, "null"); + } + g_string_append(str, ")"); + return g_string_free(str, FALSE); +} + struct _CoreTestsPigeonTestMessageCodec { FlStandardMessageCodec parent_instance; }; @@ -4299,27 +5210,283 @@ static void core_tests_pigeon_test_host_integration_core_api_echo_bool_response_class_init( CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolResponseClass* klass) { G_OBJECT_CLASS(klass)->dispose = - core_tests_pigeon_test_host_integration_core_api_echo_bool_response_dispose; + core_tests_pigeon_test_host_integration_core_api_echo_bool_response_dispose; +} + +CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolResponse* +core_tests_pigeon_test_host_integration_core_api_echo_bool_response_new( + gboolean return_value) { + CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_BOOL_RESPONSE(g_object_new( + core_tests_pigeon_test_host_integration_core_api_echo_bool_response_get_type(), + nullptr)); + self->value = fl_value_new_list(); + fl_value_append_take(self->value, fl_value_new_bool(return_value)); + return self; +} + +CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolResponse* +core_tests_pigeon_test_host_integration_core_api_echo_bool_response_new_error( + const gchar* code, const gchar* message, FlValue* details) { + CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_BOOL_RESPONSE(g_object_new( + core_tests_pigeon_test_host_integration_core_api_echo_bool_response_get_type(), + nullptr)); + self->value = fl_value_new_list(); + fl_value_append_take(self->value, fl_value_new_string(code)); + fl_value_append_take(self->value, + fl_value_new_string(message != nullptr ? message : "")); + fl_value_append_take(self->value, details != nullptr ? fl_value_ref(details) + : fl_value_new_null()); + return self; +} + +struct _CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponse { + GObject parent_instance; + + FlValue* value; +}; + +G_DEFINE_TYPE( + CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponse, + core_tests_pigeon_test_host_integration_core_api_echo_string_response, + G_TYPE_OBJECT) + +static void +core_tests_pigeon_test_host_integration_core_api_echo_string_response_dispose( + GObject* object) { + CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_STRING_RESPONSE( + object); + g_clear_pointer(&self->value, fl_value_unref); + G_OBJECT_CLASS( + core_tests_pigeon_test_host_integration_core_api_echo_string_response_parent_class) + ->dispose(object); +} + +static void +core_tests_pigeon_test_host_integration_core_api_echo_string_response_init( + CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponse* self) {} + +static void +core_tests_pigeon_test_host_integration_core_api_echo_string_response_class_init( + CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponseClass* klass) { + G_OBJECT_CLASS(klass)->dispose = + core_tests_pigeon_test_host_integration_core_api_echo_string_response_dispose; +} + +CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponse* +core_tests_pigeon_test_host_integration_core_api_echo_string_response_new( + const gchar* return_value) { + CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_STRING_RESPONSE( + g_object_new( + core_tests_pigeon_test_host_integration_core_api_echo_string_response_get_type(), + nullptr)); + self->value = fl_value_new_list(); + fl_value_append_take(self->value, fl_value_new_string(return_value)); + return self; +} + +CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponse* +core_tests_pigeon_test_host_integration_core_api_echo_string_response_new_error( + const gchar* code, const gchar* message, FlValue* details) { + CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_STRING_RESPONSE( + g_object_new( + core_tests_pigeon_test_host_integration_core_api_echo_string_response_get_type(), + nullptr)); + self->value = fl_value_new_list(); + fl_value_append_take(self->value, fl_value_new_string(code)); + fl_value_append_take(self->value, + fl_value_new_string(message != nullptr ? message : "")); + fl_value_append_take(self->value, details != nullptr ? fl_value_ref(details) + : fl_value_new_null()); + return self; +} + +struct _CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponse { + GObject parent_instance; + + FlValue* value; +}; + +G_DEFINE_TYPE( + CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponse, + core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response, + G_TYPE_OBJECT) + +static void +core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_dispose( + GObject* object) { + CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_UINT8_LIST_RESPONSE( + object); + g_clear_pointer(&self->value, fl_value_unref); + G_OBJECT_CLASS( + core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_parent_class) + ->dispose(object); +} + +static void +core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_init( + CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponse* self) {} + +static void +core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_class_init( + CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponseClass* + klass) { + G_OBJECT_CLASS(klass)->dispose = + core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_dispose; +} + +CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_new( + const uint8_t* return_value, size_t return_value_length) { + CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_UINT8_LIST_RESPONSE( + g_object_new( + core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_get_type(), + nullptr)); + self->value = fl_value_new_list(); + fl_value_append_take( + self->value, fl_value_new_uint8_list(return_value, return_value_length)); + return self; +} + +CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_new_error( + const gchar* code, const gchar* message, FlValue* details) { + CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_UINT8_LIST_RESPONSE( + g_object_new( + core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_get_type(), + nullptr)); + self->value = fl_value_new_list(); + fl_value_append_take(self->value, fl_value_new_string(code)); + fl_value_append_take(self->value, + fl_value_new_string(message != nullptr ? message : "")); + fl_value_append_take(self->value, details != nullptr ? fl_value_ref(details) + : fl_value_new_null()); + return self; +} + +struct _CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponse { + GObject parent_instance; + + FlValue* value; +}; + +G_DEFINE_TYPE( + CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponse, + core_tests_pigeon_test_host_integration_core_api_echo_object_response, + G_TYPE_OBJECT) + +static void +core_tests_pigeon_test_host_integration_core_api_echo_object_response_dispose( + GObject* object) { + CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_OBJECT_RESPONSE( + object); + g_clear_pointer(&self->value, fl_value_unref); + G_OBJECT_CLASS( + core_tests_pigeon_test_host_integration_core_api_echo_object_response_parent_class) + ->dispose(object); +} + +static void +core_tests_pigeon_test_host_integration_core_api_echo_object_response_init( + CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponse* self) {} + +static void +core_tests_pigeon_test_host_integration_core_api_echo_object_response_class_init( + CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponseClass* klass) { + G_OBJECT_CLASS(klass)->dispose = + core_tests_pigeon_test_host_integration_core_api_echo_object_response_dispose; +} + +CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponse* +core_tests_pigeon_test_host_integration_core_api_echo_object_response_new( + FlValue* return_value) { + CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_OBJECT_RESPONSE( + g_object_new( + core_tests_pigeon_test_host_integration_core_api_echo_object_response_get_type(), + nullptr)); + self->value = fl_value_new_list(); + fl_value_append_take(self->value, fl_value_ref(return_value)); + return self; +} + +CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponse* +core_tests_pigeon_test_host_integration_core_api_echo_object_response_new_error( + const gchar* code, const gchar* message, FlValue* details) { + CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_OBJECT_RESPONSE( + g_object_new( + core_tests_pigeon_test_host_integration_core_api_echo_object_response_get_type(), + nullptr)); + self->value = fl_value_new_list(); + fl_value_append_take(self->value, fl_value_new_string(code)); + fl_value_append_take(self->value, + fl_value_new_string(message != nullptr ? message : "")); + fl_value_append_take(self->value, details != nullptr ? fl_value_ref(details) + : fl_value_new_null()); + return self; +} + +struct _CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse { + GObject parent_instance; + + FlValue* value; +}; + +G_DEFINE_TYPE( + CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse, + core_tests_pigeon_test_host_integration_core_api_echo_list_response, + G_TYPE_OBJECT) + +static void +core_tests_pigeon_test_host_integration_core_api_echo_list_response_dispose( + GObject* object) { + CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_LIST_RESPONSE( + object); + g_clear_pointer(&self->value, fl_value_unref); + G_OBJECT_CLASS( + core_tests_pigeon_test_host_integration_core_api_echo_list_response_parent_class) + ->dispose(object); +} + +static void +core_tests_pigeon_test_host_integration_core_api_echo_list_response_init( + CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse* self) {} + +static void +core_tests_pigeon_test_host_integration_core_api_echo_list_response_class_init( + CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponseClass* klass) { + G_OBJECT_CLASS(klass)->dispose = + core_tests_pigeon_test_host_integration_core_api_echo_list_response_dispose; } -CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolResponse* -core_tests_pigeon_test_host_integration_core_api_echo_bool_response_new( - gboolean return_value) { - CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolResponse* self = - CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_BOOL_RESPONSE(g_object_new( - core_tests_pigeon_test_host_integration_core_api_echo_bool_response_get_type(), +CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_list_response_new( + FlValue* return_value) { + CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_LIST_RESPONSE(g_object_new( + core_tests_pigeon_test_host_integration_core_api_echo_list_response_get_type(), nullptr)); self->value = fl_value_new_list(); - fl_value_append_take(self->value, fl_value_new_bool(return_value)); + fl_value_append_take(self->value, fl_value_ref(return_value)); return self; } -CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolResponse* -core_tests_pigeon_test_host_integration_core_api_echo_bool_response_new_error( +CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_list_response_new_error( const gchar* code, const gchar* message, FlValue* details) { - CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolResponse* self = - CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_BOOL_RESPONSE(g_object_new( - core_tests_pigeon_test_host_integration_core_api_echo_bool_response_get_type(), + CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_LIST_RESPONSE(g_object_new( + core_tests_pigeon_test_host_integration_core_api_echo_list_response_get_type(), nullptr)); self->value = fl_value_new_list(); fl_value_append_take(self->value, fl_value_new_string(code)); @@ -4330,60 +5497,61 @@ core_tests_pigeon_test_host_integration_core_api_echo_bool_response_new_error( return self; } -struct _CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponse { +struct _CoreTestsPigeonTestHostIntegrationCoreApiEchoStringListResponse { GObject parent_instance; FlValue* value; }; G_DEFINE_TYPE( - CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponse, - core_tests_pigeon_test_host_integration_core_api_echo_string_response, + CoreTestsPigeonTestHostIntegrationCoreApiEchoStringListResponse, + core_tests_pigeon_test_host_integration_core_api_echo_string_list_response, G_TYPE_OBJECT) static void -core_tests_pigeon_test_host_integration_core_api_echo_string_response_dispose( +core_tests_pigeon_test_host_integration_core_api_echo_string_list_response_dispose( GObject* object) { - CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponse* self = - CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_STRING_RESPONSE( + CoreTestsPigeonTestHostIntegrationCoreApiEchoStringListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_STRING_LIST_RESPONSE( object); g_clear_pointer(&self->value, fl_value_unref); G_OBJECT_CLASS( - core_tests_pigeon_test_host_integration_core_api_echo_string_response_parent_class) + core_tests_pigeon_test_host_integration_core_api_echo_string_list_response_parent_class) ->dispose(object); } static void -core_tests_pigeon_test_host_integration_core_api_echo_string_response_init( - CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponse* self) {} +core_tests_pigeon_test_host_integration_core_api_echo_string_list_response_init( + CoreTestsPigeonTestHostIntegrationCoreApiEchoStringListResponse* self) {} static void -core_tests_pigeon_test_host_integration_core_api_echo_string_response_class_init( - CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponseClass* klass) { +core_tests_pigeon_test_host_integration_core_api_echo_string_list_response_class_init( + CoreTestsPigeonTestHostIntegrationCoreApiEchoStringListResponseClass* + klass) { G_OBJECT_CLASS(klass)->dispose = - core_tests_pigeon_test_host_integration_core_api_echo_string_response_dispose; + core_tests_pigeon_test_host_integration_core_api_echo_string_list_response_dispose; } -CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponse* -core_tests_pigeon_test_host_integration_core_api_echo_string_response_new( - const gchar* return_value) { - CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponse* self = - CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_STRING_RESPONSE( +CoreTestsPigeonTestHostIntegrationCoreApiEchoStringListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_string_list_response_new( + FlValue* return_value) { + CoreTestsPigeonTestHostIntegrationCoreApiEchoStringListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_STRING_LIST_RESPONSE( g_object_new( - core_tests_pigeon_test_host_integration_core_api_echo_string_response_get_type(), + core_tests_pigeon_test_host_integration_core_api_echo_string_list_response_get_type(), nullptr)); self->value = fl_value_new_list(); - fl_value_append_take(self->value, fl_value_new_string(return_value)); + fl_value_append_take(self->value, fl_value_ref(return_value)); return self; } -CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponse* -core_tests_pigeon_test_host_integration_core_api_echo_string_response_new_error( +CoreTestsPigeonTestHostIntegrationCoreApiEchoStringListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_string_list_response_new_error( const gchar* code, const gchar* message, FlValue* details) { - CoreTestsPigeonTestHostIntegrationCoreApiEchoStringResponse* self = - CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_STRING_RESPONSE( + CoreTestsPigeonTestHostIntegrationCoreApiEchoStringListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_STRING_LIST_RESPONSE( g_object_new( - core_tests_pigeon_test_host_integration_core_api_echo_string_response_get_type(), + core_tests_pigeon_test_host_integration_core_api_echo_string_list_response_get_type(), nullptr)); self->value = fl_value_new_list(); fl_value_append_take(self->value, fl_value_new_string(code)); @@ -4394,62 +5562,60 @@ core_tests_pigeon_test_host_integration_core_api_echo_string_response_new_error( return self; } -struct _CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponse { +struct _CoreTestsPigeonTestHostIntegrationCoreApiEchoIntListResponse { GObject parent_instance; FlValue* value; }; G_DEFINE_TYPE( - CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponse, - core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response, + CoreTestsPigeonTestHostIntegrationCoreApiEchoIntListResponse, + core_tests_pigeon_test_host_integration_core_api_echo_int_list_response, G_TYPE_OBJECT) static void -core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_dispose( +core_tests_pigeon_test_host_integration_core_api_echo_int_list_response_dispose( GObject* object) { - CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponse* self = - CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_UINT8_LIST_RESPONSE( + CoreTestsPigeonTestHostIntegrationCoreApiEchoIntListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_INT_LIST_RESPONSE( object); g_clear_pointer(&self->value, fl_value_unref); G_OBJECT_CLASS( - core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_parent_class) + core_tests_pigeon_test_host_integration_core_api_echo_int_list_response_parent_class) ->dispose(object); } static void -core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_init( - CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponse* self) {} +core_tests_pigeon_test_host_integration_core_api_echo_int_list_response_init( + CoreTestsPigeonTestHostIntegrationCoreApiEchoIntListResponse* self) {} static void -core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_class_init( - CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponseClass* - klass) { +core_tests_pigeon_test_host_integration_core_api_echo_int_list_response_class_init( + CoreTestsPigeonTestHostIntegrationCoreApiEchoIntListResponseClass* klass) { G_OBJECT_CLASS(klass)->dispose = - core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_dispose; + core_tests_pigeon_test_host_integration_core_api_echo_int_list_response_dispose; } -CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponse* -core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_new( - const uint8_t* return_value, size_t return_value_length) { - CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponse* self = - CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_UINT8_LIST_RESPONSE( +CoreTestsPigeonTestHostIntegrationCoreApiEchoIntListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_int_list_response_new( + FlValue* return_value) { + CoreTestsPigeonTestHostIntegrationCoreApiEchoIntListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_INT_LIST_RESPONSE( g_object_new( - core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_get_type(), + core_tests_pigeon_test_host_integration_core_api_echo_int_list_response_get_type(), nullptr)); self->value = fl_value_new_list(); - fl_value_append_take( - self->value, fl_value_new_uint8_list(return_value, return_value_length)); + fl_value_append_take(self->value, fl_value_ref(return_value)); return self; } -CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponse* -core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_new_error( +CoreTestsPigeonTestHostIntegrationCoreApiEchoIntListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_int_list_response_new_error( const gchar* code, const gchar* message, FlValue* details) { - CoreTestsPigeonTestHostIntegrationCoreApiEchoUint8ListResponse* self = - CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_UINT8_LIST_RESPONSE( + CoreTestsPigeonTestHostIntegrationCoreApiEchoIntListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_INT_LIST_RESPONSE( g_object_new( - core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_get_type(), + core_tests_pigeon_test_host_integration_core_api_echo_int_list_response_get_type(), nullptr)); self->value = fl_value_new_list(); fl_value_append_take(self->value, fl_value_new_string(code)); @@ -4460,60 +5626,61 @@ core_tests_pigeon_test_host_integration_core_api_echo_uint8_list_response_new_er return self; } -struct _CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponse { +struct _CoreTestsPigeonTestHostIntegrationCoreApiEchoDoubleListResponse { GObject parent_instance; FlValue* value; }; G_DEFINE_TYPE( - CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponse, - core_tests_pigeon_test_host_integration_core_api_echo_object_response, + CoreTestsPigeonTestHostIntegrationCoreApiEchoDoubleListResponse, + core_tests_pigeon_test_host_integration_core_api_echo_double_list_response, G_TYPE_OBJECT) static void -core_tests_pigeon_test_host_integration_core_api_echo_object_response_dispose( +core_tests_pigeon_test_host_integration_core_api_echo_double_list_response_dispose( GObject* object) { - CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponse* self = - CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_OBJECT_RESPONSE( + CoreTestsPigeonTestHostIntegrationCoreApiEchoDoubleListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_DOUBLE_LIST_RESPONSE( object); g_clear_pointer(&self->value, fl_value_unref); G_OBJECT_CLASS( - core_tests_pigeon_test_host_integration_core_api_echo_object_response_parent_class) + core_tests_pigeon_test_host_integration_core_api_echo_double_list_response_parent_class) ->dispose(object); } static void -core_tests_pigeon_test_host_integration_core_api_echo_object_response_init( - CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponse* self) {} +core_tests_pigeon_test_host_integration_core_api_echo_double_list_response_init( + CoreTestsPigeonTestHostIntegrationCoreApiEchoDoubleListResponse* self) {} static void -core_tests_pigeon_test_host_integration_core_api_echo_object_response_class_init( - CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponseClass* klass) { +core_tests_pigeon_test_host_integration_core_api_echo_double_list_response_class_init( + CoreTestsPigeonTestHostIntegrationCoreApiEchoDoubleListResponseClass* + klass) { G_OBJECT_CLASS(klass)->dispose = - core_tests_pigeon_test_host_integration_core_api_echo_object_response_dispose; + core_tests_pigeon_test_host_integration_core_api_echo_double_list_response_dispose; } -CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponse* -core_tests_pigeon_test_host_integration_core_api_echo_object_response_new( +CoreTestsPigeonTestHostIntegrationCoreApiEchoDoubleListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_double_list_response_new( FlValue* return_value) { - CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponse* self = - CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_OBJECT_RESPONSE( + CoreTestsPigeonTestHostIntegrationCoreApiEchoDoubleListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_DOUBLE_LIST_RESPONSE( g_object_new( - core_tests_pigeon_test_host_integration_core_api_echo_object_response_get_type(), + core_tests_pigeon_test_host_integration_core_api_echo_double_list_response_get_type(), nullptr)); self->value = fl_value_new_list(); fl_value_append_take(self->value, fl_value_ref(return_value)); return self; } -CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponse* -core_tests_pigeon_test_host_integration_core_api_echo_object_response_new_error( +CoreTestsPigeonTestHostIntegrationCoreApiEchoDoubleListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_double_list_response_new_error( const gchar* code, const gchar* message, FlValue* details) { - CoreTestsPigeonTestHostIntegrationCoreApiEchoObjectResponse* self = - CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_OBJECT_RESPONSE( + CoreTestsPigeonTestHostIntegrationCoreApiEchoDoubleListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_DOUBLE_LIST_RESPONSE( g_object_new( - core_tests_pigeon_test_host_integration_core_api_echo_object_response_get_type(), + core_tests_pigeon_test_host_integration_core_api_echo_double_list_response_get_type(), nullptr)); self->value = fl_value_new_list(); fl_value_append_take(self->value, fl_value_new_string(code)); @@ -4524,59 +5691,61 @@ core_tests_pigeon_test_host_integration_core_api_echo_object_response_new_error( return self; } -struct _CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse { +struct _CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolListResponse { GObject parent_instance; FlValue* value; }; G_DEFINE_TYPE( - CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse, - core_tests_pigeon_test_host_integration_core_api_echo_list_response, + CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolListResponse, + core_tests_pigeon_test_host_integration_core_api_echo_bool_list_response, G_TYPE_OBJECT) static void -core_tests_pigeon_test_host_integration_core_api_echo_list_response_dispose( +core_tests_pigeon_test_host_integration_core_api_echo_bool_list_response_dispose( GObject* object) { - CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse* self = - CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_LIST_RESPONSE( + CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_BOOL_LIST_RESPONSE( object); g_clear_pointer(&self->value, fl_value_unref); G_OBJECT_CLASS( - core_tests_pigeon_test_host_integration_core_api_echo_list_response_parent_class) + core_tests_pigeon_test_host_integration_core_api_echo_bool_list_response_parent_class) ->dispose(object); } static void -core_tests_pigeon_test_host_integration_core_api_echo_list_response_init( - CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse* self) {} +core_tests_pigeon_test_host_integration_core_api_echo_bool_list_response_init( + CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolListResponse* self) {} static void -core_tests_pigeon_test_host_integration_core_api_echo_list_response_class_init( - CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponseClass* klass) { +core_tests_pigeon_test_host_integration_core_api_echo_bool_list_response_class_init( + CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolListResponseClass* klass) { G_OBJECT_CLASS(klass)->dispose = - core_tests_pigeon_test_host_integration_core_api_echo_list_response_dispose; + core_tests_pigeon_test_host_integration_core_api_echo_bool_list_response_dispose; } -CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse* -core_tests_pigeon_test_host_integration_core_api_echo_list_response_new( +CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_bool_list_response_new( FlValue* return_value) { - CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse* self = - CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_LIST_RESPONSE(g_object_new( - core_tests_pigeon_test_host_integration_core_api_echo_list_response_get_type(), - nullptr)); + CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_BOOL_LIST_RESPONSE( + g_object_new( + core_tests_pigeon_test_host_integration_core_api_echo_bool_list_response_get_type(), + nullptr)); self->value = fl_value_new_list(); fl_value_append_take(self->value, fl_value_ref(return_value)); return self; } -CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse* -core_tests_pigeon_test_host_integration_core_api_echo_list_response_new_error( +CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_bool_list_response_new_error( const gchar* code, const gchar* message, FlValue* details) { - CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse* self = - CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_LIST_RESPONSE(g_object_new( - core_tests_pigeon_test_host_integration_core_api_echo_list_response_get_type(), - nullptr)); + CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolListResponse* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API_ECHO_BOOL_LIST_RESPONSE( + g_object_new( + core_tests_pigeon_test_host_integration_core_api_echo_bool_list_response_get_type(), + nullptr)); self->value = fl_value_new_list(); fl_value_append_take(self->value, fl_value_new_string(code)); fl_value_append_take(self->value, @@ -15347,6 +16516,120 @@ static void core_tests_pigeon_test_host_integration_core_api_echo_list_cb( } } +static void +core_tests_pigeon_test_host_integration_core_api_echo_string_list_cb( + FlBasicMessageChannel* channel, FlValue* message_, + FlBasicMessageChannelResponseHandle* response_handle, gpointer user_data) { + CoreTestsPigeonTestHostIntegrationCoreApi* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API(user_data); + + if (self->vtable == nullptr || self->vtable->echo_string_list == nullptr) { + return; + } + + FlValue* value0 = fl_value_get_list_value(message_, 0); + FlValue* string_list = value0; + g_autoptr(CoreTestsPigeonTestHostIntegrationCoreApiEchoStringListResponse) + response = self->vtable->echo_string_list(string_list, self->user_data); + if (response == nullptr) { + g_warning("No response returned to %s.%s", "HostIntegrationCoreApi", + "echoStringList"); + return; + } + + g_autoptr(GError) error = NULL; + if (!fl_basic_message_channel_respond(channel, response_handle, + response->value, &error)) { + g_warning("Failed to send response to %s.%s: %s", "HostIntegrationCoreApi", + "echoStringList", error->message); + } +} + +static void core_tests_pigeon_test_host_integration_core_api_echo_int_list_cb( + FlBasicMessageChannel* channel, FlValue* message_, + FlBasicMessageChannelResponseHandle* response_handle, gpointer user_data) { + CoreTestsPigeonTestHostIntegrationCoreApi* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API(user_data); + + if (self->vtable == nullptr || self->vtable->echo_int_list == nullptr) { + return; + } + + FlValue* value0 = fl_value_get_list_value(message_, 0); + FlValue* int_list = value0; + g_autoptr(CoreTestsPigeonTestHostIntegrationCoreApiEchoIntListResponse) + response = self->vtable->echo_int_list(int_list, self->user_data); + if (response == nullptr) { + g_warning("No response returned to %s.%s", "HostIntegrationCoreApi", + "echoIntList"); + return; + } + + g_autoptr(GError) error = NULL; + if (!fl_basic_message_channel_respond(channel, response_handle, + response->value, &error)) { + g_warning("Failed to send response to %s.%s: %s", "HostIntegrationCoreApi", + "echoIntList", error->message); + } +} + +static void +core_tests_pigeon_test_host_integration_core_api_echo_double_list_cb( + FlBasicMessageChannel* channel, FlValue* message_, + FlBasicMessageChannelResponseHandle* response_handle, gpointer user_data) { + CoreTestsPigeonTestHostIntegrationCoreApi* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API(user_data); + + if (self->vtable == nullptr || self->vtable->echo_double_list == nullptr) { + return; + } + + FlValue* value0 = fl_value_get_list_value(message_, 0); + FlValue* double_list = value0; + g_autoptr(CoreTestsPigeonTestHostIntegrationCoreApiEchoDoubleListResponse) + response = self->vtable->echo_double_list(double_list, self->user_data); + if (response == nullptr) { + g_warning("No response returned to %s.%s", "HostIntegrationCoreApi", + "echoDoubleList"); + return; + } + + g_autoptr(GError) error = NULL; + if (!fl_basic_message_channel_respond(channel, response_handle, + response->value, &error)) { + g_warning("Failed to send response to %s.%s: %s", "HostIntegrationCoreApi", + "echoDoubleList", error->message); + } +} + +static void core_tests_pigeon_test_host_integration_core_api_echo_bool_list_cb( + FlBasicMessageChannel* channel, FlValue* message_, + FlBasicMessageChannelResponseHandle* response_handle, gpointer user_data) { + CoreTestsPigeonTestHostIntegrationCoreApi* self = + CORE_TESTS_PIGEON_TEST_HOST_INTEGRATION_CORE_API(user_data); + + if (self->vtable == nullptr || self->vtable->echo_bool_list == nullptr) { + return; + } + + FlValue* value0 = fl_value_get_list_value(message_, 0); + FlValue* bool_list = value0; + g_autoptr(CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolListResponse) + response = self->vtable->echo_bool_list(bool_list, self->user_data); + if (response == nullptr) { + g_warning("No response returned to %s.%s", "HostIntegrationCoreApi", + "echoBoolList"); + return; + } + + g_autoptr(GError) error = NULL; + if (!fl_basic_message_channel_respond(channel, response_handle, + response->value, &error)) { + g_warning("Failed to send response to %s.%s: %s", "HostIntegrationCoreApi", + "echoBoolList", error->message); + } +} + static void core_tests_pigeon_test_host_integration_core_api_echo_enum_list_cb( FlBasicMessageChannel* channel, FlValue* message_, FlBasicMessageChannelResponseHandle* response_handle, gpointer user_data) { @@ -19163,6 +20446,50 @@ void core_tests_pigeon_test_host_integration_core_api_set_method_handlers( echo_list_channel, core_tests_pigeon_test_host_integration_core_api_echo_list_cb, g_object_ref(api_data), g_object_unref); + g_autofree gchar* echo_string_list_channel_name = g_strdup_printf( + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi." + "echoStringList%s", + dot_suffix); + g_autoptr(FlBasicMessageChannel) echo_string_list_channel = + fl_basic_message_channel_new(messenger, echo_string_list_channel_name, + FL_MESSAGE_CODEC(codec)); + fl_basic_message_channel_set_message_handler( + echo_string_list_channel, + core_tests_pigeon_test_host_integration_core_api_echo_string_list_cb, + g_object_ref(api_data), g_object_unref); + g_autofree gchar* echo_int_list_channel_name = g_strdup_printf( + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi." + "echoIntList%s", + dot_suffix); + g_autoptr(FlBasicMessageChannel) echo_int_list_channel = + fl_basic_message_channel_new(messenger, echo_int_list_channel_name, + FL_MESSAGE_CODEC(codec)); + fl_basic_message_channel_set_message_handler( + echo_int_list_channel, + core_tests_pigeon_test_host_integration_core_api_echo_int_list_cb, + g_object_ref(api_data), g_object_unref); + g_autofree gchar* echo_double_list_channel_name = g_strdup_printf( + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi." + "echoDoubleList%s", + dot_suffix); + g_autoptr(FlBasicMessageChannel) echo_double_list_channel = + fl_basic_message_channel_new(messenger, echo_double_list_channel_name, + FL_MESSAGE_CODEC(codec)); + fl_basic_message_channel_set_message_handler( + echo_double_list_channel, + core_tests_pigeon_test_host_integration_core_api_echo_double_list_cb, + g_object_ref(api_data), g_object_unref); + g_autofree gchar* echo_bool_list_channel_name = g_strdup_printf( + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi." + "echoBoolList%s", + dot_suffix); + g_autoptr(FlBasicMessageChannel) echo_bool_list_channel = + fl_basic_message_channel_new(messenger, echo_bool_list_channel_name, + FL_MESSAGE_CODEC(codec)); + fl_basic_message_channel_set_message_handler( + echo_bool_list_channel, + core_tests_pigeon_test_host_integration_core_api_echo_bool_list_cb, + g_object_ref(api_data), g_object_unref); g_autofree gchar* echo_enum_list_channel_name = g_strdup_printf( "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi." "echoEnumList%s", @@ -21075,6 +22402,42 @@ void core_tests_pigeon_test_host_integration_core_api_clear_method_handlers( FL_MESSAGE_CODEC(codec)); fl_basic_message_channel_set_message_handler(echo_list_channel, nullptr, nullptr, nullptr); + g_autofree gchar* echo_string_list_channel_name = g_strdup_printf( + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi." + "echoStringList%s", + dot_suffix); + g_autoptr(FlBasicMessageChannel) echo_string_list_channel = + fl_basic_message_channel_new(messenger, echo_string_list_channel_name, + FL_MESSAGE_CODEC(codec)); + fl_basic_message_channel_set_message_handler(echo_string_list_channel, + nullptr, nullptr, nullptr); + g_autofree gchar* echo_int_list_channel_name = g_strdup_printf( + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi." + "echoIntList%s", + dot_suffix); + g_autoptr(FlBasicMessageChannel) echo_int_list_channel = + fl_basic_message_channel_new(messenger, echo_int_list_channel_name, + FL_MESSAGE_CODEC(codec)); + fl_basic_message_channel_set_message_handler(echo_int_list_channel, nullptr, + nullptr, nullptr); + g_autofree gchar* echo_double_list_channel_name = g_strdup_printf( + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi." + "echoDoubleList%s", + dot_suffix); + g_autoptr(FlBasicMessageChannel) echo_double_list_channel = + fl_basic_message_channel_new(messenger, echo_double_list_channel_name, + FL_MESSAGE_CODEC(codec)); + fl_basic_message_channel_set_message_handler(echo_double_list_channel, + nullptr, nullptr, nullptr); + g_autofree gchar* echo_bool_list_channel_name = g_strdup_printf( + "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi." + "echoBoolList%s", + dot_suffix); + g_autoptr(FlBasicMessageChannel) echo_bool_list_channel = + fl_basic_message_channel_new(messenger, echo_bool_list_channel_name, + FL_MESSAGE_CODEC(codec)); + fl_basic_message_channel_set_message_handler(echo_bool_list_channel, nullptr, + nullptr, nullptr); g_autofree gchar* echo_enum_list_channel_name = g_strdup_printf( "dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi." "echoEnumList%s", diff --git a/packages/pigeon/platform_tests/test_plugin/linux/pigeon/core_tests.gen.h b/packages/pigeon/platform_tests/test_plugin/linux/pigeon/core_tests.gen.h index 322b9bc8a6b5..e5d97e289756 100644 --- a/packages/pigeon/platform_tests/test_plugin/linux/pigeon/core_tests.gen.h +++ b/packages/pigeon/platform_tests/test_plugin/linux/pigeon/core_tests.gen.h @@ -92,6 +92,17 @@ gboolean core_tests_pigeon_test_unused_class_equals( guint core_tests_pigeon_test_unused_class_hash( CoreTestsPigeonTestUnusedClass* object); +/** + * core_tests_pigeon_test_unused_class_to_string: + * @object: a #CoreTestsPigeonTestUnusedClass. + * + * Returns a string representation of a #CoreTestsPigeonTestUnusedClass object. + * + * Returns: (transfer full): a new string, free with g_free(). + */ +gchar* core_tests_pigeon_test_unused_class_to_string( + CoreTestsPigeonTestUnusedClass* object); + /** * CoreTestsPigeonTestAllTypes: * @@ -491,6 +502,17 @@ gboolean core_tests_pigeon_test_all_types_equals( guint core_tests_pigeon_test_all_types_hash( CoreTestsPigeonTestAllTypes* object); +/** + * core_tests_pigeon_test_all_types_to_string: + * @object: a #CoreTestsPigeonTestAllTypes. + * + * Returns a string representation of a #CoreTestsPigeonTestAllTypes object. + * + * Returns: (transfer full): a new string, free with g_free(). + */ +gchar* core_tests_pigeon_test_all_types_to_string( + CoreTestsPigeonTestAllTypes* object); + /** * CoreTestsPigeonTestAllNullableTypes: * @@ -938,6 +960,18 @@ gboolean core_tests_pigeon_test_all_nullable_types_equals( guint core_tests_pigeon_test_all_nullable_types_hash( CoreTestsPigeonTestAllNullableTypes* object); +/** + * core_tests_pigeon_test_all_nullable_types_to_string: + * @object: a #CoreTestsPigeonTestAllNullableTypes. + * + * Returns a string representation of a #CoreTestsPigeonTestAllNullableTypes + * object. + * + * Returns: (transfer full): a new string, free with g_free(). + */ +gchar* core_tests_pigeon_test_all_nullable_types_to_string( + CoreTestsPigeonTestAllNullableTypes* object); + /** * CoreTestsPigeonTestAllNullableTypesWithoutRecursion: * @@ -1375,6 +1409,18 @@ gboolean core_tests_pigeon_test_all_nullable_types_without_recursion_equals( guint core_tests_pigeon_test_all_nullable_types_without_recursion_hash( CoreTestsPigeonTestAllNullableTypesWithoutRecursion* object); +/** + * core_tests_pigeon_test_all_nullable_types_without_recursion_to_string: + * @object: a #CoreTestsPigeonTestAllNullableTypesWithoutRecursion. + * + * Returns a string representation of a + * #CoreTestsPigeonTestAllNullableTypesWithoutRecursion object. + * + * Returns: (transfer full): a new string, free with g_free(). + */ +gchar* core_tests_pigeon_test_all_nullable_types_without_recursion_to_string( + CoreTestsPigeonTestAllNullableTypesWithoutRecursion* object); + /** * CoreTestsPigeonTestAllClassesWrapper: * @@ -1516,6 +1562,18 @@ gboolean core_tests_pigeon_test_all_classes_wrapper_equals( guint core_tests_pigeon_test_all_classes_wrapper_hash( CoreTestsPigeonTestAllClassesWrapper* object); +/** + * core_tests_pigeon_test_all_classes_wrapper_to_string: + * @object: a #CoreTestsPigeonTestAllClassesWrapper. + * + * Returns a string representation of a #CoreTestsPigeonTestAllClassesWrapper + * object. + * + * Returns: (transfer full): a new string, free with g_free(). + */ +gchar* core_tests_pigeon_test_all_classes_wrapper_to_string( + CoreTestsPigeonTestAllClassesWrapper* object); + /** * CoreTestsPigeonTestTestMessage: * @@ -1571,6 +1629,17 @@ gboolean core_tests_pigeon_test_test_message_equals( guint core_tests_pigeon_test_test_message_hash( CoreTestsPigeonTestTestMessage* object); +/** + * core_tests_pigeon_test_test_message_to_string: + * @object: a #CoreTestsPigeonTestTestMessage. + * + * Returns a string representation of a #CoreTestsPigeonTestTestMessage object. + * + * Returns: (transfer full): a new string, free with g_free(). + */ +gchar* core_tests_pigeon_test_test_message_to_string( + CoreTestsPigeonTestTestMessage* object); + G_DECLARE_FINAL_TYPE(CoreTestsPigeonTestMessageCodec, core_tests_pigeon_test_message_codec, CORE_TESTS_PIGEON_TEST, MESSAGE_CODEC, @@ -1977,6 +2046,134 @@ CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse* core_tests_pigeon_test_host_integration_core_api_echo_list_response_new_error( const gchar* code, const gchar* message, FlValue* details); +G_DECLARE_FINAL_TYPE( + CoreTestsPigeonTestHostIntegrationCoreApiEchoStringListResponse, + core_tests_pigeon_test_host_integration_core_api_echo_string_list_response, + CORE_TESTS_PIGEON_TEST, HOST_INTEGRATION_CORE_API_ECHO_STRING_LIST_RESPONSE, + GObject) + +/** + * core_tests_pigeon_test_host_integration_core_api_echo_string_list_response_new: + * + * Creates a new response to HostIntegrationCoreApi.echoStringList. + * + * Returns: a new + * #CoreTestsPigeonTestHostIntegrationCoreApiEchoStringListResponse + */ +CoreTestsPigeonTestHostIntegrationCoreApiEchoStringListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_string_list_response_new( + FlValue* return_value); + +/** + * core_tests_pigeon_test_host_integration_core_api_echo_string_list_response_new_error: + * @code: error code. + * @message: error message. + * @details: (allow-none): error details or %NULL. + * + * Creates a new error response to HostIntegrationCoreApi.echoStringList. + * + * Returns: a new + * #CoreTestsPigeonTestHostIntegrationCoreApiEchoStringListResponse + */ +CoreTestsPigeonTestHostIntegrationCoreApiEchoStringListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_string_list_response_new_error( + const gchar* code, const gchar* message, FlValue* details); + +G_DECLARE_FINAL_TYPE( + CoreTestsPigeonTestHostIntegrationCoreApiEchoIntListResponse, + core_tests_pigeon_test_host_integration_core_api_echo_int_list_response, + CORE_TESTS_PIGEON_TEST, HOST_INTEGRATION_CORE_API_ECHO_INT_LIST_RESPONSE, + GObject) + +/** + * core_tests_pigeon_test_host_integration_core_api_echo_int_list_response_new: + * + * Creates a new response to HostIntegrationCoreApi.echoIntList. + * + * Returns: a new #CoreTestsPigeonTestHostIntegrationCoreApiEchoIntListResponse + */ +CoreTestsPigeonTestHostIntegrationCoreApiEchoIntListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_int_list_response_new( + FlValue* return_value); + +/** + * core_tests_pigeon_test_host_integration_core_api_echo_int_list_response_new_error: + * @code: error code. + * @message: error message. + * @details: (allow-none): error details or %NULL. + * + * Creates a new error response to HostIntegrationCoreApi.echoIntList. + * + * Returns: a new #CoreTestsPigeonTestHostIntegrationCoreApiEchoIntListResponse + */ +CoreTestsPigeonTestHostIntegrationCoreApiEchoIntListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_int_list_response_new_error( + const gchar* code, const gchar* message, FlValue* details); + +G_DECLARE_FINAL_TYPE( + CoreTestsPigeonTestHostIntegrationCoreApiEchoDoubleListResponse, + core_tests_pigeon_test_host_integration_core_api_echo_double_list_response, + CORE_TESTS_PIGEON_TEST, HOST_INTEGRATION_CORE_API_ECHO_DOUBLE_LIST_RESPONSE, + GObject) + +/** + * core_tests_pigeon_test_host_integration_core_api_echo_double_list_response_new: + * + * Creates a new response to HostIntegrationCoreApi.echoDoubleList. + * + * Returns: a new + * #CoreTestsPigeonTestHostIntegrationCoreApiEchoDoubleListResponse + */ +CoreTestsPigeonTestHostIntegrationCoreApiEchoDoubleListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_double_list_response_new( + FlValue* return_value); + +/** + * core_tests_pigeon_test_host_integration_core_api_echo_double_list_response_new_error: + * @code: error code. + * @message: error message. + * @details: (allow-none): error details or %NULL. + * + * Creates a new error response to HostIntegrationCoreApi.echoDoubleList. + * + * Returns: a new + * #CoreTestsPigeonTestHostIntegrationCoreApiEchoDoubleListResponse + */ +CoreTestsPigeonTestHostIntegrationCoreApiEchoDoubleListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_double_list_response_new_error( + const gchar* code, const gchar* message, FlValue* details); + +G_DECLARE_FINAL_TYPE( + CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolListResponse, + core_tests_pigeon_test_host_integration_core_api_echo_bool_list_response, + CORE_TESTS_PIGEON_TEST, HOST_INTEGRATION_CORE_API_ECHO_BOOL_LIST_RESPONSE, + GObject) + +/** + * core_tests_pigeon_test_host_integration_core_api_echo_bool_list_response_new: + * + * Creates a new response to HostIntegrationCoreApi.echoBoolList. + * + * Returns: a new #CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolListResponse + */ +CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_bool_list_response_new( + FlValue* return_value); + +/** + * core_tests_pigeon_test_host_integration_core_api_echo_bool_list_response_new_error: + * @code: error code. + * @message: error message. + * @details: (allow-none): error details or %NULL. + * + * Creates a new error response to HostIntegrationCoreApi.echoBoolList. + * + * Returns: a new #CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolListResponse + */ +CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolListResponse* +core_tests_pigeon_test_host_integration_core_api_echo_bool_list_response_new_error( + const gchar* code, const gchar* message, FlValue* details); + G_DECLARE_FINAL_TYPE( CoreTestsPigeonTestHostIntegrationCoreApiEchoEnumListResponse, core_tests_pigeon_test_host_integration_core_api_echo_enum_list_response, @@ -3812,6 +4009,14 @@ typedef struct { FlValue* an_object, gpointer user_data); CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse* (*echo_list)( FlValue* list, gpointer user_data); + CoreTestsPigeonTestHostIntegrationCoreApiEchoStringListResponse* ( + *echo_string_list)(FlValue* string_list, gpointer user_data); + CoreTestsPigeonTestHostIntegrationCoreApiEchoIntListResponse* ( + *echo_int_list)(FlValue* int_list, gpointer user_data); + CoreTestsPigeonTestHostIntegrationCoreApiEchoDoubleListResponse* ( + *echo_double_list)(FlValue* double_list, gpointer user_data); + CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolListResponse* ( + *echo_bool_list)(FlValue* bool_list, gpointer user_data); CoreTestsPigeonTestHostIntegrationCoreApiEchoEnumListResponse* ( *echo_enum_list)(FlValue* enum_list, gpointer user_data); CoreTestsPigeonTestHostIntegrationCoreApiEchoClassListResponse* ( diff --git a/packages/pigeon/platform_tests/test_plugin/linux/test/equality_test.cc b/packages/pigeon/platform_tests/test_plugin/linux/test/data_class_methods_test.cc similarity index 78% rename from packages/pigeon/platform_tests/test_plugin/linux/test/equality_test.cc rename to packages/pigeon/platform_tests/test_plugin/linux/test/data_class_methods_test.cc index 349c4bdd34cb..0346da708dec 100644 --- a/packages/pigeon/platform_tests/test_plugin/linux/test/equality_test.cc +++ b/packages/pigeon/platform_tests/test_plugin/linux/test/data_class_methods_test.cc @@ -236,3 +236,70 @@ TEST(Equality, SignedZeroMapValue) { EXPECT_EQ(core_tests_pigeon_test_all_nullable_types_hash(all1), core_tests_pigeon_test_all_nullable_types_hash(all2)); } + +TEST(Equality, ToStringSnapshot) { + g_autoptr(CoreTestsPigeonTestAllNullableTypes) empty_obj = + create_empty_all_nullable_types(); + + gchar* str = core_tests_pigeon_test_all_nullable_types_to_string(empty_obj); + ASSERT_NE(str, nullptr); + + // Verify structural validation across all 31 serialized fields. + const char* expected_fields[] = {"AllNullableTypes(", + "a_nullable_bool: null", + "a_nullable_int: null", + "a_nullable_int64: null", + "a_nullable_double: null", + "a_nullable_byte_array: null", + "a_nullable4_byte_array: null", + "a_nullable8_byte_array: null", + "a_nullable_float_array: null", + "a_nullable_enum: null", + "another_nullable_enum: null", + "a_nullable_string: null", + "a_nullable_object: null", + "all_nullable_types: null", + "list: null", + "string_list: null", + "int_list: null", + "double_list: null", + "bool_list: null", + "enum_list: null", + "object_list: null", + "list_list: null", + "map_list: null", + "recursive_class_list: null", + "map: null", + "string_map: null", + "int_map: null", + "enum_map: null", + "object_map: null", + "list_map: null", + "map_map: null", + "recursive_class_map: null"}; + + for (const char* field : expected_fields) { + EXPECT_TRUE(strstr(str, field) != nullptr) + << "Missing expected serialized field content: " << field; + } + + // Also verify exact expected canonical string layout for empty + // initialization. + const char* exact_expected = + "AllNullableTypes(a_nullable_bool: null, a_nullable_int: null, " + "a_nullable_int64: null, a_nullable_double: null, a_nullable_byte_array: " + "null, " + "a_nullable4_byte_array: null, a_nullable8_byte_array: null, " + "a_nullable_float_array: null, a_nullable_enum: null, " + "another_nullable_enum: null, a_nullable_string: null, " + "a_nullable_object: null, " + "all_nullable_types: null, list: null, string_list: null, int_list: " + "null, " + "double_list: null, bool_list: null, enum_list: null, object_list: null, " + "list_list: null, map_list: null, recursive_class_list: null, map: null, " + "string_map: null, int_map: null, enum_map: null, object_map: null, " + "list_map: null, map_map: null, recursive_class_map: null)"; + EXPECT_STREQ(str, exact_expected); + + g_free(str); +} diff --git a/packages/pigeon/platform_tests/test_plugin/linux/test_plugin.cc b/packages/pigeon/platform_tests/test_plugin/linux/test_plugin.cc index 693bb17eefee..1c4af93747d1 100644 --- a/packages/pigeon/platform_tests/test_plugin/linux/test_plugin.cc +++ b/packages/pigeon/platform_tests/test_plugin/linux/test_plugin.cc @@ -128,6 +128,30 @@ static CoreTestsPigeonTestHostIntegrationCoreApiEchoListResponse* echo_list( a_list); } +static CoreTestsPigeonTestHostIntegrationCoreApiEchoStringListResponse* +echo_string_list(FlValue* string_list, gpointer user_data) { + return core_tests_pigeon_test_host_integration_core_api_echo_string_list_response_new( + string_list); +} + +static CoreTestsPigeonTestHostIntegrationCoreApiEchoIntListResponse* +echo_int_list(FlValue* int_list, gpointer user_data) { + return core_tests_pigeon_test_host_integration_core_api_echo_int_list_response_new( + int_list); +} + +static CoreTestsPigeonTestHostIntegrationCoreApiEchoDoubleListResponse* +echo_double_list(FlValue* double_list, gpointer user_data) { + return core_tests_pigeon_test_host_integration_core_api_echo_double_list_response_new( + double_list); +} + +static CoreTestsPigeonTestHostIntegrationCoreApiEchoBoolListResponse* +echo_bool_list(FlValue* bool_list, gpointer user_data) { + return core_tests_pigeon_test_host_integration_core_api_echo_bool_list_response_new( + bool_list); +} + static CoreTestsPigeonTestHostIntegrationCoreApiEchoEnumListResponse* echo_enum_list(FlValue* enum_list, gpointer user_data) { return core_tests_pigeon_test_host_integration_core_api_echo_enum_list_response_new( @@ -3228,6 +3252,10 @@ static CoreTestsPigeonTestHostIntegrationCoreApiVTable host_core_api_vtable = { .echo_uint8_list = echo_uint8_list, .echo_object = echo_object, .echo_list = echo_list, + .echo_string_list = echo_string_list, + .echo_int_list = echo_int_list, + .echo_double_list = echo_double_list, + .echo_bool_list = echo_bool_list, .echo_enum_list = echo_enum_list, .echo_class_list = echo_class_list, .echo_non_null_enum_list = echo_non_null_enum_list, diff --git a/packages/pigeon/platform_tests/test_plugin/windows/CMakeLists.txt b/packages/pigeon/platform_tests/test_plugin/windows/CMakeLists.txt index 71fe7b878b29..582c49537f7d 100644 --- a/packages/pigeon/platform_tests/test_plugin/windows/CMakeLists.txt +++ b/packages/pigeon/platform_tests/test_plugin/windows/CMakeLists.txt @@ -102,6 +102,7 @@ FetchContent_MakeAvailable(googletest) # directly into the test binary rather than using the DLL. add_executable(${TEST_RUNNER} # Tests. + test/data_class_methods_test.cpp test/multiple_arity_test.cpp test/non_null_fields_test.cpp test/nullable_returns_test.cpp diff --git a/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.cpp b/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.cpp index f50c8eff918c..ac5d859f0fb7 100644 --- a/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.cpp +++ b/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include namespace core_tests_pigeontest { @@ -239,6 +240,101 @@ size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v) { return result; } +template +std::string PigeonInternalToString(const T& v); + +std::string PigeonInternalToString(const bool& v); + +template +std::string PigeonInternalToString(const std::vector& v); + +template +std::string PigeonInternalToString(const std::map& v); + +template +std::string PigeonInternalToString(const std::optional& v); + +template +std::string PigeonInternalToString(const std::unique_ptr& v); + +std::string PigeonInternalToString(const ::flutter::EncodableValue& v); + +template +std::string PigeonInternalToString(const T& v) { + std::stringstream ss; + if constexpr (std::is_enum_v) { + ss << static_cast(v); + } else { + ss << v; + } + return ss.str(); +} + +std::string PigeonInternalToString(const bool& v) { + return v ? "true" : "false"; +} + +template +std::string PigeonInternalToString(const std::vector& v) { + std::stringstream ss; + ss << "["; + for (size_t i = 0; i < v.size(); ++i) { + if (i > 0) { + ss << ", "; + } + ss << PigeonInternalToString(v[i]); + } + ss << "]"; + return ss.str(); +} + +template +std::string PigeonInternalToString(const std::map& v) { + std::stringstream ss; + ss << "{"; + bool first = true; + for (const auto& kv : v) { + if (!first) { + ss << ", "; + } + first = false; + ss << PigeonInternalToString(kv.first) << ": " + << PigeonInternalToString(kv.second); + } + ss << "}"; + return ss.str(); +} + +template +std::string PigeonInternalToString(const std::optional& v) { + return v ? PigeonInternalToString(*v) : "null"; +} + +template +std::string PigeonInternalToString(const std::unique_ptr& v) { + return v ? PigeonInternalToString(*v) : "null"; +} + +std::string PigeonInternalToString(const ::flutter::EncodableValue& v) { + return std::visit( + [](const auto& val) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + return std::string("null"); + } else if constexpr (std::is_same_v) { + return val ? std::string("true") : std::string("false"); + } else if constexpr (std::is_same_v) { + return "\"" + val + "\""; + } else if constexpr (std::is_same_v) { + return std::string("[custom]"); + } else { + return PigeonInternalToString(val); + } + }, + v); +} + } // namespace // UnusedClass @@ -291,6 +387,18 @@ size_t UnusedClass::Hash() const { return result; } +std::ostream& operator<<(std::ostream& os, const UnusedClass& obj) { + os << "UnusedClass("; + os << "a_field: "; + if (obj.a_field_.has_value()) { + os << PigeonInternalToString(*obj.a_field_); + } else { + os << "null"; + } + os << ")"; + return os; +} + size_t PigeonInternalDeepHash(const UnusedClass& v) { return v.Hash(); } // AllTypes @@ -629,6 +737,68 @@ size_t AllTypes::Hash() const { return result; } +std::ostream& operator<<(std::ostream& os, const AllTypes& obj) { + os << "AllTypes("; + os << "a_bool: "; + os << PigeonInternalToString(obj.a_bool_); + os << ", an_int: "; + os << PigeonInternalToString(obj.an_int_); + os << ", an_int64: "; + os << PigeonInternalToString(obj.an_int64_); + os << ", a_double: "; + os << PigeonInternalToString(obj.a_double_); + os << ", a_byte_array: "; + os << PigeonInternalToString(obj.a_byte_array_); + os << ", a4_byte_array: "; + os << PigeonInternalToString(obj.a4_byte_array_); + os << ", a8_byte_array: "; + os << PigeonInternalToString(obj.a8_byte_array_); + os << ", a_float_array: "; + os << PigeonInternalToString(obj.a_float_array_); + os << ", an_enum: "; + os << PigeonInternalToString(obj.an_enum_); + os << ", another_enum: "; + os << PigeonInternalToString(obj.another_enum_); + os << ", a_string: "; + os << PigeonInternalToString(obj.a_string_); + os << ", an_object: "; + os << PigeonInternalToString(obj.an_object_); + os << ", list: "; + os << PigeonInternalToString(obj.list_); + os << ", string_list: "; + os << PigeonInternalToString(obj.string_list_); + os << ", int_list: "; + os << PigeonInternalToString(obj.int_list_); + os << ", double_list: "; + os << PigeonInternalToString(obj.double_list_); + os << ", bool_list: "; + os << PigeonInternalToString(obj.bool_list_); + os << ", enum_list: "; + os << PigeonInternalToString(obj.enum_list_); + os << ", object_list: "; + os << PigeonInternalToString(obj.object_list_); + os << ", list_list: "; + os << PigeonInternalToString(obj.list_list_); + os << ", map_list: "; + os << PigeonInternalToString(obj.map_list_); + os << ", map: "; + os << PigeonInternalToString(obj.map_); + os << ", string_map: "; + os << PigeonInternalToString(obj.string_map_); + os << ", int_map: "; + os << PigeonInternalToString(obj.int_map_); + os << ", enum_map: "; + os << PigeonInternalToString(obj.enum_map_); + os << ", object_map: "; + os << PigeonInternalToString(obj.object_map_); + os << ", list_map: "; + os << PigeonInternalToString(obj.list_map_); + os << ", map_map: "; + os << PigeonInternalToString(obj.map_map_); + os << ")"; + return os; +} + size_t PigeonInternalDeepHash(const AllTypes& v) { return v.Hash(); } // AllNullableTypes @@ -1566,6 +1736,198 @@ size_t AllNullableTypes::Hash() const { return result; } +std::ostream& operator<<(std::ostream& os, const AllNullableTypes& obj) { + os << "AllNullableTypes("; + os << "a_nullable_bool: "; + if (obj.a_nullable_bool_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_bool_); + } else { + os << "null"; + } + os << ", a_nullable_int: "; + if (obj.a_nullable_int_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_int_); + } else { + os << "null"; + } + os << ", a_nullable_int64: "; + if (obj.a_nullable_int64_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_int64_); + } else { + os << "null"; + } + os << ", a_nullable_double: "; + if (obj.a_nullable_double_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_double_); + } else { + os << "null"; + } + os << ", a_nullable_byte_array: "; + if (obj.a_nullable_byte_array_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_byte_array_); + } else { + os << "null"; + } + os << ", a_nullable4_byte_array: "; + if (obj.a_nullable4_byte_array_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable4_byte_array_); + } else { + os << "null"; + } + os << ", a_nullable8_byte_array: "; + if (obj.a_nullable8_byte_array_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable8_byte_array_); + } else { + os << "null"; + } + os << ", a_nullable_float_array: "; + if (obj.a_nullable_float_array_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_float_array_); + } else { + os << "null"; + } + os << ", a_nullable_enum: "; + if (obj.a_nullable_enum_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_enum_); + } else { + os << "null"; + } + os << ", another_nullable_enum: "; + if (obj.another_nullable_enum_.has_value()) { + os << PigeonInternalToString(*obj.another_nullable_enum_); + } else { + os << "null"; + } + os << ", a_nullable_string: "; + if (obj.a_nullable_string_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_string_); + } else { + os << "null"; + } + os << ", a_nullable_object: "; + if (obj.a_nullable_object_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_object_); + } else { + os << "null"; + } + os << ", all_nullable_types: "; + if (obj.all_nullable_types_.has_value()) { + os << *obj.all_nullable_types_; + } else { + os << "null"; + } + os << ", list: "; + if (obj.list_.has_value()) { + os << PigeonInternalToString(*obj.list_); + } else { + os << "null"; + } + os << ", string_list: "; + if (obj.string_list_.has_value()) { + os << PigeonInternalToString(*obj.string_list_); + } else { + os << "null"; + } + os << ", int_list: "; + if (obj.int_list_.has_value()) { + os << PigeonInternalToString(*obj.int_list_); + } else { + os << "null"; + } + os << ", double_list: "; + if (obj.double_list_.has_value()) { + os << PigeonInternalToString(*obj.double_list_); + } else { + os << "null"; + } + os << ", bool_list: "; + if (obj.bool_list_.has_value()) { + os << PigeonInternalToString(*obj.bool_list_); + } else { + os << "null"; + } + os << ", enum_list: "; + if (obj.enum_list_.has_value()) { + os << PigeonInternalToString(*obj.enum_list_); + } else { + os << "null"; + } + os << ", object_list: "; + if (obj.object_list_.has_value()) { + os << PigeonInternalToString(*obj.object_list_); + } else { + os << "null"; + } + os << ", list_list: "; + if (obj.list_list_.has_value()) { + os << PigeonInternalToString(*obj.list_list_); + } else { + os << "null"; + } + os << ", map_list: "; + if (obj.map_list_.has_value()) { + os << PigeonInternalToString(*obj.map_list_); + } else { + os << "null"; + } + os << ", recursive_class_list: "; + if (obj.recursive_class_list_.has_value()) { + os << PigeonInternalToString(*obj.recursive_class_list_); + } else { + os << "null"; + } + os << ", map: "; + if (obj.map_.has_value()) { + os << PigeonInternalToString(*obj.map_); + } else { + os << "null"; + } + os << ", string_map: "; + if (obj.string_map_.has_value()) { + os << PigeonInternalToString(*obj.string_map_); + } else { + os << "null"; + } + os << ", int_map: "; + if (obj.int_map_.has_value()) { + os << PigeonInternalToString(*obj.int_map_); + } else { + os << "null"; + } + os << ", enum_map: "; + if (obj.enum_map_.has_value()) { + os << PigeonInternalToString(*obj.enum_map_); + } else { + os << "null"; + } + os << ", object_map: "; + if (obj.object_map_.has_value()) { + os << PigeonInternalToString(*obj.object_map_); + } else { + os << "null"; + } + os << ", list_map: "; + if (obj.list_map_.has_value()) { + os << PigeonInternalToString(*obj.list_map_); + } else { + os << "null"; + } + os << ", map_map: "; + if (obj.map_map_.has_value()) { + os << PigeonInternalToString(*obj.map_map_); + } else { + os << "null"; + } + os << ", recursive_class_map: "; + if (obj.recursive_class_map_.has_value()) { + os << PigeonInternalToString(*obj.recursive_class_map_); + } else { + os << "null"; + } + os << ")"; + return os; +} + size_t PigeonInternalDeepHash(const AllNullableTypes& v) { return v.Hash(); } // AllNullableTypesWithoutRecursion @@ -2332,6 +2694,181 @@ size_t AllNullableTypesWithoutRecursion::Hash() const { return result; } +std::ostream& operator<<(std::ostream& os, + const AllNullableTypesWithoutRecursion& obj) { + os << "AllNullableTypesWithoutRecursion("; + os << "a_nullable_bool: "; + if (obj.a_nullable_bool_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_bool_); + } else { + os << "null"; + } + os << ", a_nullable_int: "; + if (obj.a_nullable_int_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_int_); + } else { + os << "null"; + } + os << ", a_nullable_int64: "; + if (obj.a_nullable_int64_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_int64_); + } else { + os << "null"; + } + os << ", a_nullable_double: "; + if (obj.a_nullable_double_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_double_); + } else { + os << "null"; + } + os << ", a_nullable_byte_array: "; + if (obj.a_nullable_byte_array_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_byte_array_); + } else { + os << "null"; + } + os << ", a_nullable4_byte_array: "; + if (obj.a_nullable4_byte_array_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable4_byte_array_); + } else { + os << "null"; + } + os << ", a_nullable8_byte_array: "; + if (obj.a_nullable8_byte_array_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable8_byte_array_); + } else { + os << "null"; + } + os << ", a_nullable_float_array: "; + if (obj.a_nullable_float_array_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_float_array_); + } else { + os << "null"; + } + os << ", a_nullable_enum: "; + if (obj.a_nullable_enum_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_enum_); + } else { + os << "null"; + } + os << ", another_nullable_enum: "; + if (obj.another_nullable_enum_.has_value()) { + os << PigeonInternalToString(*obj.another_nullable_enum_); + } else { + os << "null"; + } + os << ", a_nullable_string: "; + if (obj.a_nullable_string_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_string_); + } else { + os << "null"; + } + os << ", a_nullable_object: "; + if (obj.a_nullable_object_.has_value()) { + os << PigeonInternalToString(*obj.a_nullable_object_); + } else { + os << "null"; + } + os << ", list: "; + if (obj.list_.has_value()) { + os << PigeonInternalToString(*obj.list_); + } else { + os << "null"; + } + os << ", string_list: "; + if (obj.string_list_.has_value()) { + os << PigeonInternalToString(*obj.string_list_); + } else { + os << "null"; + } + os << ", int_list: "; + if (obj.int_list_.has_value()) { + os << PigeonInternalToString(*obj.int_list_); + } else { + os << "null"; + } + os << ", double_list: "; + if (obj.double_list_.has_value()) { + os << PigeonInternalToString(*obj.double_list_); + } else { + os << "null"; + } + os << ", bool_list: "; + if (obj.bool_list_.has_value()) { + os << PigeonInternalToString(*obj.bool_list_); + } else { + os << "null"; + } + os << ", enum_list: "; + if (obj.enum_list_.has_value()) { + os << PigeonInternalToString(*obj.enum_list_); + } else { + os << "null"; + } + os << ", object_list: "; + if (obj.object_list_.has_value()) { + os << PigeonInternalToString(*obj.object_list_); + } else { + os << "null"; + } + os << ", list_list: "; + if (obj.list_list_.has_value()) { + os << PigeonInternalToString(*obj.list_list_); + } else { + os << "null"; + } + os << ", map_list: "; + if (obj.map_list_.has_value()) { + os << PigeonInternalToString(*obj.map_list_); + } else { + os << "null"; + } + os << ", map: "; + if (obj.map_.has_value()) { + os << PigeonInternalToString(*obj.map_); + } else { + os << "null"; + } + os << ", string_map: "; + if (obj.string_map_.has_value()) { + os << PigeonInternalToString(*obj.string_map_); + } else { + os << "null"; + } + os << ", int_map: "; + if (obj.int_map_.has_value()) { + os << PigeonInternalToString(*obj.int_map_); + } else { + os << "null"; + } + os << ", enum_map: "; + if (obj.enum_map_.has_value()) { + os << PigeonInternalToString(*obj.enum_map_); + } else { + os << "null"; + } + os << ", object_map: "; + if (obj.object_map_.has_value()) { + os << PigeonInternalToString(*obj.object_map_); + } else { + os << "null"; + } + os << ", list_map: "; + if (obj.list_map_.has_value()) { + os << PigeonInternalToString(*obj.list_map_); + } else { + os << "null"; + } + os << ", map_map: "; + if (obj.map_map_.has_value()) { + os << PigeonInternalToString(*obj.map_map_); + } else { + os << "null"; + } + os << ")"; + return os; +} + size_t PigeonInternalDeepHash(const AllNullableTypesWithoutRecursion& v) { return v.Hash(); } @@ -2574,6 +3111,42 @@ size_t AllClassesWrapper::Hash() const { return result; } +std::ostream& operator<<(std::ostream& os, const AllClassesWrapper& obj) { + os << "AllClassesWrapper("; + os << "all_nullable_types: "; + os << obj.all_nullable_types_; + os << ", all_nullable_types_without_recursion: "; + if (obj.all_nullable_types_without_recursion_.has_value()) { + os << *obj.all_nullable_types_without_recursion_; + } else { + os << "null"; + } + os << ", all_types: "; + if (obj.all_types_.has_value()) { + os << *obj.all_types_; + } else { + os << "null"; + } + os << ", class_list: "; + os << PigeonInternalToString(obj.class_list_); + os << ", nullable_class_list: "; + if (obj.nullable_class_list_.has_value()) { + os << PigeonInternalToString(*obj.nullable_class_list_); + } else { + os << "null"; + } + os << ", class_map: "; + os << PigeonInternalToString(obj.class_map_); + os << ", nullable_class_map: "; + if (obj.nullable_class_map_.has_value()) { + os << PigeonInternalToString(*obj.nullable_class_map_); + } else { + os << "null"; + } + os << ")"; + return os; +} + size_t PigeonInternalDeepHash(const AllClassesWrapper& v) { return v.Hash(); } // TestMessage @@ -2627,6 +3200,18 @@ size_t TestMessage::Hash() const { return result; } +std::ostream& operator<<(std::ostream& os, const TestMessage& obj) { + os << "TestMessage("; + os << "test_list: "; + if (obj.test_list_.has_value()) { + os << PigeonInternalToString(*obj.test_list_); + } else { + os << "null"; + } + os << ")"; + return os; +} + size_t PigeonInternalDeepHash(const TestMessage& v) { return v.Hash(); } PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} @@ -3169,6 +3754,148 @@ void HostIntegrationCoreApi::SetUp(::flutter::BinaryMessenger* binary_messenger, channel.SetMessageHandler(nullptr); } } + { + BasicMessageChannel<> channel(binary_messenger, + "dev.flutter.pigeon.pigeon_integration_tests." + "HostIntegrationCoreApi.echoStringList" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const ::flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_string_list_arg = args.at(0); + if (encodable_string_list_arg.IsNull()) { + reply(WrapError("string_list_arg unexpectedly null.")); + return; + } + const auto& string_list_arg = + std::get(encodable_string_list_arg); + ErrorOr output = + api->EchoStringList(string_list_arg); + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel(binary_messenger, + "dev.flutter.pigeon.pigeon_integration_tests." + "HostIntegrationCoreApi.echoIntList" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const ::flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_int_list_arg = args.at(0); + if (encodable_int_list_arg.IsNull()) { + reply(WrapError("int_list_arg unexpectedly null.")); + return; + } + const auto& int_list_arg = + std::get(encodable_int_list_arg); + ErrorOr output = api->EchoIntList(int_list_arg); + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel(binary_messenger, + "dev.flutter.pigeon.pigeon_integration_tests." + "HostIntegrationCoreApi.echoDoubleList" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const ::flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_double_list_arg = args.at(0); + if (encodable_double_list_arg.IsNull()) { + reply(WrapError("double_list_arg unexpectedly null.")); + return; + } + const auto& double_list_arg = + std::get(encodable_double_list_arg); + ErrorOr output = + api->EchoDoubleList(double_list_arg); + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel(binary_messenger, + "dev.flutter.pigeon.pigeon_integration_tests." + "HostIntegrationCoreApi.echoBoolList" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const ::flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_bool_list_arg = args.at(0); + if (encodable_bool_list_arg.IsNull()) { + reply(WrapError("bool_list_arg unexpectedly null.")); + return; + } + const auto& bool_list_arg = + std::get(encodable_bool_list_arg); + ErrorOr output = api->EchoBoolList(bool_list_arg); + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } { BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.pigeon_integration_tests." diff --git a/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.h b/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.h index 24ca4540d6a8..6778e1943213 100644 --- a/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.h +++ b/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.h @@ -14,6 +14,7 @@ #include #include +#include #include namespace core_tests_pigeontest { @@ -93,6 +94,8 @@ class UnusedClass { /// Returns a hash code value for the object. This method is supported for the /// benefit of hash tables. size_t Hash() const; + /// Stream output operator for formatted string representation. + friend std::ostream& operator<<(std::ostream& os, const UnusedClass& obj); private: static UnusedClass FromEncodableList(const ::flutter::EncodableList& list); @@ -227,6 +230,8 @@ class AllTypes { /// Returns a hash code value for the object. This method is supported for the /// benefit of hash tables. size_t Hash() const; + /// Stream output operator for formatted string representation. + friend std::ostream& operator<<(std::ostream& os, const AllTypes& obj); private: static AllTypes FromEncodableList(const ::flutter::EncodableList& list); @@ -442,6 +447,9 @@ class AllNullableTypes { /// Returns a hash code value for the object. This method is supported for the /// benefit of hash tables. size_t Hash() const; + /// Stream output operator for formatted string representation. + friend std::ostream& operator<<(std::ostream& os, + const AllNullableTypes& obj); private: static AllNullableTypes FromEncodableList( @@ -643,6 +651,9 @@ class AllNullableTypesWithoutRecursion { /// Returns a hash code value for the object. This method is supported for the /// benefit of hash tables. size_t Hash() const; + /// Stream output operator for formatted string representation. + friend std::ostream& operator<<(std::ostream& os, + const AllNullableTypesWithoutRecursion& obj); private: static AllNullableTypesWithoutRecursion FromEncodableList( @@ -748,6 +759,9 @@ class AllClassesWrapper { /// Returns a hash code value for the object. This method is supported for the /// benefit of hash tables. size_t Hash() const; + /// Stream output operator for formatted string representation. + friend std::ostream& operator<<(std::ostream& os, + const AllClassesWrapper& obj); private: static AllClassesWrapper FromEncodableList( @@ -790,6 +804,8 @@ class TestMessage { /// Returns a hash code value for the object. This method is supported for the /// benefit of hash tables. size_t Hash() const; + /// Stream output operator for formatted string representation. + friend std::ostream& operator<<(std::ostream& os, const TestMessage& obj); private: static TestMessage FromEncodableList(const ::flutter::EncodableList& list); @@ -861,6 +877,18 @@ class HostIntegrationCoreApi { virtual ErrorOr<::flutter::EncodableList> EchoList( const ::flutter::EncodableList& list) = 0; // Returns the passed list, to test serialization and deserialization. + virtual ErrorOr<::flutter::EncodableList> EchoStringList( + const ::flutter::EncodableList& string_list) = 0; + // Returns the passed list, to test serialization and deserialization. + virtual ErrorOr<::flutter::EncodableList> EchoIntList( + const ::flutter::EncodableList& int_list) = 0; + // Returns the passed list, to test serialization and deserialization. + virtual ErrorOr<::flutter::EncodableList> EchoDoubleList( + const ::flutter::EncodableList& double_list) = 0; + // Returns the passed list, to test serialization and deserialization. + virtual ErrorOr<::flutter::EncodableList> EchoBoolList( + const ::flutter::EncodableList& bool_list) = 0; + // Returns the passed list, to test serialization and deserialization. virtual ErrorOr<::flutter::EncodableList> EchoEnumList( const ::flutter::EncodableList& enum_list) = 0; // Returns the passed list, to test serialization and deserialization. diff --git a/packages/pigeon/platform_tests/test_plugin/windows/test/equality_test.cpp b/packages/pigeon/platform_tests/test_plugin/windows/test/data_class_methods_test.cpp similarity index 55% rename from packages/pigeon/platform_tests/test_plugin/windows/test/equality_test.cpp rename to packages/pigeon/platform_tests/test_plugin/windows/test/data_class_methods_test.cpp index 79cfe24f9cb8..b94b84c92d2a 100644 --- a/packages/pigeon/platform_tests/test_plugin/windows/test/equality_test.cpp +++ b/packages/pigeon/platform_tests/test_plugin/windows/test/data_class_methods_test.cpp @@ -5,6 +5,7 @@ #include #include +#include #include "pigeon/core_tests.gen.h" @@ -100,5 +101,61 @@ TEST(EqualityTests, ZeroMapValueEquality) { EXPECT_EQ(all1, all2); } +TEST(SerializationTests, StreamOutputSnapshot) { + flutter::EncodableList list; + list.push_back(flutter::EncodableValue("hello")); + list.push_back(flutter::EncodableValue(42)); + + TestMessage msg; + msg.set_test_list(list); + + std::stringstream ss; + ss << msg; + + EXPECT_EQ(ss.str(), "TestMessage(testList: [\"hello\", 42])"); +} + +// On Windows, C++ stream serialization and std::map key traversal are +// completely deterministic and stable, allowing us to validate the entire +// output with a single exact string. +TEST(SerializationTests, StreamOutputFullSnapshot) { + AllNullableTypes everything; + everything.set_a_nullable_bool(true); + everything.set_a_nullable_int(1); + everything.set_a_nullable_double(2.0); + everything.set_a_nullable_string("123"); + + flutter::EncodableList list; + list.push_back(flutter::EncodableValue("string")); + list.push_back(flutter::EncodableValue(1)); + everything.set_list(list); + + flutter::EncodableMap map; + map[flutter::EncodableValue("hello")] = flutter::EncodableValue("you"); + everything.set_string_map(map); + + std::stringstream ss; + ss << everything; + + EXPECT_EQ( + ss.str(), + "AllNullableTypes(aNullableBool: true, aNullableInt: 1, aNullableInt64: " + "null, " + "aNullableDouble: 2, aNullableByteArray: null, aNullable4ByteArray: " + "null, " + "aNullable8ByteArray: null, aNullableFloatArray: null, aNullableEnum: " + "null, " + "anotherNullableEnum: null, aNullableString: 123, aNullableObject: null, " + "allNullableTypes: null, list: [\"string\", 1], stringList: null, " + "intList: null, " + "doubleList: null, boolList: null, enumList: null, objectList: null, " + "listList: null, " + "mapList: null, recursiveClassList: null, map: null, stringMap: " + "{\"hello\": \"you\"}, " + "intMap: null, enumMap: null, objectMap: null, listMap: null, mapMap: " + "null, " + "recursiveClassMap: null)"); +} + } // namespace test } // namespace test_plugin diff --git a/packages/pigeon/platform_tests/test_plugin/windows/test_plugin.cpp b/packages/pigeon/platform_tests/test_plugin/windows/test_plugin.cpp index 212e1866fa83..298b52cc278f 100644 --- a/packages/pigeon/platform_tests/test_plugin/windows/test_plugin.cpp +++ b/packages/pigeon/platform_tests/test_plugin/windows/test_plugin.cpp @@ -158,6 +158,25 @@ ErrorOr TestPlugin::EchoList(const EncodableList& a_list) { return a_list; } +ErrorOr TestPlugin::EchoStringList( + const EncodableList& string_list) { + return string_list; +} + +ErrorOr TestPlugin::EchoIntList(const EncodableList& int_list) { + return int_list; +} + +ErrorOr TestPlugin::EchoDoubleList( + const EncodableList& double_list) { + return double_list; +} + +ErrorOr TestPlugin::EchoBoolList( + const EncodableList& bool_list) { + return bool_list; +} + ErrorOr TestPlugin::EchoEnumList( const EncodableList& enum_list) { return enum_list; diff --git a/packages/pigeon/platform_tests/test_plugin/windows/test_plugin.h b/packages/pigeon/platform_tests/test_plugin/windows/test_plugin.h index a52bd83f03a2..066231295f95 100644 --- a/packages/pigeon/platform_tests/test_plugin/windows/test_plugin.h +++ b/packages/pigeon/platform_tests/test_plugin/windows/test_plugin.h @@ -91,6 +91,14 @@ class TestPlugin : public flutter::Plugin, const flutter::EncodableValue& an_object) override; core_tests_pigeontest::ErrorOr EchoList( const flutter::EncodableList& a_list) override; + core_tests_pigeontest::ErrorOr EchoStringList( + const flutter::EncodableList& string_list) override; + core_tests_pigeontest::ErrorOr EchoIntList( + const flutter::EncodableList& int_list) override; + core_tests_pigeontest::ErrorOr EchoDoubleList( + const flutter::EncodableList& double_list) override; + core_tests_pigeontest::ErrorOr EchoBoolList( + const flutter::EncodableList& bool_list) override; core_tests_pigeontest::ErrorOr EchoEnumList( const flutter::EncodableList& enum_list) override; core_tests_pigeontest::ErrorOr EchoClassList( diff --git a/packages/pigeon/pubspec.yaml b/packages/pigeon/pubspec.yaml index 7ac94252e537..f3a1ae8856e3 100644 --- a/packages/pigeon/pubspec.yaml +++ b/packages/pigeon/pubspec.yaml @@ -2,7 +2,7 @@ name: pigeon description: Code generator tool to make communication between Flutter and the host platform type-safe and easier. repository: https://github.com/flutter/packages/tree/main/packages/pigeon issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+pigeon%22 -version: 26.3.4 # This must match the version in lib/src/generator_tools.dart +version: 26.4.0 # This must match the version in lib/src/generator_tools.dart environment: sdk: ^3.10.0 diff --git a/packages/pigeon/test/cpp_generator_test.dart b/packages/pigeon/test/cpp_generator_test.dart index 0c77bed2b1de..94283a38ca55 100644 --- a/packages/pigeon/test/cpp_generator_test.dart +++ b/packages/pigeon/test/cpp_generator_test.dart @@ -535,6 +535,7 @@ void main() { #include #include +#include #include '''), ); @@ -571,6 +572,7 @@ void main() { #include #include #include +#include #include '''), ); @@ -2725,6 +2727,44 @@ void main() { expect(code, contains('bool Foo::operator==(const Foo& other) const {')); }); + test('data class operator<<', () { + final root = Root( + apis: [], + classes: [ + Class( + name: 'Foo', + fields: [ + NamedType( + type: const TypeDeclaration(baseName: 'int', isNullable: false), + name: 'bar', + ), + ], + ), + ], + enums: [], + ); + final sink = StringBuffer(); + const generator = CppGenerator(); + final generatorOptions = OutputFileOptions( + fileType: FileType.source, + languageOptions: const InternalCppOptions( + cppHeaderOut: '', + cppSourceOut: '', + headerIncludePath: '', + ), + ); + generator.generate( + generatorOptions, + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final code = sink.toString(); + expect(code, contains('std::ostream& operator<<(')); + expect(code, contains('os << "bar: ";')); + expect(code, contains('os << PigeonInternalToString(obj.bar_);')); + }); + test('data classes implement Hash', () { final root = Root( apis: [], diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index f3774fc75c92..01dd129b06b3 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -2151,4 +2151,32 @@ name: foobar expect(code, contains('bool operator ==(Object other) {')); expect(code, contains('int get hashCode =>')); }); + + test('data class toString', () { + final classDefinition = Class( + name: 'Foobar', + fields: [ + NamedType( + type: const TypeDeclaration(baseName: 'int', isNullable: true), + name: 'field1', + ), + ], + ); + final root = Root( + apis: [], + classes: [classDefinition], + enums: [], + ); + final sink = StringBuffer(); + const generator = DartGenerator(); + generator.generate( + const InternalDartOptions(ignoreLints: false), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final code = sink.toString(); + expect(code, contains('String toString() {')); + expect(code, contains(r"return 'Foobar(field1: $field1)';")); + }); } diff --git a/packages/pigeon/test/gobject_generator_test.dart b/packages/pigeon/test/gobject_generator_test.dart index 8f44885a4617..1cb5c94728e3 100644 --- a/packages/pigeon/test/gobject_generator_test.dart +++ b/packages/pigeon/test/gobject_generator_test.dart @@ -1081,4 +1081,40 @@ void main() { expect(code, contains('guint test_package_input_hash(')); } }); + + test('data classes handle to_string', () { + final inputClass = Class( + name: 'Input', + fields: [ + NamedType( + type: const TypeDeclaration(baseName: 'String', isNullable: true), + name: 'input', + ), + ], + ); + final root = Root( + apis: [], + classes: [inputClass], + enums: [], + ); + final sink = StringBuffer(); + const generator = GObjectGenerator(); + final generatorOptions = OutputFileOptions( + fileType: FileType.source, + languageOptions: const InternalGObjectOptions( + headerIncludePath: '', + gobjectHeaderOut: '', + gobjectSourceOut: '', + ), + ); + generator.generate( + generatorOptions, + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final code = sink.toString(); + expect(code, contains('gchar* test_package_input_to_string(')); + expect(code, contains('g_string_new("Input(");')); + }); } diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart index a5f0708abf58..0ca4fed593ca 100644 --- a/packages/pigeon/test/java_generator_test.dart +++ b/packages/pigeon/test/java_generator_test.dart @@ -1920,4 +1920,33 @@ void main() { expect(code, contains('public boolean equals(Object o) {')); expect(code, contains('public int hashCode() {')); }); + + test('data class toString', () { + final classDefinition = Class( + name: 'Foobar', + fields: [ + NamedType( + type: const TypeDeclaration(baseName: 'int', isNullable: true), + name: 'field1', + ), + ], + ); + final root = Root( + apis: [], + classes: [classDefinition], + enums: [], + ); + final sink = StringBuffer(); + const javaOptions = InternalJavaOptions(className: 'Messages', javaOut: ''); + const generator = JavaGenerator(); + generator.generate( + javaOptions, + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final code = sink.toString(); + expect(code, contains('public String toString() {')); + expect(code, contains('return "Foobar{" + "field1=" + field1 + "}";')); + }); } diff --git a/packages/pigeon/test/kotlin_generator_test.dart b/packages/pigeon/test/kotlin_generator_test.dart index fe9600e81bc1..278ad250069b 100644 --- a/packages/pigeon/test/kotlin_generator_test.dart +++ b/packages/pigeon/test/kotlin_generator_test.dart @@ -2171,4 +2171,66 @@ void main() { expect(code, contains('override fun equals(other: Any?): Boolean {')); expect(code, contains('override fun hashCode(): Int {')); }); + + test('data class toString', () { + final classDefinition = Class( + name: 'Foobar', + fields: [ + NamedType( + type: const TypeDeclaration(baseName: 'int', isNullable: true), + name: 'field1', + ), + ], + ); + final root = Root( + apis: [], + classes: [classDefinition], + enums: [], + ); + final sink = StringBuffer(); + const kotlinOptions = InternalKotlinOptions(kotlinOut: ''); + const generator = KotlinGenerator(); + generator.generate( + kotlinOptions, + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final code = sink.toString(); + expect(code, contains('override fun toString(): String {')); + expect(code, contains(r'return "Foobar(field1=$field1)"')); + }); + + test('data class toString multi-field', () { + final classDefinition = Class( + name: 'Foobar', + fields: [ + NamedType( + type: const TypeDeclaration(baseName: 'int', isNullable: true), + name: 'field1', + ), + NamedType( + type: const TypeDeclaration(baseName: 'String', isNullable: true), + name: 'field2', + ), + ], + ); + final root = Root( + apis: [], + classes: [classDefinition], + enums: [], + ); + final sink = StringBuffer(); + const kotlinOptions = InternalKotlinOptions(kotlinOut: ''); + const generator = KotlinGenerator(); + generator.generate( + kotlinOptions, + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final code = sink.toString(); + expect(code, contains('override fun toString(): String {')); + expect(code, contains(r'return "Foobar(field1=$field1, field2=$field2)"')); + }); } diff --git a/packages/pigeon/test/objc_generator_test.dart b/packages/pigeon/test/objc_generator_test.dart index fb18833f77bc..09ed49236f21 100644 --- a/packages/pigeon/test/objc_generator_test.dart +++ b/packages/pigeon/test/objc_generator_test.dart @@ -4099,4 +4099,75 @@ void main() { expect(code, contains('- (NSUInteger)hash {')); } }); + + test('data class description', () { + final root = Root( + apis: [], + classes: [ + Class( + name: 'Foo', + fields: [ + NamedType( + type: const TypeDeclaration(baseName: 'int', isNullable: false), + name: 'bar', + ), + ], + ), + ], + enums: [], + ); + final sink = StringBuffer(); + const generator = ObjcGenerator(); + final generatorOptions = OutputFileOptions( + fileType: FileType.source, + languageOptions: const InternalObjcOptions( + prefix: 'ABC', + objcHeaderOut: '', + objcSourceOut: '', + headerIncludePath: '', + ), + ); + generator.generate( + generatorOptions, + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final code = sink.toString(); + expect(code, contains('- (NSString *)description {')); + expect( + code, + contains( + 'return [NSString stringWithFormat:@"ABCFoo(bar: %ld)", (long)self.bar];', + ), + ); + }); + + test('data class description empty', () { + final root = Root( + apis: [], + classes: [Class(name: 'Foo', fields: [])], + enums: [], + ); + final sink = StringBuffer(); + const generator = ObjcGenerator(); + final generatorOptions = OutputFileOptions( + fileType: FileType.source, + languageOptions: const InternalObjcOptions( + prefix: 'ABC', + objcHeaderOut: '', + objcSourceOut: '', + headerIncludePath: '', + ), + ); + generator.generate( + generatorOptions, + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final code = sink.toString(); + expect(code, contains('- (NSString *)description {')); + expect(code, contains('return [NSString stringWithFormat:@"ABCFoo()"];')); + }); } diff --git a/packages/pigeon/test/pigeon_lib_test.dart b/packages/pigeon/test/pigeon_lib_test.dart index 7b2d3b78a1c7..2d2922901d6b 100644 --- a/packages/pigeon/test/pigeon_lib_test.dart +++ b/packages/pigeon/test/pigeon_lib_test.dart @@ -41,7 +41,7 @@ class _ValidatorGeneratorAdapter implements GeneratorAdapter { void main() { /// Creates a temporary file named [filename] then calls [callback] with a - /// [File] representing that temporary directory. The file will be deleted + /// [File] representing that temporary directory. The file will be deleted /// after the [callback] is executed. void withTempFile(String filename, void Function(File) callback) { final Directory dir = Directory.systemTemp.createTempSync(); @@ -1888,5 +1888,32 @@ abstract class events { contains('Sealed class: "DataClass" must not contain fields.'), ); }); + + test('swift description field error', () async { + final completer = Completer(); + const code = ''' +class Foo { + String? description; +} + +@HostApi() +abstract class Api { + void method(Foo foo); +} +'''; + withTempFile('foo.dart', (File input) async { + input.writeAsStringSync(code); + final int result = await Pigeon.runWithOptions( + PigeonOptions( + input: input.path, + swiftOut: 'Foo.swift', + dartOut: 'foo.dart', + ), + ); + expect(result, isNot(0)); + completer.complete(); + }); + await completer.future; + }); }); } diff --git a/packages/pigeon/test/swift_generator_test.dart b/packages/pigeon/test/swift_generator_test.dart index fa567e2b02c8..101fbb4a2688 100644 --- a/packages/pigeon/test/swift_generator_test.dart +++ b/packages/pigeon/test/swift_generator_test.dart @@ -1853,4 +1853,37 @@ void main() { ); expect(code, contains('func hash(into hasher: inout Hasher) {')); }); + + test('data class toString', () { + final classDefinition = Class( + name: 'Foobar', + fields: [ + NamedType( + type: const TypeDeclaration(baseName: 'int', isNullable: true), + name: 'field1', + ), + ], + ); + final root = Root( + apis: [], + classes: [classDefinition], + enums: [], + ); + final sink = StringBuffer(); + const swiftOptions = InternalSwiftOptions(swiftOut: ''); + const generator = SwiftGenerator(); + generator.generate( + swiftOptions, + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final code = sink.toString(); + expect(code, contains(': Hashable, CustomStringConvertible')); + expect(code, contains('public var description: String {')); + expect( + code, + contains(r'return "Foobar(field1: \(String(describing: field1)))"'), + ); + }); }