Skip to content

[pigeon] Adds ProxyApi code generation for Dart #5544

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 89 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
169cd76
update ast
bparrishMines Nov 30, 2023
9d4f82c
update pigeon_lib
bparrishMines Nov 30, 2023
b5d7fcd
fix unit tests
bparrishMines Dec 3, 2023
740a395
add impls for instancemanager and instancemanager api
bparrishMines Dec 3, 2023
304e1a0
add write proxy api impl
bparrishMines Dec 4, 2023
968715d
fix comments
bparrishMines Dec 4, 2023
4628c70
update constructors
bparrishMines Dec 4, 2023
4f643eb
add field impls
bparrishMines Dec 4, 2023
8a87f7f
fix methods
bparrishMines Dec 5, 2023
eaef031
Merge branch 'main' of github.com:flutter/packages into pigeon_wrappe…
bparrishMines Dec 5, 2023
bb052eb
add helper methods to astproxyapi
bparrishMines Dec 5, 2023
c4b7c26
Merge branch 'main' of github.com:flutter/packages into pigeon_wrappe…
bparrishMines Dec 5, 2023
e73f881
start of something
bparrishMines Dec 6, 2023
3898970
use dart extends/implements
bparrishMines Dec 6, 2023
e216947
validate ast work
bparrishMines Dec 6, 2023
2604466
verify constructor parameters and that all classes are proxyapis
bparrishMines Dec 7, 2023
8fdcca4
inheritance chaecker validator
bparrishMines Dec 8, 2023
5863c68
fix tests
bparrishMines Dec 8, 2023
b7ec6ca
undo making validate async
bparrishMines Dec 8, 2023
be1f9fb
finish proxyapi validation (maybe)
bparrishMines Dec 8, 2023
abf11b6
undo pubspec change
bparrishMines Dec 8, 2023
f31df3b
Merge branch 'main' of github.com:flutter/packages into pigeon_wrappe…
bparrishMines Dec 8, 2023
8a35b5e
version bump
bparrishMines Dec 8, 2023
9a79ea9
fix lints
bparrishMines Dec 8, 2023
245a322
remove unneccessary cast
bparrishMines Dec 8, 2023
4a5c1c7
formatting
bparrishMines Dec 8, 2023
0d603ae
Merge branch 'main' of github.com:flutter/packages into pigeon_wrappe…
bparrishMines Dec 12, 2023
abefd56
fix kotlin tests
bparrishMines Dec 12, 2023
54e4102
fix and add core tests
bparrishMines Dec 13, 2023
00aafe6
ensure constructor parameter names dont overlap field or flutter meth…
bparrishMines Dec 13, 2023
c5b3790
some unit tests
bparrishMines Dec 14, 2023
fb20cd9
more tests
bparrishMines Dec 14, 2023
3aa0fe9
test fields
bparrishMines Dec 14, 2023
147604a
core tests inheritance and error for double super class naming
bparrishMines Dec 14, 2023
d40f976
add code_builder and dart_style to allowed deps
bparrishMines Dec 14, 2023
5286b7a
Merge branch 'main' of github.com:flutter/packages into pigeon_wrappe…
bparrishMines Dec 14, 2023
6f887e2
add todo
bparrishMines Dec 14, 2023
cc79e77
Merge branch 'main' of github.com:flutter/packages into pigeon_wrappe…
bparrishMines Dec 15, 2023
b129a51
use collection for functional methods
bparrishMines Dec 15, 2023
9f52a74
formatting and some updates
bparrishMines Dec 15, 2023
e947f31
improve PR looks and commented out code
bparrishMines Dec 15, 2023
4463b09
exclude astproxyapi
bparrishMines Dec 15, 2023
f0ca949
regenerate code
bparrishMines Dec 15, 2023
6a5226b
fix last cpp prob
bparrishMines Dec 15, 2023
8e26c08
test generator_tools additions
bparrishMines Dec 15, 2023
5b725c3
Merge branch 'main' of github.com:flutter/packages into pigeon_wrappe…
bparrishMines Dec 15, 2023
fcdc09f
change to avoid using $ in code gen
bparrishMines Dec 19, 2023
8572dba
add attached fields to core tests and make instance avoid collisions
bparrishMines Dec 19, 2023
fd144c5
fix lists and maps with proxy apis
bparrishMines Dec 19, 2023
7c49057
test dart instance manager
bparrishMines Dec 19, 2023
f8f460a
use prefix for attached fields
bparrishMines Dec 19, 2023
2087c10
Merge branch 'main' of github.com:flutter/packages into pigeon_wrappe…
bparrishMines Dec 19, 2023
66af298
validate naming and change private codec instance name
bparrishMines Dec 20, 2023
5d4cc54
make a base codec and move attached fields to main class
bparrishMines Dec 20, 2023
382e456
Merge branch 'main' of github.com:flutter/packages into pigeon_wrappe…
bparrishMines Dec 20, 2023
eb72b38
fix unit test
bparrishMines Dec 20, 2023
50fc804
fix version error
bparrishMines Dec 21, 2023
fbe7c5b
fix test and make instance avoid collisions
bparrishMines Dec 21, 2023
df2ecac
add documentation
bparrishMines Dec 21, 2023
e157568
create a base class for dart
bparrishMines Dec 21, 2023
de987e0
fix tests and lint
bparrishMines Dec 21, 2023
30abd65
replace copyable with a base class
bparrishMines Dec 22, 2023
c4e0af3
fix unit tests
bparrishMines Dec 22, 2023
93bafbd
Merge branch 'main' of github.com:flutter/packages into pigeon_wrappe…
bparrishMines Dec 22, 2023
cd71bf0
link to immutable
bparrishMines Dec 22, 2023
b28e27b
fix instance manager tests
bparrishMines Dec 22, 2023
096d65c
change nonattached to unattached
bparrishMines Dec 26, 2023
4601ce2
change flutter method constructor to newInstance
bparrishMines Dec 26, 2023
fff1c9f
Merge branch 'main' of github.com:flutter/packages into pigeon_wrappe…
bparrishMines Dec 26, 2023
235464f
add passing proxy api to core test class
bparrishMines Dec 26, 2023
66161fc
verify nonnull attached fields and add docs to callback methods
bparrishMines Dec 26, 2023
1a8b464
make all test callback methods nullable
bparrishMines Dec 26, 2023
5fe2e26
update test pigeon and docs
bparrishMines Dec 28, 2023
c0d96c0
add constructor to proxyapisuperclass
bparrishMines Dec 28, 2023
ffbe73b
update test pigeon
bparrishMines Dec 28, 2023
c4f589e
fix formatting some
bparrishMines Dec 28, 2023
036d12c
Merge branch 'main' of github.com:flutter/packages into pigeon_wrappe…
bparrishMines Jan 3, 2024
f5c0ee0
Merge branch 'main' of github.com:flutter/packages into pigeon_wrappe…
bparrishMines Jan 4, 2024
2e47909
Merge branch 'main' of github.com:flutter/packages into pigeon_wrappe…
bparrishMines Jan 5, 2024
716cd79
dont have repeating code start
bparrishMines Jan 6, 2024
1630fa6
fix up host methods
bparrishMines Jan 6, 2024
6fb56be
update fields
bparrishMines Jan 6, 2024
139e3df
reuse flutter method call code
bparrishMines Jan 6, 2024
ec6b94f
gross fix for whether to null out handlers
bparrishMines Jan 7, 2024
89daaea
update setUpMessageHandler with same thing from the commit above
bparrishMines Jan 7, 2024
79f9afa
fix unit tests
bparrishMines Jan 7, 2024
cd58d50
use param
bparrishMines Jan 7, 2024
f1d4f7a
Merge branch 'main' of github.com:flutter/packages into pigeon_wrappe…
bparrishMines Jan 7, 2024
67f2818
Merge branch 'main' of github.com:flutter/packages into pigeon_wrappe…
bparrishMines Jan 10, 2024
File filter

Filter by extension

Filter by extension


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

* Adds support for `ProxyApi` generation only for Dart.

## 16.0.0

* [java] Adds `VoidResult` type for `Void` returns.
Expand Down
2 changes: 1 addition & 1 deletion packages/pigeon/example/app/lib/src/messages.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// found in the LICENSE file.
// Autogenerated from Pigeon, do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers, camel_case_types

import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
Expand Down
213 changes: 201 additions & 12 deletions packages/pigeon/lib/ast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ class Method extends Node {
required this.name,
required this.returnType,
required this.parameters,
required this.location,
this.required = false,
this.isAsynchronous = false,
this.isStatic = false,
this.offset,
this.objcSelector = '',
this.swiftFunction = '',
Expand Down Expand Up @@ -68,6 +71,18 @@ class Method extends Node {
/// For example: [" List of documentation comments, separated by line.", ...]
List<String> documentationComments;

/// Where the implementation of this method is located, host or Flutter.
ApiLocation location;

/// Whether this method is required to be implemented.
///
/// This flag is typically used to determine whether a callback method for
/// a `ProxyApi` is nullable or not.
bool required;

/// Whether this is a static method of a ProxyApi.
bool isStatic;

@override
String toString() {
final String objcSelectorStr =
Expand All @@ -78,29 +93,185 @@ class Method extends Node {
}
}

/// Represents a collection of [Method]s that are hosted on a given [location].
class Api extends Node {
/// Represents a collection of [Method]s that are implemented on the platform
/// side.
class AstHostApi extends Api {
/// Parametric constructor for [AstHostApi].
AstHostApi({
required super.name,
required super.methods,
super.documentationComments = const <String>[],
this.dartHostTestHandler,
});

/// The name of the Dart test interface to generate to help with testing.
String? dartHostTestHandler;

@override
String toString() {
return '(HostApi name:$name methods:$methods documentationComments:$documentationComments dartHostTestHandler:$dartHostTestHandler)';
}
}

/// Represents a collection of [Method]s that are hosted on the Flutter side.
class AstFlutterApi extends Api {
/// Parametric constructor for [AstFlutterApi].
AstFlutterApi({
required super.name,
required super.methods,
super.documentationComments = const <String>[],
});

@override
String toString() {
return '(FlutterApi name:$name methods:$methods documentationComments:$documentationComments)';
}
}

/// Represents an API that wraps a native class.
class AstProxyApi extends Api {
/// Parametric constructor for [AstProxyApi].
AstProxyApi({
required super.name,
required super.methods,
super.documentationComments = const <String>[],
required this.constructors,
required this.fields,
this.superClassName,
this.interfacesNames = const <String>{},
});

/// List of constructors inside the API.
final List<Constructor> constructors;

/// List of fields inside the API.
List<Field> fields;

/// Name of the class this class considers the super class.
final String? superClassName;

/// Name of the classes this class considers to be implemented.
final Set<String> interfacesNames;

/// Methods implemented in the host platform language.
Iterable<Method> get hostMethods => methods.where(
(Method method) => method.location == ApiLocation.host,
);

/// Methods implemented in Flutter.
Iterable<Method> get flutterMethods => methods.where(
(Method method) => method.location == ApiLocation.flutter,
);

/// All fields that are attached.
///
/// See [attached].
Iterable<Field> get attachedFields => fields.where(
(Field field) => field.isAttached,
);

/// All fields that are not attached.
///
/// See [attached].
Iterable<Field> get unattachedFields => fields.where(
(Field field) => !field.isAttached,
);

@override
String toString() {
return '(ProxyApi name:$name methods:$methods documentationComments:$documentationComments superClassName:$superClassName interfacesNames:$interfacesNames)';
}
}

/// Represents a constructor for an API.
class Constructor extends Node {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does a constructor have to be a special type? It seems like all the properties are standard method properties.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is similar to our discussion about parameter vs field. They overlap but some of the parameters don't apply (e.g. static/isAsynchronous). However, if I consider the Method as the message call and not the AST class member, then I suppose they are essentially the same thing. I still need to distinguish the difference between Constructors for the Dart code generation, so I think I will keep the class and have it extend Method.

/// Parametric constructor for [Constructor].
Constructor({
required this.name,
required this.parameters,
this.offset,
this.swiftFunction = '',
this.documentationComments = const <String>[],
});

/// The name of the method.
String name;

/// The parameters passed into the [Constructor].
List<Parameter> parameters;

/// The offset in the source file where the field appears.
int? offset;

/// An override for the generated swift function signature (ex. "divideNumber(_:by:)").
String swiftFunction;

/// List of documentation comments, separated by line.
///
/// Lines should not include the comment marker itself, but should include any
/// leading whitespace, so that any indentation in the original comment is preserved.
/// For example: [" List of documentation comments, separated by line.", ...]
List<String> documentationComments;

@override
String toString() {
final String swiftFunctionStr =
swiftFunction.isEmpty ? '' : ' swiftFunction:$swiftFunction';
return '(Constructor name:$name parameters:$parameters $swiftFunctionStr documentationComments:$documentationComments)';
}
}

/// Represents a field of an API.
class Field extends NamedType {
/// Constructor for [Field].
Field({
required super.name,
required super.type,
super.offset,
super.documentationComments,
this.isAttached = false,
this.isStatic = false,
}) : assert(!isStatic || isAttached);

/// Whether this is an attached field for a [AstProxyApi].
///
/// See [attached].
final bool isAttached;

/// Whether this is a static field of a [AstProxyApi].
///
/// A static field must also be attached. See [attached].
final bool isStatic;

/// Returns a copy of [Parameter] instance with new attached [TypeDeclaration].
@override
Field copyWithType(TypeDeclaration type) {
return Field(
name: name,
type: type,
offset: offset,
documentationComments: documentationComments,
isAttached: isAttached,
isStatic: isStatic,
);
}
}

/// Represents a collection of [Method]s.
sealed class Api extends Node {
/// Parametric constructor for [Api].
Api({
required this.name,
required this.location,
required this.methods,
this.dartHostTestHandler,
this.documentationComments = const <String>[],
});

/// The name of the API.
String name;

/// Where the API's implementation is located, host or Flutter.
ApiLocation location;

/// List of methods inside the API.
List<Method> methods;

/// The name of the Dart test interface to generate to help with testing.
String? dartHostTestHandler;

/// List of documentation comments, separated by line.
///
/// Lines should not include the comment marker itself, but should include any
Expand All @@ -110,7 +281,7 @@ class Api extends Node {

@override
String toString() {
return '(Api name:$name location:$location methods:$methods documentationComments:$documentationComments)';
return '(Api name:$name methods:$methods documentationComments:$documentationComments)';
}
}

Expand All @@ -123,6 +294,7 @@ class TypeDeclaration {
required this.isNullable,
this.associatedEnum,
this.associatedClass,
this.associatedProxyApi,
this.typeArguments = const <TypeDeclaration>[],
});

Expand All @@ -132,6 +304,7 @@ class TypeDeclaration {
isNullable = false,
associatedEnum = null,
associatedClass = null,
associatedProxyApi = null,
typeArguments = const <TypeDeclaration>[];

/// The base name of the [TypeDeclaration] (ex 'Foo' to 'Foo<Bar>?').
Expand All @@ -158,6 +331,12 @@ class TypeDeclaration {
/// Associated [Class], if any.
final Class? associatedClass;

/// Associated [AstProxyApi], if any.
final AstProxyApi? associatedProxyApi;

/// Whether the [TypeDeclaration] has an [associatedProxyApi].
bool get isProxyApi => associatedProxyApi != null;

@override
int get hashCode {
// This has to be implemented because TypeDeclaration is used as a Key to a
Expand Down Expand Up @@ -207,11 +386,21 @@ class TypeDeclaration {
);
}

/// Returns duplicated `TypeDeclaration` with attached `associatedProxyApi` value.
TypeDeclaration copyWithProxyApi(AstProxyApi proxyApiDefinition) {
return TypeDeclaration(
baseName: baseName,
isNullable: isNullable,
associatedProxyApi: proxyApiDefinition,
typeArguments: typeArguments,
);
}

@override
String toString() {
final String typeArgumentsStr =
typeArguments.isEmpty ? '' : 'typeArguments:$typeArguments';
return '(TypeDeclaration baseName:$baseName isNullable:$isNullable$typeArgumentsStr isEnum:$isEnum isClass:$isClass)';
return '(TypeDeclaration baseName:$baseName isNullable:$isNullable$typeArgumentsStr isEnum:$isEnum isClass:$isClass isProxyApi:$isProxyApi)';
}
}

Expand Down
Loading