Skip to content

Commit a0c0453

Browse files
Style Guide updates (flutter#152525)
This pull request updates the style guide for improved internal consistency and to match current linter rules. I'll make comments for each change here!
1 parent febf4cd commit a0c0453

File tree

1 file changed

+106
-103
lines changed

1 file changed

+106
-103
lines changed

docs/contributing/Style-guide-for-Flutter-repo.md

+106-103
Original file line numberDiff line numberDiff line change
@@ -752,13 +752,13 @@ abstract class RenderBox extends RenderObject {
752752
// more complicated asserts:
753753
assert(() {
754754
final RenderObject parent = this.parent;
755-
if (owner.debugDoingLayout)
756-
return (RenderObject.debugActiveLayout == parent) &&
757-
parent.debugDoingThisLayout;
758-
if (owner.debugDoingPaint)
759-
return ((RenderObject.debugActivePaint == parent) &&
760-
parent.debugDoingThisPaint) ||
761-
((RenderObject.debugActivePaint == this) && debugDoingThisPaint);
755+
if (owner.debugDoingLayout) {
756+
return (RenderObject.debugActiveLayout == parent) && parent.debugDoingThisLayout;
757+
}
758+
if (owner.debugDoingPaint) {
759+
return ((RenderObject.debugActivePaint == parent) && parent.debugDoingThisPaint)
760+
|| ((RenderObject.debugActivePaint == this) && debugDoingThisPaint);
761+
}
762762
assert(parent == this.parent);
763763
return false;
764764
});
@@ -928,8 +928,9 @@ TheType get theProperty => _theProperty;
928928
TheType _theProperty;
929929
void set theProperty(TheType value) {
930930
assert(value != null);
931-
if (_theProperty == value)
931+
if (_theProperty == value) {
932932
return;
933+
}
933934
_theProperty = value;
934935
markNeedsWhatever(); // the method to mark the object dirty
935936
}
@@ -1073,7 +1074,7 @@ const double kParagraphSpacing = 1.5;
10731074
const String kSaveButtonTitle = 'Save';
10741075
```
10751076

1076-
However, where possible avoid global constants. Rather than `kDefaultButtonColor`, consider `Button.defaultColor`. If necessary, consider creating a class with a private constructor to hold relevant constants.
1077+
However, where possible avoid global constants. Rather than `kDefaultButtonColor`, consider `Button.defaultColor`. If necessary, consider creating an `abstract final class` to hold relevant constants.
10771078

10781079

10791080
### Avoid abbreviations
@@ -1249,7 +1250,9 @@ include a link to that issue in the code.
12491250
Generally the closure passed to `setState` should include all the code that changes the state. Sometimes this is not possible because the state changed elsewhere and the `setState` is called in response. In those cases, include a comment in the `setState` closure that explains what the state is that changed.
12501251

12511252
```dart
1252-
setState(() { /* The animation ticked. We use the animation's value in the build method. */ });
1253+
setState(() {
1254+
// The animation ticked. We use the animation's value in the build method.
1255+
});
12531256
```
12541257

12551258

@@ -1328,25 +1331,21 @@ to the superclass.
13281331

13291332
```dart
13301333
// one-line constructor example
1331-
abstract class Foo extends StatelessWidget {
1332-
Foo(this.bar, { Key key, this.child }) : super(key: key);
1333-
final int bar;
1334-
final Widget child;
1334+
class ConstantTween<T> extends Tween<T> {
1335+
ConstantTween(T value) : super(begin: value, end: value);
1336+
13351337
// ...
13361338
}
13371339
13381340
// fully expanded constructor example
1339-
abstract class Foo extends StatelessWidget {
1340-
Foo(
1341-
this.bar, {
1342-
Key key,
1343-
Widget childWidget,
1344-
}) : child = childWidget,
1345-
super(
1346-
key: key,
1347-
);
1348-
final int bar;
1349-
final Widget child;
1341+
class ConstantTween<T> extends Tween<T> {
1342+
ConstantTween(
1343+
T value,
1344+
) : super(
1345+
begin: value,
1346+
end: value,
1347+
);
1348+
13501349
// ...
13511350
}
13521351
```
@@ -1432,8 +1431,6 @@ Example:
14321431
bar,
14331432
baz,
14341433
);
1435-
foo(bar,
1436-
baz);
14371434
```
14381435

14391436
### Use a trailing comma for arguments, parameters, and list items, but only if they each have their own line.
@@ -1453,6 +1450,42 @@ foo1(
14531450
foo2(bar, baz);
14541451
```
14551452

1453+
If one of the items is a multi-line callback, collection literal,
1454+
or switch expression, it can be added without a trailing comma.
1455+
1456+
```dart
1457+
// GOOD:
1458+
foo(
1459+
bar,
1460+
baz,
1461+
switch (value) {
1462+
true => ScrollDirection.forward,
1463+
false => ScrollDirection.reverse,
1464+
null => ScrollDirection.idle,
1465+
},
1466+
);
1467+
1468+
// also GOOD:
1469+
foo(bar, baz, switch (value) {
1470+
true => ScrollDirection.forward,
1471+
false => ScrollDirection.reverse,
1472+
null => ScrollDirection.idle,
1473+
});
1474+
1475+
// The same applies to collection literals and callbacks:
1476+
foo(<String>[
1477+
'list item 1',
1478+
'list item 2',
1479+
'list item 3',
1480+
]);
1481+
1482+
Future.delayed(Durations.short1, () {
1483+
if (mounted && _shouldOpenDrawer) {
1484+
_drawerController.forward();
1485+
}
1486+
});
1487+
```
1488+
14561489
Whether to put things all on one line or whether to have one line per item is an aesthetic choice. We prefer whatever ends up being most readable. Typically this means that when everything would fit on one line, put it all on one line, otherwise, split it one item to a line.
14571490

14581491
However, there are exceptions. For example, if there are six back-to-back lists and all but one of them need multiple lines, then one would not want to have the single case that does fit on one line use a different style than the others.
@@ -1488,17 +1521,6 @@ However, there are exceptions. For example, if there are six back-to-back lists
14881521
];
14891522
```
14901523

1491-
### Prefer single quotes for strings
1492-
1493-
Use double quotes for nested strings or (optionally) for strings that contain single quotes.
1494-
For all other strings, use single quotes.
1495-
1496-
Example:
1497-
1498-
```dart
1499-
print('Hello ${name.split(" ")[0]}');
1500-
```
1501-
15021524

15031525
### Consider using `=>` for short functions and methods
15041526

@@ -1520,14 +1542,49 @@ String capitalize(String s) {
15201542
}
15211543
```
15221544

1523-
### Use `=>` for inline callbacks that just return literals or switch expressions
1545+
### Use `=>` for getters and callbacks that just return literals or switch expressions
1546+
1547+
```dart
1548+
// GOOD:
1549+
List<Color> get favorites => <Color>[
1550+
const Color(0xFF80FFFF),
1551+
const Color(0xFF00FFF0),
1552+
const Color(0xFF4000FF),
1553+
_mysteryColor(),
1554+
];
1555+
1556+
// GOOD:
1557+
bool get isForwardOrCompleted => switch (status) {
1558+
AnimationStatus.forward || AnimationStatus.completed => true,
1559+
AnimationStatus.reverse || AnimationStatus.dismissed => false,
1560+
};
1561+
```
1562+
1563+
It's important to use discretion, since there are cases where a function body
1564+
is easier to visually parse:
1565+
1566+
```dart
1567+
// OKAY, but the code is more dense than it could be:
1568+
String? get validated => switch(input[_inputIndex]?.trim()) {
1569+
final String value when value.isNotEmpty => value,
1570+
_ => null,
1571+
}
15241572
1525-
If your code is passing an inline closure that merely returns a list or
1526-
map literal, or a switch expression, or is merely calling another function,
1527-
then if the argument is on its own line, then rather than using braces and a
1528-
`return` statement, you can instead use the `=>` form. When doing this, the
1529-
closing `]`, `}`, or `)` bracket will line up with the argument name, for
1530-
named arguments, or the `(` of the argument list, for positional arguments.
1573+
// BETTER (more verbose, but also more readable):
1574+
String? get validated {
1575+
final String? value = input[_inputIndex]?.trim();
1576+
1577+
if (value != null && value.isNotEmpty) {
1578+
return value;
1579+
}
1580+
return null;
1581+
}
1582+
```
1583+
1584+
If your code is passing an inline closure containing only a `return` statement,
1585+
you can instead use the `=>` form.\
1586+
When doing this, the closing `]`, `}`, or `)` bracket will have the same
1587+
indentation as the line where the callback starts.
15311588

15321589
For example:
15331590

@@ -1541,11 +1598,11 @@ For example:
15411598
return <PopupMenuItem<String>>[
15421599
PopupMenuItem<String>(
15431600
value: 'Friends',
1544-
child: MenuItemWithIcon(Icons.people, 'Friends', '5 new')
1601+
child: MenuItemWithIcon(Icons.people, 'Friends', '5 new'),
15451602
),
15461603
PopupMenuItem<String>(
15471604
value: 'Events',
1548-
child: MenuItemWithIcon(Icons.event, 'Events', '12 upcoming')
1605+
child: MenuItemWithIcon(Icons.event, 'Events', '12 upcoming'),
15491606
),
15501607
];
15511608
}
@@ -1560,11 +1617,11 @@ For example:
15601617
itemBuilder: (BuildContext context) => <PopupMenuItem<String>>[
15611618
PopupMenuItem<String>(
15621619
value: 'Friends',
1563-
child: MenuItemWithIcon(Icons.people, 'Friends', '5 new')
1620+
child: MenuItemWithIcon(Icons.people, 'Friends', '5 new'),
15641621
),
15651622
PopupMenuItem<String>(
15661623
value: 'Events',
1567-
child: MenuItemWithIcon(Icons.event, 'Events', '12 upcoming')
1624+
child: MenuItemWithIcon(Icons.event, 'Events', '12 upcoming'),
15681625
),
15691626
]
15701627
);
@@ -1666,60 +1723,6 @@ final List<String> args = <String>[
16661723
Use a block (with braces) when a body would wrap onto more than one line (as opposed to using `=>`; the cases where you can use `=>` are discussed in the previous two guidelines).
16671724

16681725

1669-
### Separate the 'if' expression from its statement
1670-
1671-
(This is enforced by the `always_put_control_body_on_new_line` and `curly_braces_in_flow_control_structures` lints.)
1672-
1673-
Don't put the statement part of an 'if' statement on the same line as
1674-
the expression, even if it is short. (Doing so makes it unobvious that
1675-
there is relevant code there. This is especially important for early
1676-
returns.)
1677-
1678-
Example:
1679-
1680-
```dart
1681-
// BAD:
1682-
if (notReady) return;
1683-
1684-
// GOOD:
1685-
// Use this style for code that is expected to be publicly read by developers
1686-
if (notReady) {
1687-
return;
1688-
}
1689-
```
1690-
1691-
If the body is more than one line, or if there is an `else` clause, wrap the body in braces:
1692-
1693-
```dart
1694-
// BAD:
1695-
if (foo)
1696-
bar(
1697-
'baz',
1698-
);
1699-
1700-
// BAD:
1701-
if (foo)
1702-
bar();
1703-
else
1704-
baz();
1705-
1706-
// GOOD:
1707-
if (foo) {
1708-
bar(
1709-
'baz',
1710-
);
1711-
}
1712-
1713-
// GOOD:
1714-
if (foo) {
1715-
bar();
1716-
} else {
1717-
baz();
1718-
}
1719-
```
1720-
1721-
We require bodies to make it very clear where the bodies belong.
1722-
17231726
### Align expressions
17241727

17251728
Where possible, subexpressions on different lines should be aligned, to make the structure of the expression easier. When doing this with a `return` statement chaining `||` or `&&` operators, consider putting the operators on the left hand side instead of the right hand side.

0 commit comments

Comments
 (0)