From a13b4ef628f634bbbd4a5dcfb96f16a6500578a7 Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Thu, 2 Jan 2025 10:50:24 -0800 Subject: [PATCH] [pigeon] Discuss stability in README (#8366) Updates the README to discuss two anti-patterns that clients should be aware of: - Why Pigeon-generated code should not be used in public APIs. - Why Pigeon-generated code should not be split across packages. --- packages/pigeon/CHANGELOG.md | 4 ++ packages/pigeon/README.md | 50 ++++++++++++++++++------ packages/pigeon/lib/generator_tools.dart | 2 +- packages/pigeon/pubspec.yaml | 2 +- 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/packages/pigeon/CHANGELOG.md b/packages/pigeon/CHANGELOG.md index 71b33fa74417..676756512949 100644 --- a/packages/pigeon/CHANGELOG.md +++ b/packages/pigeon/CHANGELOG.md @@ -1,3 +1,7 @@ +## 22.7.2 + +* Updates README to discuss best practices for using Pigeon-generated code. + ## 22.7.1 * [swift] Adds support for platform checks of imports of ProxyApis. diff --git a/packages/pigeon/README.md b/packages/pigeon/README.md index 39df85d65f41..0e5b91c25128 100644 --- a/packages/pigeon/README.md +++ b/packages/pigeon/README.md @@ -21,16 +21,16 @@ Currently pigeon supports generating: ### Supported Datatypes -Pigeon uses the `StandardMessageCodec` so it supports +Pigeon uses the `StandardMessageCodec` so it supports [any datatype platform channels support](https://flutter.dev/to/platform-channels-codec). -Custom classes, nested datatypes, and enums are also supported. +Custom classes, nested datatypes, and enums are also supported. Basic inheritance with empty `sealed` parent classes is allowed only in the Swift, Kotlin, and Dart generators. Nullable enums in Objective-C generated code will be wrapped in a class to allow for nullability. -By default, custom classes in Swift are defined as structs. +By default, custom classes in Swift are defined as structs. Structs don't support some features - recursive data, or Objective-C interop. Use the @SwiftClass annotation when defining the class to generate the data as a Swift class instead. @@ -41,7 +41,7 @@ While all calls across platform channel APIs (such as pigeon methods) are asynch pigeon methods can be written on the native side as synchronous methods, to make it simpler to always reply exactly once. -If asynchronous methods are needed, the `@async` annotation can be used. This will require +If asynchronous methods are needed, the `@async` annotation can be used. This will require results or errors to be returned via a provided callback. [Example](./example/README.md#HostApi_Example). ### Error Handling @@ -53,7 +53,7 @@ All Host API exceptions are translated into Flutter `PlatformException`. * For asynchronous methods, there is no default exception handling; errors should be returned via the provided callback. -To pass custom details into `PlatformException` for error handling, +To pass custom details into `PlatformException` for error handling, use `FlutterError` in your Host API. [Example](./example/README.md#HostApi_Example). For swift, use `PigeonError` instead of `FlutterError` when throwing an error. See [Example#Swift](./example/README.md#Swift) for more details. @@ -79,8 +79,8 @@ the threading model for handling HostApi methods can be selected with the ### Multi-Instance Support -Host and Flutter APIs now support the ability to provide a unique message channel suffix string -to the api to allow for multiple instances to be created and operate in parallel. +Host and Flutter APIs now support the ability to provide a unique message channel suffix string +to the api to allow for multiple instances to be created and operate in parallel. ## Usage @@ -94,7 +94,7 @@ to the api to allow for multiple instances to be created and operate in parallel 1) Implement the host-language code and add it to your build (see below). 1) Call the generated Dart methods. -### Rules for defining your communication interface +### Rules for defining your communication interface [Example](./example/README.md#HostApi_Example) 1) The file should contain no method or function definitions, only declarations. @@ -110,7 +110,7 @@ to the api to allow for multiple instances to be created and operate in parallel 1) Event channel methods should be wrapped in an `abstract class` with the metadata `@EventChannelApi`. 1) Event channel definitions should not include the `Stream` return type, just the type that is being streamed. 1) Objective-C and Swift have special naming conventions that can be utilized with the - `@ObjCSelector` and `@SwiftFunction` respectively. + `@ObjCSelector` and `@SwiftFunction` respectively. ### Flutter calling into iOS steps @@ -151,10 +151,38 @@ to the api to allow for multiple instances to be created and operate in parallel Pigeon also supports calling in the opposite direction. The steps are similar but reversed. For more information look at the annotation `@FlutterApi()` which -denotes APIs that live in Flutter but are invoked from the host platform. +denotes APIs that live in Flutter but are invoked from the host platform. [Example](./example/README.md#FlutterApi_Example). +## Stability of generated code + +Pigeon is intended to replace direct use of method channels in the internal +implementation of plugins and applications. Because the expected use of Pigeon +is as an internal implementation detail, its development strongly favors +improvements to generated code over consistency with previous generated code, +so breaking changes in generated code are common. + +As a result, using Pigeon-generated code in public APIs is +**strongy discouraged**, as doing so will likely create situations where you are +unable to update to a new version of Pigeon without causing breaking changes +for your clients. + +### Inter-version compatibility + +The generated message channel code used for Pigeon communication is an +internal implementation detail of Pigeon that is subject to change without +warning, and changes to the communication are *not* considered breaking changes. +Both sides of the communication (the Dart code and the host-language code) +must be generated with the **same version** of Pigeon. Using code generated with +different versions has undefined behavior, including potentially crashing the +application. + +This means that Pigeon-generated code **should not** be split across packages. +For example, putting the generated Dart code in a platform interface package +and the generated host-language code in a platform implementation package is +very likely to cause crashes for some plugin clients after updates. + ## Feedback -File an issue in [flutter/flutter](https://github.com/flutter/flutter) with +File an issue in [flutter/flutter](https://github.com/flutter/flutter) with "[pigeon]" at the start of the title. diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart index c23817ad6174..295d223fada0 100644 --- a/packages/pigeon/lib/generator_tools.dart +++ b/packages/pigeon/lib/generator_tools.dart @@ -14,7 +14,7 @@ import 'ast.dart'; /// The current version of pigeon. /// /// This must match the version in pubspec.yaml. -const String pigeonVersion = '22.7.1'; +const String pigeonVersion = '22.7.2'; /// Read all the content from [stdin] to a String. String readStdin() { diff --git a/packages/pigeon/pubspec.yaml b/packages/pigeon/pubspec.yaml index 6e5378a26242..a4334a271a16 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: 22.7.1 # This must match the version in lib/generator_tools.dart +version: 22.7.2 # This must match the version in lib/generator_tools.dart environment: sdk: ^3.4.0