26738fe09d
Change-Id: I15e3b9f8867de3ef651e844cc474119d6c3aea81 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/454323 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Samuel Rawlins <srawlins@google.com>
191 lines
7.8 KiB
Markdown
191 lines
7.8 KiB
Markdown
# Coding style
|
|
|
|
This document is a place to record information about the coding style that's
|
|
currently being used by the Dash Developer Experience team for some static
|
|
analysis packages (the `analysis_server`, `analysis_server_plugin`,
|
|
`analyzer_plugin`, `analyzer_testing`, `analyzer_utilities`, and `linter`
|
|
packages). As such, it's subject to change as the language evolves and as our
|
|
experience dictates.
|
|
|
|
Note that the `analyzer` package is developed by the Dart Model team, which
|
|
follows a different coding style. The `analyzer_testing` and
|
|
`analyzer_utilities` packages are developed jointly between the Dart Model and
|
|
Dash Developer Experience teams.
|
|
|
|
The document is divided into three main sections covering the coding styles we
|
|
- have decided to follow,
|
|
- are currently discussing, and
|
|
- have decided not to enforce.
|
|
|
|
Our goal is to make as much as possible of the style be automatically enforced,
|
|
either through lints or tests, but this document also includes style choices
|
|
that can't reasonably be enforced automatically.
|
|
|
|
## Styles we're following
|
|
|
|
This section documents the styles we have agreed to follow.
|
|
|
|
### Effective Dart
|
|
|
|
We follow the styles laid out by [Effective Dart][effective dart], the Dart style
|
|
guide, unless otherwise noted below. Most of the rules in Effective Dart have
|
|
lint rules that keep us honest, but not all.
|
|
|
|
### Lint rules
|
|
|
|
- [`flutter_style_todos`][] - Keeps our todo format canonical.
|
|
- [`prefer_single_quotes`][] - We don't enforce this in each of our packages yet, but
|
|
we aspire to.
|
|
- [`unnecessary_breaks`][] - All our packages require at least Dart `3.0.0`, so we
|
|
can do it.
|
|
- [`use_null_aware_elements`][] - All our packages require at least Dart `3.8.0`, so
|
|
we can do it, and benefit from the more concise syntax.
|
|
|
|
[`flutter_style_todos`]: https://dart.dev/tools/linter-rules/flutter_style_todos
|
|
[`prefer_single_quotes`]: https://dart.dev/tools/linter-rules/prefer_single_quotes
|
|
[`unnecessary_breaks`]: https://dart.dev/tools/linter-rules/unnecessary_breaks
|
|
[`use_null_aware_elements`]: https://dart.dev/tools/linter-rules/use_null_aware_elements
|
|
|
|
### Formatting and sorting
|
|
|
|
All of our source code is expected to be
|
|
- formatted by the `dart format` command, and
|
|
- sorted according to the Sort Members command (available in IDEs).
|
|
|
|
(With the exception that we don't sort in either the `dartdoc` or `markdown`
|
|
packages.)
|
|
|
|
Formatting is enforced by presubmit and sorting is enforced by tests. We
|
|
recommend that you enable both the formatter and the Sort Members command to be
|
|
run on save, at least within our packages.
|
|
|
|
### Naming conventions
|
|
|
|
We generally follow the naming conventions from the Dart style guide. We do
|
|
have some legacy code that uses screaming caps for constant names, but newer
|
|
code doesn't use that style.
|
|
|
|
#### Import prefixes
|
|
|
|
The Dart style guide doesn't explicitly specify a naming convention for import
|
|
prefixes beyond the guidance to use snake case. (See [DO name import prefixes
|
|
using lowercase_with_underscores][do name import prefixes].)
|
|
|
|
[effective dart]: https://dart.dev/effective-dart
|
|
[do name import prefixes]: https://dart.dev/effective-dart/style#do-name-import-prefixes-using-lowercase_with_underscores
|
|
|
|
However, the examples in the Dart style guide all use the name of the file with
|
|
the `.dart` suffix removed. That's the standard we follow, with the exception
|
|
that we also drop `_test.dart` for test files. That includes using the prefix
|
|
`path` for the path package, even though it's a commonly used variable name. In
|
|
code where there would be a conflict, we prefix the variable name with a
|
|
qualifying noun to form a unique name, such as `filePath`.
|
|
|
|
#### Extensions
|
|
|
|
Public extensions (which are intended to be accessible outside their declaring
|
|
library) are named in a consistent style. An extension on a type `Foo` is
|
|
named `FooExtension`. An extension on a nullable type `Foo?` uses the word
|
|
"Nullable" in place of the question mark, like `FooNullableExtension`. While
|
|
this can lead to long names (like `AnalysisOptionsImplExtension`), the
|
|
extension name is rarely used (only in explicit extension overrides), and we
|
|
value consistency.
|
|
|
|
### Modifier usage
|
|
|
|
#### Local variables
|
|
|
|
We use `var` to declare local variables with two exceptions:
|
|
|
|
- We use a type annotation if the type of the variable would be incorrectly
|
|
inferred without it, such as when a variable that needs to be nullable would
|
|
be inferred to be non-nullable because it's initialized to a non-null value.
|
|
|
|
- We use `final` if the local variable shadows a field and is being used to
|
|
allow the type of the field to be promoted.
|
|
|
|
The reason to prefer `var` over `final` is that the majority of the team felt
|
|
that the benefit of using `var` was slightly greater than the benefit of
|
|
using `final`.
|
|
|
|
## Styles we're discussing
|
|
|
|
This section documents the styles we are currently discussing. The purpose
|
|
is to capture the state of the discussions so that we don't forget what we've
|
|
already discussed.
|
|
|
|
### Lint rules
|
|
|
|
For historic reasons we have enabled some of the lint rules in the [core][core]
|
|
and [recommended][recommended] rule sets, but some have been disabled in various
|
|
packages.
|
|
|
|
[core]:https://github.com/dart-lang/lints/blob/main/lib/core.yaml
|
|
[recommended]:https://github.com/dart-lang/lints/blob/main/lib/recommended.yaml
|
|
|
|
In addition, there are lint rules outside those sets that are enabled in some
|
|
packages but not in all packages.
|
|
|
|
All of these lint rules need to be discussed, and descriptions will be added as
|
|
discussions occur.
|
|
|
|
### Other style guidelines
|
|
|
|
#### No new null-asserts
|
|
|
|
There is a proposal to disallow any new uses of the unary null-assert operator
|
|
(`!`). Use of the operator is generally undesirable because if the value of the
|
|
operand is `null` an exception will be thrown.
|
|
|
|
The biggest concern is with the fact that we have some nullable properties that
|
|
can't be made non-nullable (because of limitations in the type system) but that
|
|
are known to be non-nullable in practice. The most obvious examples of this are
|
|
`Token.next` and `Token.previous`. We routinely use the null-assert operator in
|
|
those cases.
|
|
|
|
A similar case is `Expression.staticType` where we know that the type will be
|
|
non-null after resolution, but there we've wrapped the null check in an
|
|
extension getter named `typeOrThrow`. We could use this as a convention to
|
|
signal that we've decided that the possibility of an exception is rare.
|
|
|
|
It has also been suggested that it might be better, however, to just use `!` to
|
|
signal those cases, and to only disallow the operator in cases where we don't
|
|
think the exception will be rare. That might have the advantage of making the
|
|
presence of the check (and possibility of an exception) more explicit in the
|
|
code.
|
|
|
|
We might want to allow this in tests, where the null-assert becomes another form
|
|
of expectation.
|
|
|
|
#### No new type casts
|
|
|
|
There is a proposal to disallow any new uses of type casts, with two exceptions:
|
|
when using `covariant` and where there isn't any other reasonable way.
|
|
|
|
There's concern about using `covariant` other than in places where we know it to
|
|
be safe (for example, the `AstNode` hierarchy is designed in such a way that
|
|
it's safe to use `covariant` if the covariant type is the `Impl` type of the
|
|
overridden method).
|
|
|
|
The second exclusion is not well defined. We probably need to clarify what cases
|
|
we would allow so we know that the style can be consistently applied.
|
|
|
|
There's also speculation that we might want to not impose this restriction in
|
|
test code because using type casts is effectively equivalent to an expectation
|
|
but with the advantage that the type of the variable can be promoted.
|
|
|
|
## Styles we're not following
|
|
|
|
This section documents the styles that we've explicitly decided we're not going
|
|
to follow. For each style there should be a description of why the decision was
|
|
made. The purpose is to know when circumstances have changed enough that it
|
|
might be worth reconsidering.
|
|
|
|
### Lint rules
|
|
|
|
TBD
|
|
|
|
### Other style guidelines
|
|
|
|
TBD
|