NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
pub.dev · #15 most downloaded on pub.dev
Opinionated, automatic Dart source code formatter. Provides an API and a CLI tool.
Last release 1 months ago
26 Aug 2026
Ships fairly regularly
a new release about every 6 weeks
Nearly every release is documented
notes for 58 of the last 60 stable releases
1 version withdrawn
withdrawn after publishing
12 years old
120 releases · first in 2015
The setter for lineEnding is still available but is marked deprecated and does nothing. This is technically a breaking change , but I believe no code…
enum Color {
red,
yellow,
blue,
}enum Color() {
red,
yellow,
blue,
}DartFormatter.lineEnding is no longer mutable. If no line ending islineEnding field. Instead, accessinglineEnding always returns the value you passed in the constructor.DartFormatter instance to format code withformat() will infer a separate line ending for only that call's codelineEnding is still available but is marked deprecated andformat(), or call thelineEnding getter. I haven't found any code on pub that sets or getslineEnding, so I suspect this change is harmless. In a future major versionOne column per quarter.
Allow package_config version 3 ( #1876 ).
Internal changes Migrate off grinder. Allow analyzer version 14.
Show the supported language versions in dart format --version --verbose .
dart format --version --verbose.analysis_options.yaml file has an include that points toThe following minor style bug fixes are not language versioned and apply to all
formatted code:
Fix a bug in eager splitting optimization that in rare cases would lead to a
collection or argument list splitting unnecessarily (#1809).
Don't add a blank line before a comment at the end of a compilation unit or
braced body (#1644).
If you have already formatted code using dart_style that encounters this bug,
then reformatting it even after this fix will have no effect since the
unneeded blank line was already added.
The following changes only apply when formatting code at language version 3.13
or higher:
Fix a bug in an eager splitting optimization that would lead the formatter to
prefer less desirable solutions (#1847).
Typically, the code affected by this bug is a call chain that contains an
argument list with a large collection literal, as in:
// Before:
await MethodChannelContainer()
.onMethodChannelInvoke("reportCrash", <String, dynamic>{
"time": nowTime,
"errorValue": errorName,
"reason": reason,
"stacktrace": stacktrace,
});
// After:
await MethodChannelContainer().onMethodChannelInvoke(
"reportCrash",
<String, dynamic>{
"time": nowTime,
"errorValue": errorName,
"reason": reason,
"stacktrace": stacktrace,
},
);Prefer to split call chains for single-element targets (#1732).
When formatting a method call chain whose target can also split, the formatter
must decide whether to split the target or the call chain (or both). For
example:
// Split target:
function(
argument,
).method().another();
// Or split chain:
function(argument)
.method()
.another();We've tried various heuristics for this over the years but most make some code
look better while making other code look worse. This version introduces a
relatively simple rule that seems to work well in practice: If the call chain
target has only one element or argument, then prefer to split the call chain
and keep the target together. So in the above example, if prefers the second
output.
Allow block formatting parameter lists (#1693). The formatter supports
"block formatting" for most bracket-delimited constructs in the language. This
is what enables a multi-line list literal in an assignment to look like this:
variable = [
some,
list,
elements,
];Instead of:
variable =
[
some,
list,
elements,
];This style applies to most language constructs, but function parameter lists
were omitted. Now they are not. This rarely shows up in real code, except for
typedefs of large function types:
// Before:
typedef DataViewBuilder<T> =
Widget Function(
BuildContext context,
PagingState<int, T> state,
NextPageCallback fetchNextPage,
);
// After:
typedef DataViewBuilder<T> = Widget Function(
BuildContext context,
PagingState<int, T> state,
NextPageCallback fetchNextPage,
);Allow as, is, and is! expressions to be block formatted (#1542).
// Before:
variable =
function(
argument,
argument,
argument,
)
as Type;
// After:
variable = function(
argument,
argument,
argument,
) as Type;Separate imports into sections (#1120). Following the guidelines in
"Effective Dart", the formatter inserts a blank line between
"dart:", "package:", and other imports:
// Before:
import 'dart:io';
import 'dart:math';
import 'package:args/args.dart';
import 'package:test/test.dart';
import 'my_library.dart';
// After:
import 'dart:io';
import 'dart:math';
import 'package:args/args.dart';
import 'package:test/test.dart';
import 'my_library.dart';In if-case statements and elements, split the guard if the pattern
block-splits (#1596).
This tends to lead to code where the pattern is kept on one line and the
guard splits:
// Before:
if (expression case SomeClass(
property: var x,
) when guardClause(x)) {
...
}
// After:
if (expression case SomeClass(property: var x)
when guardClause(x)) {
...
}When no solution fits the page width, prefer solutions where the overflowing
lines have trailing string literals or comments (#1802, #1803, #1837).
Sometimes the formatter is unable to split the code in a way that fits it all
within the page width. When this happens, the formatter prefers whatever
solution has the fewest overflowing characters.
In practice, overflowing solutions are usually caused by long string literals
or comments that the user should split manually. To help the user do that, the
formatter now treats overflowing characters caused by trailing string
literals, comments, and a few other things that often follow a string literal
like ,, ;, () {, or () async {, as "less bad" when comparing the
amount of overflow between two solutions.
The effect is that when no solution fits, the formatter tends to prefer a
solution with hanging strings or comments, which makes it clearer to the user
which code they need to go back and manually split.
This change has no effect on code that does fit in the page width.
Write a trailing comma in split extension type representation clauses when in
a library whose language version allows it (#1845).
Prior to Dart 3.13, extension type representation clauses didn't allow
trailing commas even though they syntactically appear like formal parameter
lists. In Dart 3.13, that was fixed, so now the formatter formats them the
same way as other parameter lists in primary constructors.
analyzer: ^13.1.0.Require analyzer: ^13.0.0
analyzer: ^13.0.0Format extension type representation clauses the same way primary constructor formal parameter lists are formatted. This rarely makes a difference but
// Before:
extension type JSExportedDartFunction._(
JSExportedDartFunctionRepType _jsExportedDartFunction
)
implements JSFunction {}
// After:
extension type JSExportedDartFunction._(
JSExportedDartFunctionRepType _jsExportedDartFunction
) implements JSFunction {}; body:
// Before:
int above;
extension type Inches(int x) {}
mixin M {}
int below;
// After:
int above;
extension type Inches(int x) {}
mixin M {}
int below;;analyzer: '^12.0.0'.Require analyzer: '>=10.0.0 <12.0.0' .
analyzer: '>=10.0.0 <12.0.0'.When trailing commas are preserved, don't insert a newline before the ; in an enum with members unless there actually is a trailing comma. (Fix by @Ba
; insdk: ^3.10.0.Support upcoming Dart language version 3.11.
Remove dependencies on analyzer internal implementation.
analyzer: '^10.0.0'.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
import 'foo.dart' as prefix if (cond) 'bar.dart';? and . if a null-aware element contains aanalyzer: '>=8.2.0 <10.0.0'.args: ^2.5.0.sdk: ^3.9.0.@dart= version comments when determining which >3.7 style to apply.Update to the latest package:analyzer.
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.)
Update to latest analyzer and enable language version 3.9.
This release contains a fairly large number of style changes in response to feedback we got from shipping the new tall style formatter.
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,
);
Handle trailing commas in for-loop updaters (#1354).
|| 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 implement
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.
Nothing published for this version
Allow passing a language version to DartFomatter(). Formatted code will be parsed at that version. If omitted, defaults to the latest version. In a fu
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.Fix compile error when using dart_style with analyzer 6.2.0.
Ensure switch expressions containing line comments split (#1404).
3.3 to parse so that code with extension types can be
formatted.macro modifier when the macros experiment flag
is passed.Add tall-style experiment flag to enable the in-progress unstable new formatting style (#1253).
tall-style experiment flag to enable the in-progress unstable new
formatting style (#1253).Always split enum declarations containing a line comment (#1254).
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.Don't indent parameters that have metadata annotations. Instead, align them with the metadata and other parameters.
. following a record literal (#1213).package:analyzer >=5.12.0 <7.0.0.? on nullable empty record types (#1224).Hide --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
--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.Format patterns and related features.
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.* Format unnamed libraries. * Require Dart 2.17.
Nothing published for this version
Unify how brace-delimited syntax is formatted. This is mostly an internal refactoring, but slightly changes how a type body containing only an inline
{ 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.Allow the latest version of package:analyzer.
package:analyzer.Format named arguments anywhere (#1072).
Require package:analyzer version 2.6.0.
package:analyzer version 2.6.0.NamedType instead of TypeName.Fix analyzer dependency constraint (#1051).
Republish 2.0.3 as 2.1.1 in order to avoid users getting 2.1.0, which has a bad dependency constraint (#1051).
Support generic function references and constructor tear-offs (#1028).
Fix hang when reading from stdin (https://github.com/dart-lang/sdk/issues/46600).
Don't unnecessarily split argument lists with /* */ comments (#837).
/* */ comments (#837).FormatCommand when formatting stdin (#1035).package:analyzer.Support triple-shift >>> and >>>= operators (#992).
>>> and >>>= operators (#992).required (#1010).* Migrate to null safety.
Add support for generic annotations.
FormatCommand.run() now returns the value set in exitCode during
formatting.Allow the latest version of package:analyzer.
package:analyzer.Allow the latest versions of package:args and package:pub_semver.
package:args and package:pub_semver.Remove use of deprecated analyzer API and List constructor.
* Allow analyzer version 0.41.x.
Don't duplicate comments on chained if elements (#966).
Preserve ? in initializing formal function-typed parameters (#960).
? in initializing formal function-typed parameters (#960).Nothing published for this version
Split help into verbose and non-verbose lists (#938).
?:) when they are nested (#927).external and abstract fields and variables (#946).Change the path used in error messages when reading from stdin from " " to "stdin". The former crashes on Windows since it is not a valid Windows path
--stdin-name=<stdin>.Restore command line output accidentally removed in 1.3.4.
Add --fix-single-cascade-statements.
--fix-single-cascade-statements.var in --fix-function-typedefs (#826).?.[] to ?[].Support package:analyzer 0.39.0.
package:analyzer 0.39.0.Restore the code that publishes the dart-style npm package.
Fix crash in formatting complex method chains (#855).
Add support for formatting extension methods (#830).
? in types.late modifier.required modifier.. when the target is parenthesized (#704).Format null assertion operators.
package:analyzer 0.38.0.Support package:analyzer 0.37.0.
package:analyzer 0.37.0.Better indentation of function expressions inside trailing comma argument lists. (Thanks a14@!)
Improve indentation of adjacent strings inside => functions.
=> functions.Properly format trailing commas in assertions.
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.
Add support for spreads inside collections (#778).
if and for elements inside collections (#779).Your coding agent can read these notes before it upgrades. Set up the MCP server →