No longer format imports with configurations and a prefix in the wrong order. The parser used to accept this without error even though it violated the language spec. The parser is being fixed, so the formatter will no longer accept or format code like:
import 'foo.dart' as prefix if (cond) 'bar.dart';
Don't force a space between ? and . if a null-aware element contains a dot shorthand.
@dart= version comments when determining which >3.7 style to apply. The formatter correctly used those comments to switch between the old short and new tall style, but ignored them for language versioned style rule changes after 3.7. Now the language version of the file is consistently respected for all style rules (#1762).package:analyzer.trailing_commas: preserve) applies to record type annotations too (#1721).This change only applies to code whose language version is 3.10 or higher:
When trailing_commas is preserve, preserve a trailing comma after the last enum constant when members are present (#1678, #1729).
// Before formatting: enum { constant, ; member() {} } // After formatting at language version 3.9 or lower: enum { constant; member() {} } // After formatting at language version 3.10 or higher: enum { constant, ; member() {} }
(Thanks to jellynoone@ for this change.)
This release contains a fairly large number of style changes in response to feedback we got from shipping the new tall style formatter.
Allow preserving trailing commas and forcing the surrounding construct to split even when it would otherwise fit on one line. This is off by default (because it breaks reversibility among other reasons) but can be enabled by adding this to a surrounding analysis_options.yaml file:
formatter: trailing_commas: preserve
This is similar to how trailing commas work in the old short style formatter applied to code before language version 3.7.
The following style changes are language versioned and only affect code whose language version is 3.8 or later. Dart code at 3.7 or earlier is formatted the same as it was before.
Allow more code on the same line as a named argument or => (#1536, #1545, #1668, #1679).
// Before: function( name: (param, another) => veryLongBody, ); function( name: (param) => another( argument1, argument2, argument3, ), ); // After: function( name: (param, another) => veryLongBody, ); function( name: (param) => another( argument1, argument2, argument3, ), );
Avoid splitting chains containing only properties.
// Before: variable = target .property .another; // After: variable = target.property.another;
Note that this only applies to . chains that are only properties. If there are method calls in the chain, then it prefers to split the chain instead of splitting at =, :, or =>.
Allow the target or property chain part of a split method chain on the RHS of =, :, and => (#1466).
// Before: variable = target.property .method() .another(); // After: variable = target.property .method() .another();
Allow the condition part of a split conditional expression on the RHS of =, :, and => (#1465).
// Before: variable = condition ? longThenBranch : longElseBranch; // After: variable = condition ? longThenBranch : longElseBranch;
Don't indent conditional branches redundantly after =, :, and =>.
// Before: function( argument: condition ? thenBranch : elseBranch, ) // After: function( argument: condition ? thenBranch : elseBranch, )
Indent conditional branches past the operators (#1534).
// Before: condition ? thenBranch + anotherOperand : elseBranch( argument, ); // After: condition ? thenBranch + anotherOperand : elseBranch( argument, );
Block format record types in typedefs (#1651):
// Before: typedef ExampleRecordTypedef = ( String firstParameter, int secondParameter, String thirdParameter, String fourthParameter, ); // After: typedef ExampleRecordTypedef = ( String firstParameter, int secondParameter, String thirdParameter, String fourthParameter, );
Eagerly split argument lists whose contents are complex enough to be easier to read spread across multiple lines even if they would otherwise fit on a single line (#1660). The rules are basically:
If an argument list contains at least three named arguments, at least one of which must be directly in the argument list and at least one of which must be nested in an inner argument list, then force the outer one to split. We make an exception where a named argument whose expression is a simple number, Boolean, or null literal doesn't count as a named argument.
If a list, set, or map literal is the immediate expression in a named argument and contains any argument lists with a named argument, then force the collection to split.
// Before: TabBar(tabs: [Tab(text: 'A'), Tab(text: 'B')], labelColor: Colors.white70); // After: TabBar( tabs: [ Tab(text: 'A'), Tab(text: 'B'), ], labelColor: Colors.white70, );
|| patterns like fallthrough cases in switch expressions (#1602).This is a large change. Under the hood, the formatter was almost completely rewritten, with the codebase now containing both the old and new implementations. The old formatter exists to support the older “short” style and the new code implements the new “tall” style.
The formatter uses the language version of the formatted code to determine which style you get. If the language version is 3.6 or lower, the code is formatted with the old style. If 3.7 or later, you get the new tall style. You typically control the language version by setting a min SDK constraint in your package's pubspec.
In addition to the new formatting style, a number of other API and CLI changes are included, some of them breaking:
Support project-wide page width configuration. By long request, you can now configure your preferred formatting page width on a project-wide basis. When formatting files, the formatter will look in the file's directory and any surrounding directories for an analysis_options.yaml file. If it finds one, it looks for the following YAML:
formatter: page_width: 123
If it finds a formatter key containing a map with a page_width key whose value is an integer, then that is the page width that the file is formatted using. Since the formatter will walk the surrounding directories until it finds an analysis_options.yaml file, this can be used to globally set the page width for an entire directory, package, or even collection of packages.
Support overriding the page width for a single file. In code formatted using the new tall style, you can use a special marker comment to control the page width that it's formatted using:
// dart format width=30 main() { someExpression + thatSplitsAt30; }
This comment must appear before any code in the file and must match that format exactly. The width set by the comment overrides the width set by any surrounding analysis_options.yaml file.
This feature is mainly for code generators that generate and immediately format code but don‘t know about any surrounding analysis_options.yaml that might be configuring the page width. By inserting this comment in the generated code before formatting, it ensures that the code generator’s behavior matches the behavior of dart format.
End users should mostly use analysis_options.yaml for configuring their preferred page width (or do nothing and use the default page width of 80).
Support opting out a region of code from formatting. In code formatted using the new tall style, you can use a pair of special marker comments to opt a region of code out of automated formatting:
main() { this.isFormatted(); // dart format off no + formatting + here; // dart format on formatting.isBackOnHere(); }
The comments must be exactly // dart format off and // dart format on. A file may have multiple regions, but they can't overlap or nest.
This can be useful for highly structured data where custom layout can help a reader understand the data, like large lists of numbers.
Remove support for fixes and --fix. The tools that come with the Dart SDK provide two ways to apply automated changes to code: dart format --fix and dart fix. The former is older and used to be faster. But it can only apply a few fixes and hasn't been maintained in many years. The dart fix command is actively maintained, can apply all of the fixes that dart format --fix could apply and many many more.
In order to avoid duplicate engineering effort, we decided to consolidate on dart fix as the one way to make automated changes that go beyond the simple formatting and style changes that dart format applies.
The ability to apply fixes is also removed from the DartFormatter() library API.
Make the language version parameter to DartFormatter() mandatory. This way, the formatter always knows what language version the input is intended to be treated as. Note that a // @dart= language version comment, if present, overrides the specified language version. You can think of the version passed to the DartFormatter() constructor as a “default” language version which the file's contents may then override.
If you don‘t particularly care about the version of what you’re formatting, you can pass in DartFormatter.latestLanguageVersion to unconditionally get the latest language version that the formatter supports. Note that doing so means you will also implicitly opt into the new tall style.
This change only affects the library API. When using the formatter from the command line, you can use --language-version= to specify a language version or pass --language-version=latest to use the latest supported version. If omitted, the formatter will look in the surrounding directories for a package config file and infer the language version for the package from that, similar to how other Dart tools behave like dart analyze and dart run.
Remove the old formatter executables and CLI options. Before the dart format command was added to the core Dart SDK, users accessed the formatter by running a separate dartfmt executable that was included with the Dart SDK. That executable had a different CLI interface. For example, you had to pass -w to get it to overwrite files. When we added dart format, we took that opportunity to revamp the CLI options.
However, the dart_style package still exposed an executable with the old CLI. If you ran dart pub global activate dart_style, this would give you a dartfmt (and dartformat) executable with the old CLI options. Now that almost everyone is using dart format, we have removed the old CLI and the old package executables.
You can still run the formatter on the CLI through the package (for example, if you want to use a particular version of dart_style instead of the one bundled with your Dart SDK). But it now uses the exact same CLI options and arguments as the dart format command. You can invoke it with dart run dart_style:format <args...>.
Treat the --stdin-name name as a path when inferring language version. When reading input on stdin, the formatter still needs to know what language version to parse the code as. If the --stdin-name option is set, then that is treated as a file path and the formatter looks for a package config surrounding that file path to infer the language version from.
If you don't want that behavior, pass in an explicit language version using --language-version=, or use --language-version=latest to parse the input using the latest language version supported by the formatter.
If --stdin-name and --language-version are both omitted, then the formatter parses stdin using the latest supported language version.
Rename the --line-length option to --page-width. This is consistent with the public API, internal implementation, and docs, which all use “page width” to refer to the limit that the formatter tries to fit code into.
The --line-length name is still supported for backwards compatibility, but may be removed at some point in the future. You‘re encouraged to move to --page-width. Use of this option (however it’s named) is rare, and will likely be even rarer now that project-wide configuration is supported, so this shouldn't affect many users.
Apply class modifiers to API classes. The dart_style package exposes only a few classes in its public API: DartFormatter, SourceCode, FormatterException, and UnexpectedOutputException. None were ever intended to be extended or implemented. They are now all marked final to make that intention explicit.
Require package:analyzer >=6.5.0 <8.0.0.
DartFomatter(). Formatted code will be parsed at that version. If omitted, defaults to the latest version. In a future release, this parameter will become required.// dart format off and // dart format on comments. Note: This only works using the new tall style and requires passing the --enable-experiment=tall-style experiment flag (#361).this. or super. (#1321).as and if clauses (#1544).package:analyzer >=6.5.0 <7.0.0.3.3 to parse so that code with extension types can be formatted.macro modifier when the macros experiment flag is passed.tall-style experiment flag to enable the in-progress unstable new formatting style (#1253).inline class since that syntax has changed.--enable-experiment command-line option to enable language experiments. The library API also supports this with DartFormatter.experimentFlags.. following a record literal (#1213).package:analyzer >=5.12.0 <7.0.0.? on nullable empty record types (#1224).--fix and related options in --help. The options are still there and supported, but are no longer shown by default. Eventually, we would like all users to move to using dart fix instead of dart format --fix.|| pattern operands in switch expression cases.sealed, interface, and final keywords on mixin declarations. The proposal was updated to no longer support them.base, final, interface, mixin, and sealed.inline class declarations.sync* and async* functions with => bodies.< in collection literals._visitFunctionOrMethodDeclaration instead of dynamically typed.( significant (sdk#50769).package:analyzer ^5.7.0.{ or [ and a subsequent comment. It used to do this before the { in type bodies, but not switch bodies, optional parameter sections, or named parameter sections.package:analyzer >=4.4.0 <6.0.0.package:analyzer.package:analyzer version 2.6.0.NamedType instead of TypeName./* */ comments (#837).FormatCommand when formatting stdin (#1035).package:analyzer.>>> and >>>= operators (#992).required (#1010).FormatCommand.run() now returns the value set in exitCode during formatting.package:analyzer.package:args and package:pub_semver.? in initializing formal function-typed parameters (#960).?:) when they are nested (#927).external and abstract fields and variables (#946).--stdin-name=<stdin>.--fix-single-cascade-statements.var in --fix-function-typedefs (#826).?.[] to ?[].package:analyzer 0.39.0.? in types.late modifier.required modifier.. when the target is parenthesized (#704).package:analyzer 0.38.0.package:analyzer 0.37.0.=> functions.Properly format trailing commas in assertions.
Improve indentation of adjacent strings. This fixes a regression introduced in 1.2.5 and hopefully makes adjacent strings generally look better.
Adjacent strings in argument lists now format the same regardless of whether the argument list contains a trailing comma. The rule is that if the argument list contains no other strings, then the adjacent strings do not get extra indentation. This keeps them lined up when doing so is unlikely to be confused as showing separate independent string arguments.
Previously, adjacent strings were never indented in argument lists without a trailing comma and always in argument lists that did. With this change, adjacent strings are still always indented in collection literals because readers are likely to interpret a series of unindented lines there as showing separate collection elements.
if and for elements inside collections (#779).package:analyzer constraint to '>=0.33.0 <0.36.0'.--fix-function-typedefs to convert the old typedef syntax for function types to the new preferred syntax.--stdin-name to specify name shown when reading from stdin (#739).--fix-doc-comments to turn /** ... */ doc comments into /// (#730).const in all metadata annotations with --fix-optional-const` (#720).Preserve whitespace in multi-line strings inside string interpolations (#711). Note! This bug means that dart_style 1.1.2 may make semantics changes to your strings. You should avoid that version and use 1.1.3.
Set max SDK version to <3.0.0, and adjusted other dependencies.
: to = as the named parameter default value separator.new keywords.const keywords.package:analyzer.. if the target expression is an argument list with a trailing comma (#548, #665).new/const (#652).pkg/args.pkg/analyzer.- and -- (#170).=> bodies (#584).< when a collection is in statement position (#589).covariant modifier on methods.is and as expressions.--set-exit-if-changed to set the exit code on a change (#365).--version command line argument (#240).. in a method chain if the target splits (#255).=> bodies (#434.if statements without curly bodies better (#448).get and set (#462).--indent to specify leading indent (#464).for fully split if initializers or updaters do (#375, #377).deferred (#381).as and is expressions (#384).?., ??, and ??=) (#385).BREAKING: The indent argument to new DartFormatter() is now a number of spaces, not indentation levels.
This version introduces a new n-way constraint system replacing the previous binary constraints. It‘s mostly an internal change, but allows us to fix a number of bugs that the old solver couldn’t express solutions to.
In particular, it forces argument and parameter lists to go one-per-line if they don't all fit in two lines. And it allows function and collection literals inside expressions to indent like expressions in some contexts. (#78, #97, #101, #123, #139, #141, #142, #143, et. al.)
Indent cascades more deeply when the receiver is a method call (#137).
Preserve newlines in collections containing line comments (#139).
Allow multiple variable declarations on one line if they fit (#155).
Prefer splitting at “.” on non-identifier method targets (#161).
Enforce a blank line before and after classes (#168).
More precisely control newlines between declarations (#173).
Preserve mandatory newlines in inline block comments (#178).
Splitting inside type parameter and type argument lists (#184).
Nest blocks deeper inside a wrapped conditional operator (#186).
Split named arguments if the positional arguments split (#189).
Re-indent line doc comments even if they are flush left (#192).
Nest cascades like expressions (#200, #203, #205, #221, #236).
Prefer splitting after => over other options (#217).
Nested non-empty collections force surrounding ones to split (#223).
Allow splitting inside with and implements clauses (#228, #259).
Allow splitting after = in a constructor initializer (#242).
If a => function's parameters split, split after the => too (#250).
Allow splitting between successive index operators (#256).
Correctly indent wrapped constructor initializers (#257).
Set failure exit code for malformed input when reading from stdin (#359).
Do not nest blocks inside single-argument function and method calls.
Do nest blocks inside => functions.
test package runner internally.analyzer and args packages.dartformat to dartfmt.--dry-run option to show files that need formatting (#67).await for statements (#154).- calls (#170).-t flag to preserve compatibility with old formatter (#166).--machine flag for machine-readable output (#164).