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

Replace json_utils with a modern extension type, add tests. #52769

Merged
merged 8 commits into from
May 14, 2024

Conversation

matanlurey
Copy link
Contributor

I started on a refactoring of flutter/flutter#147666, and was frustrated with the JSON decoding of gn desc --format=json, so I used a similar pattern from my micro-json library (https://pub.dev/packages/jsonut) and encapsulated it as an extension type.

My favorite is the JsonObject.map function which replaces:

/// Construct a RunTarget from a JSON map.
factory RunTarget.fromJson(Map<String, Object> map) {
  final List<String> errors = <String>[];
  final String name = stringOfJson(map, _nameKey, errors)!;
  final String id = stringOfJson(map, _idKey, errors)!;
  final String targetPlatform =
      stringOfJson(map, _targetPlatformKey, errors)!;

  if (errors.isNotEmpty) {
    throw FormatException('Failed to parse RunTarget: ${errors.join('\n')}');
  }
  return RunTarget._(name, id, targetPlatform);
}

... with:

/// Construct a RunTarget from a JSON map.
factory RunTarget.fromJson(Map<String, Object> map) {
  return JsonObject(map).map((JsonObject json) => RunTarget._(
    json.string(_nameKey),
    json.string(_idKey),
    json.string(_targetPlatformKey),
  ));
}

/// [map] to read multiple values at once and convert them to a custom object:
///
/// ```dart
/// try {
Copy link
Member

Choose a reason for hiding this comment

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

This seems like a good pattern to follow, and I think it's necessary to use it when parsing JSON with this API in the situation that the errors that are accumulated are expected to be user-actionable. (For example, if we used this API for parsing the build config json under ci/builders.)

In this PR, the JSON that this API is parsing is internal. That is, if there's a problem with it, the user wouldn't necessarily be expected to fix it. So if the JSON exceptions aren't caught and make it to the terminal, that seems to be WAI.

But that leaves the awkward situation that the pattern noted here, which should be followed in certain situations, doesn't have a live example in this PR. My suggestion to avoid that awkwardness would be that we just always follow this pattern, so that future users of the API follow it as well even when it isn't strictly necessary.

Copy link
Contributor Author

@matanlurey matanlurey May 13, 2024

Choose a reason for hiding this comment

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

But that leaves the awkward situation that the pattern noted here, which should be followed in certain situations, doesn't have a live example in this PR.

Do you mean that we don't have try/catch of JsonMapException?

I could imagine doing that, but as you mentioned we don't have any way to do recovery in this CLI - mal-formatted JSON means we'll have to stop, so the best we could do is try-catch and provide a more context-aware error message (for example 'Failed to parse process artifacts: $error').

Copy link
Member

Choose a reason for hiding this comment

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

the best we could do is try-catch and provide a more context-aware error message (for example 'Failed to parse process artifacts: $error').

Yeah, I think if there's a nice place to try that in this PR, then that would be an improvement.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds reasonable.

I might add a onError callback in that case so nesting doesn't get unnecessarily long.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done, and added as discussed. Thanks!

@matanlurey matanlurey requested a review from zanderso May 13, 2024 22:25
@@ -0,0 +1,346 @@
import 'dart:convert' show JsonEncoder, jsonDecode;
Copy link
Member

Choose a reason for hiding this comment

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

Needs the engine copyright header.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

/// },
/// );
/// ```
T map<T extends Object>(
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure how it would be useful, but if T can be a Future, then I'm not sure that the mechanism for saving and restoring the errors will work. Is there some way to say that T can't be a Future?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

2018 Matan was ahead of us both: dart-lang/sdk#35024.

It is probably trivial to add such a hint assuming the analyzer team is on board. For now I'll do a runtime check that the result is not a Future.

Copy link
Member

@zanderso zanderso left a comment

Choose a reason for hiding this comment

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

LGTM

@matanlurey matanlurey merged commit 84687fe into flutter:main May 14, 2024
26 checks passed
@matanlurey matanlurey deleted the et-typed-json-2024 branch May 14, 2024 03:03
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request May 14, 2024
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request May 14, 2024
…148282)

flutter/engine@bee398d...84687fe

2024-05-14 matanlurey@users.noreply.github.com Replace `json_utils` with a modern `extension type`, add tests. (flutter/engine#52769)
2024-05-14 jason-simmons@users.noreply.github.com Move libcxx to //flutter/third_party (flutter/engine#52773)
2024-05-14 dustingreen@google.com [fuchsia][sysmem2] route fuchsia.sysmem2.Allocator (flutter/engine#52708)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-engine-flutter-autoroll
Please CC rmistry@google.com,zra@google.com 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants