Skip to content

Commit c9c0004

Browse files
[pigeon] Kotlin implementation for ProxyApis (#6371)
Kotlin portion of flutter/flutter#134777
1 parent d472256 commit c9c0004

File tree

26 files changed

+8733
-189
lines changed

26 files changed

+8733
-189
lines changed

packages/pigeon/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 22.2.0
2+
3+
* [kotlin] Adds implementation for `@ProxyApi`.
4+
15
## 22.1.0
26

37
* Allows generation of classes that aren't referenced in an API.

packages/pigeon/example/app/android/app/src/main/kotlin/dev/flutter/pigeon_example_app/Messages.g.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ data class MessageData(
8484
}
8585
}
8686

87-
private object MessagesPigeonCodec : StandardMessageCodec() {
87+
private open class MessagesPigeonCodec : StandardMessageCodec() {
8888
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
8989
return when (type) {
9090
129.toByte() -> {
@@ -122,7 +122,7 @@ interface ExampleHostApi {
122122

123123
companion object {
124124
/** The codec used by ExampleHostApi. */
125-
val codec: MessageCodec<Any?> by lazy { MessagesPigeonCodec }
125+
val codec: MessageCodec<Any?> by lazy { MessagesPigeonCodec() }
126126
/** Sets up an instance of `ExampleHostApi` to handle messages through the `binaryMessenger`. */
127127
@JvmOverloads
128128
fun setUp(
@@ -209,7 +209,7 @@ class MessageFlutterApi(
209209
) {
210210
companion object {
211211
/** The codec used by MessageFlutterApi. */
212-
val codec: MessageCodec<Any?> by lazy { MessagesPigeonCodec }
212+
val codec: MessageCodec<Any?> by lazy { MessagesPigeonCodec() }
213213
}
214214

215215
fun flutterMethod(aStringArg: String?, callback: (Result<String>) -> Unit) {

packages/pigeon/lib/ast.dart

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
import 'package:collection/collection.dart' show ListEquality;
66
import 'package:meta/meta.dart';
7+
78
import 'generator_tools.dart';
9+
import 'kotlin_generator.dart' show KotlinProxyApiOptions;
810
import 'pigeon_lib.dart';
911

1012
typedef _ListEquals = bool Function(List<Object?>, List<Object?>);
@@ -140,6 +142,7 @@ class AstProxyApi extends Api {
140142
required this.fields,
141143
this.superClass,
142144
this.interfaces = const <TypeDeclaration>{},
145+
this.kotlinOptions,
143146
});
144147

145148
/// List of constructors inside the API.
@@ -154,6 +157,10 @@ class AstProxyApi extends Api {
154157
/// Name of the classes this class considers to be implemented.
155158
Set<TypeDeclaration> interfaces;
156159

160+
/// Options that control how Kotlin code will be generated for a specific
161+
/// ProxyApi.
162+
final KotlinProxyApiOptions? kotlinOptions;
163+
157164
/// Methods implemented in the host platform language.
158165
Iterable<Method> get hostMethods => methods.where(
159166
(Method method) => method.location == ApiLocation.host,
@@ -253,7 +260,7 @@ class AstProxyApi extends Api {
253260
}
254261
}
255262

256-
/// Whether the api has a method that callbacks to Dart to add a new instance
263+
/// Whether the API has a method that callbacks to Dart to add a new instance
257264
/// to the InstanceManager.
258265
///
259266
/// This is possible as long as no callback methods are required to
@@ -265,6 +272,21 @@ class AstProxyApi extends Api {
265272
.every((Method method) => !method.isRequired);
266273
}
267274

275+
/// Whether the API has any message calls from Dart to host.
276+
bool hasAnyHostMessageCalls() =>
277+
constructors.isNotEmpty ||
278+
attachedFields.isNotEmpty ||
279+
hostMethods.isNotEmpty;
280+
281+
/// Whether the API has any message calls from host to Dart.
282+
bool hasAnyFlutterMessageCalls() =>
283+
hasCallbackConstructor() || flutterMethods.isNotEmpty;
284+
285+
/// Whether the host proxy API class will have methods that need to be
286+
/// implemented.
287+
bool hasMethodsRequiringImplementation() =>
288+
hasAnyHostMessageCalls() || unattachedFields.isNotEmpty;
289+
268290
// Recursively search for all the interfaces apis from a list of names of
269291
// interfaces.
270292
//

packages/pigeon/lib/dart/templates.dart

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@
44

55
import '../generator_tools.dart';
66

7+
/// Name for the generated InstanceManager for ProxyApis.
8+
///
9+
/// This lowers the chances of variable name collisions with user defined
10+
/// parameters.
11+
const String dartInstanceManagerClassName =
12+
'${proxyApiClassNamePrefix}InstanceManager';
13+
14+
/// Name for the generated InstanceManager API for ProxyApis.
15+
///
16+
/// This lowers the chances of variable name collisions with user defined
17+
/// parameters.
18+
const String dartInstanceManagerApiClassName =
19+
'_${classNamePrefix}InstanceManagerApi';
20+
721
/// Creates the `InstanceManager` with the passed string values.
822
String instanceManagerTemplate({
923
required Iterable<String> allProxyApiNames,
@@ -30,9 +44,9 @@ String instanceManagerTemplate({
3044
/// is added as a weak reference with the same identifier. This prevents a
3145
/// scenario where the weak referenced instance was released and then later
3246
/// returned by the host platform.
33-
class $instanceManagerClassName {
34-
/// Constructs a [$instanceManagerClassName].
35-
$instanceManagerClassName({required void Function(int) onWeakReferenceRemoved}) {
47+
class $dartInstanceManagerClassName {
48+
/// Constructs a [$dartInstanceManagerClassName].
49+
$dartInstanceManagerClassName({required void Function(int) onWeakReferenceRemoved}) {
3650
this.onWeakReferenceRemoved = (int identifier) {
3751
_weakInstances.remove(identifier);
3852
onWeakReferenceRemoved(identifier);
@@ -46,12 +60,12 @@ class $instanceManagerClassName {
4660
// 0 <= n < 2^16.
4761
static const int _maxDartCreatedIdentifier = 65536;
4862
49-
/// The default [$instanceManagerClassName] used by ProxyApis.
63+
/// The default [$dartInstanceManagerClassName] used by ProxyApis.
5064
///
5165
/// On creation, this manager makes a call to clear the native
5266
/// InstanceManager. This is to prevent identifier conflicts after a host
5367
/// restart.
54-
static final $instanceManagerClassName instance = _initInstance();
68+
static final $dartInstanceManagerClassName instance = _initInstance();
5569
5670
// Expando is used because it doesn't prevent its keys from becoming
5771
// inaccessible. This allows the manager to efficiently retrieve an identifier
@@ -72,17 +86,17 @@ class $instanceManagerClassName {
7286
/// or becomes inaccessible.
7387
late final void Function(int) onWeakReferenceRemoved;
7488
75-
static $instanceManagerClassName _initInstance() {
89+
static $dartInstanceManagerClassName _initInstance() {
7690
WidgetsFlutterBinding.ensureInitialized();
77-
final _${instanceManagerClassName}Api api = _${instanceManagerClassName}Api();
78-
// Clears the native `$instanceManagerClassName` on the initial use of the Dart one.
91+
final $dartInstanceManagerApiClassName api = $dartInstanceManagerApiClassName();
92+
// Clears the native `$dartInstanceManagerClassName` on the initial use of the Dart one.
7993
api.clear();
80-
final $instanceManagerClassName instanceManager = $instanceManagerClassName(
94+
final $dartInstanceManagerClassName instanceManager = $dartInstanceManagerClassName(
8195
onWeakReferenceRemoved: (int identifier) {
8296
api.removeStrongReference(identifier);
8397
},
8498
);
85-
_${instanceManagerClassName}Api.setUpMessageHandlers(instanceManager: instanceManager);
99+
$dartInstanceManagerApiClassName.setUpMessageHandlers(instanceManager: instanceManager);
86100
${apiHandlerSetUps.join('\n\t\t')}
87101
return instanceManager;
88102
}
@@ -229,9 +243,9 @@ abstract class $proxyApiBaseClassName {
229243
/// Construct a [$proxyApiBaseClassName].
230244
$proxyApiBaseClassName({
231245
this.$_proxyApiBaseClassMessengerVarName,
232-
$instanceManagerClassName? $_proxyApiBaseClassInstanceManagerVarName,
246+
$dartInstanceManagerClassName? $_proxyApiBaseClassInstanceManagerVarName,
233247
}) : $_proxyApiBaseClassInstanceManagerVarName =
234-
$_proxyApiBaseClassInstanceManagerVarName ?? $instanceManagerClassName.instance;
248+
$_proxyApiBaseClassInstanceManagerVarName ?? $dartInstanceManagerClassName.instance;
235249
236250
/// Sends and receives binary data across the Flutter platform barrier.
237251
///
@@ -242,12 +256,12 @@ abstract class $proxyApiBaseClassName {
242256
243257
/// Maintains instances stored to communicate with native language objects.
244258
@protected
245-
final $instanceManagerClassName $_proxyApiBaseClassInstanceManagerVarName;
259+
final $dartInstanceManagerClassName $_proxyApiBaseClassInstanceManagerVarName;
246260
247261
/// Instantiates and returns a functionally identical object to oneself.
248262
///
249263
/// Outside of tests, this method should only ever be called by
250-
/// [$instanceManagerClassName].
264+
/// [$dartInstanceManagerClassName].
251265
///
252266
/// Subclasses should always override their parent's implementation of this
253267
/// method.
@@ -264,11 +278,11 @@ abstract class $proxyApiBaseClassName {
264278
const String proxyApiBaseCodec = '''
265279
class $_proxyApiCodecName extends _PigeonCodec {
266280
const $_proxyApiCodecName(this.instanceManager);
267-
final $instanceManagerClassName instanceManager;
281+
final $dartInstanceManagerClassName instanceManager;
268282
@override
269283
void writeValue(WriteBuffer buffer, Object? value) {
270284
if (value is $proxyApiBaseClassName) {
271-
buffer.putUint8(128);
285+
buffer.putUint8($proxyApiCodecInstanceManagerKey);
272286
writeValue(buffer, instanceManager.getIdentifier(value));
273287
} else {
274288
super.writeValue(buffer, value);
@@ -277,7 +291,7 @@ class $_proxyApiCodecName extends _PigeonCodec {
277291
@override
278292
Object? readValueOfType(int type, ReadBuffer buffer) {
279293
switch (type) {
280-
case 128:
294+
case $proxyApiCodecInstanceManagerKey:
281295
return instanceManager
282296
.getInstanceWithWeakReference(readValue(buffer)! as int);
283297
default:

0 commit comments

Comments
 (0)