Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit c7667fd

Browse files
authored
Re-land #52859: Revamp the engine style guide, remove always_specify_types (#53223)
Based on the (internal) discussion around converging on using the official Dart style guide, the design discussion https://flutter.dev/go/use-dart-style-in-flutter-engine, and with the exception of the code that gets published under `dart:ui` (as that is user-facing, and we'd like to evolve the code style in conjunction with the framework), we're going to be (gradually) adopting the Dart style guide in `flutter/engine`. For now, we: - Remove `always_specify_types` (except for `lib/ui`, i.e. `dart:ui`) - Re-enable `type_annotate_public_apis` (which is now relevant since the above is disabled) - Announce our _intent_ to re-format and apply the Dart formatter (which we'll land in the near future) --- I also took the opportunity to specify more about our style guide use in general, mostly to make it easier to understand our conventions, and also call out known problem areas (notably, our over-use of `shared_ptr` and `auto` in some cases). I am happy to split those up, but it was easier to make the markdown changes at once. I also took @cbracken and folks advice and clarified directly that explicit types in Dart are _not_ bad (with examples).
1 parent d79239e commit c7667fd

File tree

3 files changed

+173
-19
lines changed

3 files changed

+173
-19
lines changed

CONTRIBUTING.md

Lines changed: 170 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,182 @@ contributing guide.
1414

1515
## Style
1616

17-
The Flutter engine follows Google style for the languages it uses:
18-
19-
- [C++](https://google.github.io/styleguide/cppguide.html)
20-
- **Note**: The Linux embedding generally follows idiomatic GObject-based C
21-
style. Use of C++ is discouraged in that embedding to avoid creating hybrid
22-
code that feels unfamiliar to either developers used to working with
23-
`GObject` or C++ developers. For example, do not use STL collections or
24-
`std::string`. Exceptions:
25-
- C-style casts are forbidden; use C++ casts.
26-
- Use `nullptr` rather than `NULL`.
27-
- Avoid `#define`; for internal constants use `static constexpr` instead.
28-
- [Objective-C][objc_style] (including [Objective-C++][objcc_style])
29-
- [Java][java_style]
30-
31-
C/C++ and Objective-C/C++ files are formatted with `clang-format`, and GN files
32-
with `gn format`.
17+
The Flutter engine _generally_ follows Google style for the languages it uses,
18+
with some exceptions.
3319

20+
### C/C++
21+
22+
Follows the [Google C++ Style Guide][google_cpp_style] and is automatically
23+
formatted with `clang-format`.
24+
25+
Some additional considerations that are in compliance with the style guide, but
26+
are worth noting:
27+
28+
#### Judiciously use shared_ptr
29+
30+
The engine currently (as of 2024-05-15) uses `shared_ptr` liberally, which can
31+
be expensive to copy, and is not always necessary.
32+
33+
The C++ style guide has a
34+
[section on ownership and smart pointers][cpp_ownership] worth reading:
35+
36+
> Do not design your code to use shared ownership without a very good reason.
37+
> One such reason is to avoid expensive copy operations, but you should only do
38+
> this if the performance benefits are significant, and the underlying object is
39+
> immutable.
40+
41+
Prefer using `std::unique_ptr` when possible.
42+
43+
#### Judiciously use `auto`
44+
45+
The C++ style guide has a [section on type deduction][cpp_auto] that is worth
46+
reading:
47+
48+
> The fundamental rule is: use type deduction only to make the code clearer or
49+
> safer, and do not use it merely to avoid the inconvenience of writing an
50+
> explicit type. When judging whether the code is clearer, keep in mind that
51+
> your readers are not necessarily on your team, or familiar with your project,
52+
> so types that you and your reviewer experience as unnecessary clutter will
53+
> very often provide useful information to others. For example, you can assume
54+
> that the return type of `make_unique<Foo>()` is obvious, but the return type
55+
> of `MyWidgetFactory()` probably isn't.
56+
57+
Due to our codebase's extensive use of `shared_ptr`, `auto` can have surprising
58+
performance implications. See [#49801][pr_49801] for an example.
59+
60+
#### Linux Embedding
61+
62+
> [!NOTE]
63+
> The Linux embedding instead follows idiomatic GObject-based C style.
64+
65+
Use of C++ in the [Linux embedding][] is discouraged in that embedding to avoid
66+
creating hybrid code that feels unfamiliar to either developers used to working
67+
with `GObject` or C++ developers.
68+
69+
For example, _do not_ use STL collections or `std::string`, but _do_:
70+
71+
- Use C++ casts (C-style casts are forbidden).
72+
- Use `nullptr` rather than `NULL`.
73+
- Avoid `#define`; for internal constants use `static constexpr` instead.
74+
75+
### Dart
76+
77+
The Flutter engine _intends_ to follow the [Dart style guide][dart_style] but
78+
currently follows the [Flutter style guide][flutter_style], with the following
79+
exceptions:
80+
81+
#### Use of type inference is allowed
82+
83+
The [Dart style guide][dart_inference] only requires explicit types when type
84+
inference is not possible, but the Flutter style guide always requires explicit
85+
types. The engine is moving towards the Dart style guide, but this is a gradual
86+
process. In the meantime, follow these guidelines:
87+
88+
- **Always** annotate when inference is not possible.
89+
- **Prefer** annotating when inference is possible but the type is not
90+
obvious.
91+
92+
Some cases when using `var`/`final`/`const` is appropriate:
93+
94+
- When the type is obvious from the right-hand side of the assignment:
95+
96+
```dart
97+
// Capitalized constructor name always returns a Foo.
98+
var foo = Foo();
99+
100+
// Similar with factory constructors.
101+
var bar = Bar.create();
102+
103+
// Literals (strings, numbers, lists, maps, etc) always return the same type.
104+
var name = 'John Doe';
105+
var flag = true;
106+
var numbers = [1, 2, 3];
107+
var map = {'one': 1, 'two': 2, 'three': 3};
108+
```
109+
110+
- When the type is obvious from the method name:
111+
112+
```dart
113+
// toString() always returns a String.
114+
var string = foo().toString();
115+
116+
// It's reasonable to assume that length returns an int.
117+
var length = string.length;
118+
```
119+
120+
- When the type is obvious from the context:
121+
122+
```dart
123+
// When variables are in the same scope, reduce() clearly returns an int.
124+
var list = [1, 2, 3];
125+
var sum = list.reduce((a, b) => a + b);
126+
```
127+
128+
Some cases where an explicit type should be considered:
129+
130+
- When the type is not obvious from the right-hand side of the assignment:
131+
132+
```dart
133+
// What does 'fetchLatest()' return?
134+
ImageBuffer buffer = fetchLatest();
135+
136+
// What does this large chain of method calls return?
137+
Iterable<int> numbers = foo().bar().map((b) => b.baz());
138+
```
139+
140+
- When there are semantic implications to the type:
141+
142+
```dart
143+
// Without 'num', the map would be inferred as 'Map<String, int>'.
144+
const map = <String, num>{'one': 1, 'two': 2, 'three': 3};
145+
```
146+
147+
- Or, **when a reviewer requests it**!
148+
149+
Remember that the goal is to make the code more readable and maintainable, and
150+
explicit types _can_ help with that. Code can be changed, so it's always
151+
possible to add or remove type annotations later as the code evolves, so avoid
152+
bikeshedding over this.
153+
154+
### Java
155+
156+
Follows the [Google Java Style Guide][java_style] and is automatically formatted
157+
with `google-java-format`.
158+
159+
### Objective-C
160+
161+
Follows the [Google Objective-C Style Guide][objc_style], including for
162+
Objective-C++ and is automatically formatted with `clang-format`.
163+
164+
### Python
165+
166+
Follows the [Google Python Style Guide][google_python_style] and is
167+
automatically formatted with `yapf`.
168+
169+
> [!WARNING]
170+
> Historically, the engine grew a number of one-off Python scripts, often as
171+
> part of the testing or build infrastructure (i.e. command-line tools). We are
172+
> instead moving towards using Dart for these tasks, so new Python scripts
173+
> should be avoided whenever possible.
174+
175+
### GN
176+
177+
Automatically formatted with `gn format`.
178+
179+
[cpp_auto]: https://google.github.io/styleguide/cppguide.html#Type_deduction
180+
[cpp_ownership]: https://google.github.io/styleguide/cppguide.html#Ownership_and_Smart_Pointers
181+
[dart_inference]: https://dart.dev/effective-dart/design#types
182+
[dart_style]: https://dart.dev/effective-dart/style
183+
[linux embedding]: shell/platform/linux
184+
[google_cpp_style]: https://google.github.io/styleguide/cppguide.html
185+
[pr_49801]: https://github.com/flutter/engine/pull/49801
34186
[code_of_conduct]: https://github.com/flutter/flutter/blob/master/CODE_OF_CONDUCT.md
35187
[contrib_guide]: https://github.com/flutter/flutter/blob/master/CONTRIBUTING.md
36188
[engine_dev_setup]: https://github.com/flutter/flutter/blob/master/docs/engine/contributing/Setting-up-the-Engine-development-environment.md
189+
[flutter_style]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
37190
[objc_style]: https://google.github.io/styleguide/objcguide.html
38-
[objcc_style]: https://google.github.io/styleguide/objcguide.html#objective-c
39191
[java_style]: https://google.github.io/styleguide/javaguide.html
192+
[google_python_style]: https://google.github.io/styleguide/pyguide.html
40193

41194
## Testing
42195

analysis_options.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ linter:
2929
- always_declare_return_types
3030
- always_put_control_body_on_new_line
3131
# - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219
32-
- always_specify_types
32+
# - always_specify_types # DIFFERENT FROM FLUTTER/FLUTTER; see https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#dart
3333
# - always_use_package_imports # we do this commonly
3434
- annotate_overrides
3535
# - avoid_annotating_with_dynamic # conflicts with always_specify_types
@@ -191,7 +191,7 @@ linter:
191191
- test_types_in_equals
192192
- throw_in_finally
193193
- tighten_type_of_initializing_formals
194-
# - type_annotate_public_apis # subset of always_specify_types
194+
- type_annotate_public_apis # DIFFERENT FROM FLUTTER/FLUTTER; this repo disable always_specify_types (https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#dart)
195195
- type_init_formals
196196
- type_literal_in_constant_pattern
197197
# - unawaited_futures # too many false positives, especially with the way AnimationController works

lib/ui/analysis_options.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ analyzer:
77

88
linter:
99
rules:
10+
always_specify_types: true # dart:ui is shipped as part of flutter/flutter, let's keep them consistent for now
1011
unreachable_from_main: false # lint not compatible with how dart:ui is structured

0 commit comments

Comments
 (0)