Description
After the new tall style issue, the two formatter issues with the most 👍 are both about configuring page width (1, 2). This has been the #1
feature request for many years with hundreds of users asking for it.
So we are adding support for project-wide page width configuration to the formatter. After weighing a number of ways to author this configuration, the best approach seems to be a combination of two options. Each helps address the problems of the other:
Look for a surrounding analysis_options.yaml file and let it configure the page width
When formatting a file on disk using dart format
, we walk up the surrounding directories looking for an analysis_options.yaml
file. If we find one and it has a section like:
formatter:
page_width: 123
Then the file is formatted at that width.
This lets users author the width in one location in a parent directory (likely the root directory of a package), and then all files in that directory tree get formatted the same way. Since analysis_options.yaml
files also support an include
key to import another analysis_options.yaml
file, organizations have a way to have a standardized formatting style shared across all of their projects.
The main problem with using analysis_options.yaml
(or any other config file) is that code generators and other tools that format code that only exists in memory don't know what config file to use. If the code generator doesn't use the configured width, but the user then runs dart format
on the whole directory, the generated code will be changed. Likewise, if CI tries to validate that every file is formatted using the configured width, that will fail because the generated stuff is formatted at a different width.
Allow a comment inside of a source file to indicate the page width for that file
If you put // dart format width=123
at the top of a file, then the file is formatted at that page width. This is simple to implement, and works with dart format
, code generators, and any other tool that wants to format code. It works even without having access to file IO or any knowledge of where the formatted code will end up on disk.
But it's very tedious for users to have to remember to put this in every single file they author. If they forget, they get inconsistently formatted code. No user has asked for this. They want project-wide configuration.
Hybrid approach
We implement both of these. If there is both a project-wide page width set in analysis_options.yaml
and the file has a page width comment, the latter takes precedence (just like a // @dart=1.2
language version comment takes precedence over the SDK constraint in a pubspec).
Mixing both approaches lets us avoid the problems with each:
-
Tools like
dart format
and IDEs look for a configured project-wide page width inanalysis_options.yaml
. This is implemented indart format
now (behind an experiment flag). The analysis_server package, which most Dart IDE integrations use, already has support for working withanalysis_options.yaml
files, so plumbing the page width from that to the files it formats should be straightforward.This gives users the project-wide configuration they want for the code they write and read.
-
Tools that generate Dart code and then immediately format in memory without having easy access to the surrounding
analysis_options.yaml
file can simply add a// dart format width=123
comment to the top of the generated code before they format it.Since that takes precedence over any project-wide configuration, then formatting that file in memory with no
analysis_options.yaml
file will produce the same results as when the file is later formatted withdart format
or the IDE. That should mean that things like CI steps that check for formatted files won't end up breaking on generated code.
This approach does mean that generated files may have a different width than the user prefers. But these files are fairly rarely read, so that's a tolerable compromise to avoid having every library that works with generated code and the formatter become obligated to support searching for and reading analysis_options.yaml
(which isn't possible in some contexts like build_runner).
Implementation tasks
The core formatter work is done now (but behind a flag). The work remaining is largely in other packages:
- Generalize lines_longer_than_80_characters #59552 Generalize lines_longer_than_80_characters lint to use the configured width.
- Plumb page width from analysis_options.yaml to formatter when formatting in analysis_server #56864 Have analysis_server plumb page width from analysis_options.yaml to formatter
- Add "// dart format width=80" comment in generated code source_gen#724 Have source_gen include the page width comment in generated code
- Reserve "formatter" as a package name pub-dev#8128 Reserve "formatter" package name on pub
- Respect
formatter: page-width
setting inanalysis_options.yaml
pana#1405 Use configured page width in pana