Skip to content
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

[pigeon] Adds Dart implementation of ProxyApi #6043

Merged
merged 45 commits into from
Mar 19, 2024

Conversation

bparrishMines
Copy link
Contributor

@bparrishMines bparrishMines commented Feb 2, 2024

Part of flutter/flutter#134777

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

packages/pigeon/example/app/lib/src/messages.g.dart Outdated Show resolved Hide resolved
packages/pigeon/lib/dart_generator.dart Outdated Show resolved Hide resolved
}) {
const String codecName = '_${classNamePrefix}ProxyApiBaseCodec';

// Each api has a private codec instance used by every host method,
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: API

packages/pigeon/lib/dart_generator.dart Outdated Show resolved Hide resolved
.followedBy(flutterMethodsFromInterfaces)
.followedBy(api.flutterMethods),
)),
);
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems pretty nice. Definitely something to consider for the other Dart generation.

packages/pigeon/lib/dart_generator.dart Outdated Show resolved Hide resolved
packages/pigeon/pigeons/proxy_api_tests.dart Outdated Show resolved Hide resolved
ProxyApiSuperClass? nullableProxyApiParam,
);

late bool aBool;
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 everything need to be late in the interface definition?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

late is required since the field isn't added to the constructor. And it's not added to the constructor to differentiate it from constructor params: https://docs.google.com/document/d/1Sw6F8GbNiO_lvS2fFjXrRYk2Go5RNDHudDT6kIX6Sm0/edit?tab=t.0#heading=h.1amuvpa8b1ic

@stuartmorgan
Copy link
Contributor

(Mostly small comments; There are some big walls of text so I was skimming in the generator, but it looks like the overall structure here is pretty well factored.)

Copy link
Contributor

@tarrinneal tarrinneal left a comment

Choose a reason for hiding this comment

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

Seems like a lot of good stuff.

packages/pigeon/lib/dart/templates.dart Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you see these templates changing much in the future? I get a bit nervous thinking about adding logic into this later. Just based on doing that with previously written pigeon code.

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 wouldn't expect these to have many changes in the future. And if they do, it shouldn't be changes that require adding logic when generating them. This should at least be true for InstanceManager, InstanceManagerApi, and ProxyApiBaseClass. I expect all of these to always be basic templates.

However, ProxyApiBaseCodec could require logic later to solve some complex issues, but I don't have any plans for it yet.

packages/pigeon/lib/dart_generator.dart Outdated Show resolved Hide resolved
packages/pigeon/lib/dart_generator.dart Outdated Show resolved Hide resolved
packages/pigeon/example/app/lib/src/messages.g.dart Outdated Show resolved Hide resolved
Comment on lines 511 to 546
// A list of ProxyApis where each `extends` the API that follows it.
final List<AstProxyApi> superClassApisChain =
recursiveGetSuperClassApisChain(
api,
);

// All ProxyApis this API `implements` and all the interfaces those APIs
// `implements`.
final Set<AstProxyApi> apisOfInterfaces =
recursiveFindAllInterfaceApis(api);

// All methods inherited from interfaces and the interfaces of interfaces.
final List<Method> flutterMethodsFromInterfaces = <Method>[];
for (final AstProxyApi proxyApi in apisOfInterfaces) {
flutterMethodsFromInterfaces.addAll(proxyApi.methods);
}

// A list of Flutter methods inherited from the ProxyApi that this ProxyApi
// `extends`. This also recursively checks the ProxyApi that the super class
// `extends` and so on.
//
// This also includes methods that super classes inherited from interfaces
// with `implements`.
final List<Method> flutterMethodsFromSuperClasses = <Method>[];
for (final AstProxyApi proxyApi in superClassApisChain.reversed) {
flutterMethodsFromSuperClasses.addAll(proxyApi.flutterMethods);
}
if (api.superClass != null) {
final Set<AstProxyApi> interfaceApisFromSuperClasses =
recursiveFindAllInterfaceApis(
api.superClass!.associatedProxyApi!,
);
for (final AstProxyApi proxyApi in interfaceApisFromSuperClasses) {
flutterMethodsFromSuperClasses.addAll(proxyApi.methods);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can these be moved onto the AstProxyApi class itself and be pre-populated during the ast generation?

In general I'm hoping to move any data processing like this into pre generation. Especially if it's going to happen in the dart generator and or multiple generators.

Comment on lines +730 to 748
final bool hasHostMethod = root.apis
.whereType<AstHostApi>()
.any((AstHostApi api) => api.methods.isNotEmpty) ||
root.apis.whereType<AstProxyApi>().any((AstProxyApi api) =>
api.constructors.isNotEmpty ||
api.attachedFields.isNotEmpty ||
api.hostMethods.isNotEmpty);
final bool hasFlutterMethod = root.apis
.whereType<AstFlutterApi>()
.any((AstFlutterApi api) => api.methods.isNotEmpty) ||
root.apis.any((Api api) => api is AstProxyApi);

if (hasHostMethod) {
_writeCreateConnectionError(indent);
}
if (hasFlutterApi || generatorOptions.testOutPath != null) {
if (hasFlutterMethod || generatorOptions.testOutPath != null) {
_writeWrapResponse(generatorOptions, root, indent);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

You don't need to do this, but ideally these checks would be done pre-generation as well, so these bool checks would be a lot cleaner here.

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 created flutter/flutter#144642 to tracking moving the methods to Generator.

Copy link
Contributor

@tarrinneal tarrinneal Feb 22, 2024

Choose a reason for hiding this comment

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

This file makes me want to quit my job. Generally seems like everything is there and makes sense.

I'm torn about whether or not to keep it apart from the other core_tests file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, this file is all generated so that I can write the integration tests and verify the generated code doesn't cause any lint warnings. I assumed the review for this file would only require someone to skim it.

Copy link
Contributor

Choose a reason for hiding this comment

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

In a sense this is the code that needs the most review, since it's the actual functioning code from what you've written. The rest of it is just preference and future work looking.

Comment on lines 181 to 219
/// A list of AstProxyApis where each `extends` the API that follows it.
Iterable<AstProxyApi> get allSuperClasses => recursiveGetSuperClassApisChain(
this,
);

/// All ProxyApis this API `implements` and all the interfaces those APIs
/// `implements`.
Iterable<AstProxyApi> get apisOfInterfaces =>
recursiveFindAllInterfaceApis(this);

/// All methods inherited from interfaces and the interfaces of interfaces.
Iterable<Method> flutterMethodsFromInterfaces() sync* {
for (final AstProxyApi proxyApi in apisOfInterfaces) {
yield* proxyApi.methods;
}
}

/// A list of Flutter methods inherited from the ProxyApi that this ProxyApi
/// `extends`.
///
/// This also recursively checks the ProxyApi that the super class `extends`
/// and so on.
///
/// This also includes methods that super classes inherited from interfaces
/// with `implements`.
Iterable<Method> flutterMethodsFromSuperClasses() sync* {
for (final AstProxyApi proxyApi in allSuperClasses.toList().reversed) {
yield* proxyApi.flutterMethods;
}
if (superClass != null) {
final Set<AstProxyApi> interfaceApisFromSuperClasses =
recursiveFindAllInterfaceApis(
superClass!.associatedProxyApi!,
);
for (final AstProxyApi proxyApi in interfaceApisFromSuperClasses) {
yield* proxyApi.methods;
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know if performance really matters here, but ideally these methods would only ever be ran once, and the data stored on the class.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since some of the fields of AstProxyApi that this method uses are mutable, I don't think we can run it only once. And they are mutable because of the step in pigeon_lib.dart where the associatedProxyApi is added to all the type declarations.

Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't the code that associates the api's make copies? Maybe I'm looking in the wrong place.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unless I'm missing something, a new api is not created: https://github.com/flutter/packages/blob/main/packages/pigeon/lib/pigeon_lib.dart#L1297 and https://github.com/flutter/packages/blob/main/packages/pigeon/lib/pigeon_lib.dart#L1337.

Only NamedTypes (e.g. fields, methods parameters, method returnType, constructor parameters, etc...) are copied. The original apis, methods, and constructors are retained.

But even so, as long as the fields are mutable, it could cause a bug in the future if a contributor uses the method. I do think we should probably restructure the AST with immutable classes in the future. Mutable data classes can end up being a foot-gun.

Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add a todo for this and tag me in it?

packages/pigeon/lib/ast.dart Outdated Show resolved Hide resolved
@bparrishMines bparrishMines requested a review from tarrinneal March 5, 2024 22:04
Copy link
Contributor

@tarrinneal tarrinneal left a comment

Choose a reason for hiding this comment

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

I think we're good to land this now, if @stuartmorgan wants to get another pass in now's the time.

Please add an issue as mentioned above, and I think it's good to land.

@stuartmorgan
Copy link
Contributor

I've reviewed manual versions of the output in webview_flutter in the past, so if you're happy with the generator aspects of this I don't feel like I need to review again.

@bparrishMines bparrishMines added the autosubmit Merge PR when tree becomes green via auto submit App label Mar 19, 2024
@auto-submit auto-submit bot merged commit da16269 into flutter:main Mar 19, 2024
78 checks passed
@bparrishMines bparrishMines deleted the pigeon_wrapper_dart_2 branch March 19, 2024 17:58
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Mar 20, 2024
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Mar 20, 2024
flutter/packages@a2f4ce0...23e56af

2024-03-19 [email protected] [camerax] Update README to encourage users to opt in (flutter/packages#6352)
2024-03-19 [email protected] [flutter_markdown] Allow for custom block element (flutter/packages#5815)
2024-03-19 [email protected] [pigeon] Adds Dart implementation of ProxyApi (flutter/packages#6043)
2024-03-19 [email protected] [camerax] Implements `setFocusMode` (flutter/packages#6176)
2024-03-19 [email protected] Roll Flutter from f217fc1 to d31a85b (23 revisions) (flutter/packages#6356)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC [email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
arc-yong pushed a commit to Arctuition/packages-arc that referenced this pull request Jun 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
autosubmit Merge PR when tree becomes green via auto submit App p: pigeon
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants