Skip to content

update the generator to emit formatted files #1020

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

Merged
merged 6 commits into from
Jul 15, 2025
Merged

Conversation

devoncarew
Copy link
Collaborator

  • update the generator to emit formatted files

This uses package:dart_style to format the generated proto files.

There is additional complexity here as we support an option to generate metadata about the source location of symbols for .pb.dart and .pbenum.dart files. I see a reference to this being in support of the Kythe indexer. I'm not sure why it needs us to generate metadata files for it to use - it can just parse dart source directly. Perhaps this option is no longer needed? It would be nice to be able to remove it for general simplification.

@devoncarew devoncarew requested a review from osa1 June 11, 2025 16:47
@devoncarew
Copy link
Collaborator Author

@osa1, once this lands (after review and such), I may have one more small style PR, then would likely want to do another publish.

@osa1
Copy link
Member

osa1 commented Jun 11, 2025

Why do you want the plugin to generate formatted files?

The problem with formatting generated files in protoc plugin is that the plugin and the project that uses generated files can have different formatting settings and foramtter versions. This may even be the common case for non-Google packages, or if you rarely update your protoc plugin as you update your Dart versions.

So you have to format generated files anyway with your project's formatter.

I don't remember if adding dart_style as a dependency was a problem for g3, but we should check that as well.

(I don't have access to g3 right now, I can check tomorrow.)

FWIW, grpc generator used to format generated files in the open source version but not in the g3 version. That may suggest that there's a problem with adding dart_style dependency to the g3 version. #702 then removed formatting in the open source version as well.

Maybe an alternative could be formatting the files with dart format (as a shell command) rather than with a formatter built into the plugin. That way the formatting would be done using the project's settings rather than the plugin's.

@devoncarew
Copy link
Collaborator Author

devoncarew commented Jun 11, 2025

Why do you want the plugin to generate formatted files?

For general readability, and so the generated code looks and feels like regular dart code. I think its more common then not to have your generated code be formatted. See the readme example for our code_builder package: https://github.com/dart-lang/tools/tree/main/pkgs/code_builder.

The problem with formatting generated files in protoc plugin is that the plugin and the project that uses generated files can have different formatting settings and foramtter versions. This may even be the common case for non-Google packages, or if you rarely update your protoc plugin as you update your Dart versions.

So you have to format generated files anyway with your project's formatter.

Yes, this is a good point. I think less of an issue for quite a while, but we've had big formatter changes from 3.6 => 3.7, and additional changes from 3.7 => 3.8.

I don't remember if adding dart_style as a dependency was a problem for g3, but we should check that as well.

FWIW, grpc generator used to format generated files in the open source version but not in the g3 version. That may suggest that there's a problem with adding dart_style dependency to the g3 version. #702 then removed formatting in the open source version as well.

I don't know if the dep is an issue; worth digging into through.

Separately, I don't know that formatting generated files matters as much for google3. I think generated files there are treated more ephemerally; they're almost never committed, and just available after a blaze build. cc @srawlins

Maybe an alternative could be formatting the files with dart format (as a shell command) rather than with a formatter built into the plugin. That way the formatting would be done using the project's settings rather than the plugin's.

I think using the formatter as a library will have fewer moving parts - we won't have to shell out to anything. But aside from that, I think we would want a deterministic way for the user to indicate which dart version to format with (in this PR, see: protoc_plugin/lib/src/formatter.dart).

  • we could hard-code the version in the source code, and update that as the min. sdk version of package:protoc_plugin changes
  • we could assume that package:protoc_plugin has been added as a dev dependency of the generation target, and read the min. sdk version from that pubspec. that would mean we'd get the same formatting version as the rest of the target package's source
  • format using 'dart format' w/ a cwd of the generation output directory
  • find the nearest pubspec to the generation output directory, read the min sdk version, and use that version for the formatter

@devoncarew
Copy link
Collaborator Author

After thinking about this a bit more, I updated this PR (09eaaa8) to always format using the Dart version from the min. sdk constraint in the protoc_plugin pubspec. This:

  • is predictable for users; a particular version of protoc_plugin will always format the same
  • doesn't require us to plumb a new parameter through the dart plugin options, or, require the user to know about a new option
  • means we don't have to do something potentially unpredictable, like looking around the filesystem in the output directory for a parent pubspec file, and reading the sdk constraint version from that

If its necessary for a particular use of protoc_plugin to have the files formatted at a specific version, they can always generate+format as part of their regular regeneration process.

Copy link
Member

@osa1 osa1 left a comment

Choose a reason for hiding this comment

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

Btw, I asked around a little bit and found this prior art on formatting generated codes:

There's also a build_runner package for Dart protos: https://github.com/pikaju/dart-protoc-builder

I don't know if it does formatting itself.

return _buffer.toString();
var source = _buffer.toString();

// We don't always want to format the source (for example, we don't want to
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is an interesting problem. It would be cool if we had some way of "anchoring" the annotated locations in the source.

Something like https://gcc.gnu.org/onlinedocs/cpp/Line-Control.html#Line-Control-1 ...

@lrhn wdyt?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Hmm, I think that would be interesting. I have in the past (when absolutely necessary) 'recovered' locations post format by:

  • generating code and recording the location something was generated at
  • formatting the code
  • recognizing that the formatter is only ever changing whitespace; recover the new post-format location by counting the number of non-whitespace chars from the start of the file

Separately, I think this location annotation code only exists for generating files used by kythe. I don't know if those are used anymore? Kythe has a dart parser, so not sure why we need to generate separate symbol location files for it. 🤷

@devoncarew devoncarew merged commit 38f1549 into master Jul 15, 2025
16 checks passed
@devoncarew devoncarew deleted the format_output branch July 15, 2025 18:11
copybara-service bot pushed a commit to dart-lang/sdk that referenced this pull request Jul 22, 2025
Revisions updated by `dart tools/rev_sdk_deps.dart`.

ai (https://github.com/dart-lang/ai/compare/61ba1ea..40607dc):
  40607dc  2025-07-21  Jacob MacDonald  rename ElicitationHandler.reject to ElicitationHandler.decline (dart-lang/ai#240)
  ec6efa4  2025-07-21  Kostia Sokolovskyi  Fix ping request handling from non-dart clients. (dart-lang/ai#239)
  00889b4  2025-07-17  Jacob MacDonald  release dart_mcp version 0.3.2 (dart-lang/ai#237)
  5e93ef4  2025-07-17  Jacob MacDonald  Deprecate EnumSchema and JsonType.enumeration (dart-lang/ai#236)
  66af21b  2025-07-17  Jacob MacDonald  fix the firstMatchOnly and matchRoot schemas to be booleans (dart-lang/ai#235)
  141fbe1  2025-07-17  Jacob MacDonald  release dart_mcp 0.3.1 (dart-lang/ai#234)
  ce519e8  2025-07-17  Jacob MacDonald  Add flutter driver tool (dart-lang/ai#223)
  3bf650e  2025-07-16  Jacob MacDonald  add completions support to the prompts example (dart-lang/ai#233)
  aed93b4  2025-07-16  Jacob MacDonald  Deprecate the WithElicitationhandler interface (dart-lang/ai#231)
  01cf3d4  2025-07-16  Jacob MacDonald  Require dart_mcp version 0.3.1 (dart-lang/ai#232)
  5c28640  2025-07-16  Jacob MacDonald  add a sampling example (dart-lang/ai#230)
  df0c4f1  2025-07-16  Jacob MacDonald  add elicitation example, fix some issues with the elicitation APIs (dart-lang/ai#229)

http (https://github.com/dart-lang/http/compare/2d9681d..4a90d16):
  4a90d16  2025-07-21  Alex Li  [cronet_http] Update Cronet dependencies version (dart-lang/http#1796)
  5c06c6c  2025-07-18  Brian Quinlan  Prepare to release cronet 1.4.0 (dart-lang/http#1794)
  8c49ef5  2025-07-18  Hossein Yousefi  [cronet_http] Upgrade jni and jnigen to 0.14.2 (dart-lang/http#1793)
  ca07b4c  2025-07-17  Brian Quinlan  Add request cancellation to cupertino_http (dart-lang/http#1779)
  984cc43  2025-07-15  Brian Quinlan  Fix a bug where ConnectionException.toString didn't stringify NSError (dart-lang/http#1785)

protobuf (https://github.com/dart-lang/protobuf/compare/04bd6ac..4916e6f):
  4916e6f  2025-07-21  Ömer Sinan Ağacan  CI: Test PRs and commits to all branches, instead of just master (google/protobuf.dart#1029)
  a9822d8  2025-07-16  Devon Carew  prep for publishing protobuf 4.1.1, protoc_plugin 22.5.0 (google/protobuf.dart#1025)
  38f1549  2025-07-15  Devon Carew  update the generator to emit formatted files (google/protobuf.dart#1020)

test (https://github.com/dart-lang/test/compare/2be5ca0..c201cc9):
  c201cc98  2025-07-21  Nate Bosch  Expand Analyzer constraints to allow 8.x (dart-lang/test#2518)

tools (https://github.com/dart-lang/tools/compare/a4335eb..2a2a2d6):
  2a2a2d61  2025-07-17  Nikechukwu  [code_builder] Set `external` and `static` in correct order (dart-lang/tools#2120)

web (https://github.com/dart-lang/web/compare/7e0853d..767151e):
  767151e  2025-07-21  Nikechukwu  [web_generator] Bug Fixes in Entrypoint `gen_interop_bindings.dart` (dart-lang/web#423)
  1f80532  2025-07-21  Nikechukwu  [interop] Support `typeof` type declarations (dart-lang/web#417)
  affce52  2025-07-17  Kevin Moore  generator: drop build bits. Not used. (dart-lang/web#419)
  0a16c09  2025-07-17  Nikechukwu  [interop] Support Classes and Interfaces (dart-lang/web#415)

Change-Id: I9fbe6d7c15d63b19e45829628e7c5dfb3e87ca6c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/441820
Auto-Submit: Devon Carew <[email protected]>
Reviewed-by: Konstantin Shcheglov <[email protected]>
Commit-Queue: Konstantin Shcheglov <[email protected]>
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.

3 participants