-
Notifications
You must be signed in to change notification settings - Fork 121
Formatting rules
The canonical source of truth for the logic dartfmt applies is in the code. The rules can be complex and interact in subtle ways that makes them difficult or just tedious to capture in prose. (Do you really want to know the three different ways a show
clause may be line-split? No, you probably don't.)
But if you want an approximate list of the main high-level whitespace rules the formatter applies, these are them:
Using spaces for formatting ensures the code looks the same in everyone's editor. It also makes sure it looks the same when posted to blogs, or on code sites like GitHub.
Modern editors emulate the behavior of tabs while inserting spaces, giving you the easy editing of tabs and the consistency of spaces.
main() {
first(statement);
second(statement);
third(statement);
}
anotherDeclaration() { ... }
log(arg) { ... }
bool operator ==(other) => ...
set contents(value) { ... }
bool operator ==(other) => ...
Note that <
and >
are considered binary operators when used as expressions,
but not for specifying generic types. Both is
and is!
are considered single
binary operators. However, the .
used to access members is not and should
not have spaces around it.
average = (a + b) / 2;
largest = a > b ? a : b;
if (obj is! SomeType) print('not SomeType');
function(a, b, named: c)
[some, list, literal]
{map: literal}
!condition
index++
for (var i = 0; i < 100; i++) { ... }
for (final item in collection) { ... }
This is unlike function and method calls, which do not have a space between the name and the opening parenthesis.
while (foo) { ... }
try {
// ...
} catch (e) {
// ...
}
Also, do not use a space when using <
and >
for generic types.
var numbers = <int>[1, 2, (3 + 4)];
When a {
is used after a parameter list in a function or method, there should
be a space between it and the )
ending the parameters.
getEmptyFn(a) {
return () {};
}
class Foo {
method() {
if (someCondition) {
// ...
} else {
// ...
}
}
}
There are valid arguments for both styles but most of our code seems to go this way, and consistency matters most.
var bobLikesIt = isDeepFried ||
(hasPieCrust && !vegan) ||
containsBacon;
bobLikes() =>
isDeepFried || (hasPieCrust && !vegan) || containsBacon;
Also, if you break the line before one of the operators, break around both.
return someCondition
? whenTrue
: whenFalse;
someVeryLongVariableName.withAVeryLongPropertyName
.aReallyLongMethodName(args);
MyClass()
: firstField = 'some value',
secondField = 'another',
thirdField = 'last' {
// ...
}
Note that the :
should be wrapped to the next line and indented four spaces.
Fields should all line up (so all but the first field end up indented six
spaces).
This means after the opening bracket, before the closing one, and after the ,
for each element.
mapInsideList([
{
'a': 'b',
'c': 'd'
},
{
'a': 'b',
'c': 'd'
},
]);
if (condition) {
print('hi');
}
var compoundsWithLongNames = [
buckminsterfullerene,
dodecahedrane,
olympiadane
];
switch (fruit) {
case 'apple':
print('delish');
break;
case 'durian':
print('stinky');
break;
}
buffer
..write('Hello, ')
..write(name)
..write('!');
someVeryLongVariableName.aReallyLongMethodName(
arg, anotherArg, wrappedToNextLine);
This includes =>
as well:
bobLikes() =>
isDeepFried || (hasPieCrust && !vegan) || containsBacon;
There are exceptions to this when the expression contains multi-line function or collection literals.
new Future.delayed(const Duration(seconds: 1), () {
print('I am a callback');
});
args.addAll([
'--mode',
'release',
'--checked'
]);
Your goal is to balance using indentation to show expression structure while not wanting to indent large swathes of code unnecessarily.