diff options
Diffstat (limited to 'docs/dev/style.md')
-rw-r--r-- | docs/dev/style.md | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/docs/dev/style.md b/docs/dev/style.md index c594946be..6ab60b50e 100644 --- a/docs/dev/style.md +++ b/docs/dev/style.md | |||
@@ -53,9 +53,9 @@ https://www.tedinski.com/2018/02/06/system-boundaries.html | |||
53 | ## Crates.io Dependencies | 53 | ## Crates.io Dependencies |
54 | 54 | ||
55 | We try to be very conservative with usage of crates.io dependencies. | 55 | We try to be very conservative with usage of crates.io dependencies. |
56 | Don't use small "helper" crates (exception: `itertools` is allowed). | 56 | Don't use small "helper" crates (exception: `itertools` and `either` are allowed). |
57 | If there's some general reusable bit of code you need, consider adding it to the `stdx` crate. | 57 | If there's some general reusable bit of code you need, consider adding it to the `stdx` crate. |
58 | A useful exercise is to read Cargo.lock and see if some of the *transitive* dependencies do not make sense for rust-analyzer. | 58 | A useful exercise is to read Cargo.lock and see if some *transitive* dependencies do not make sense for rust-analyzer. |
59 | 59 | ||
60 | **Rationale:** keep compile times low, create ecosystem pressure for faster compiles, reduce the number of things which might break. | 60 | **Rationale:** keep compile times low, create ecosystem pressure for faster compiles, reduce the number of things which might break. |
61 | 61 | ||
@@ -83,8 +83,19 @@ This makes it easier to prepare a changelog. | |||
83 | 83 | ||
84 | If the change adds a new user-visible functionality, consider recording a GIF with [peek](https://github.com/phw/peek) and pasting it into the PR description. | 84 | If the change adds a new user-visible functionality, consider recording a GIF with [peek](https://github.com/phw/peek) and pasting it into the PR description. |
85 | 85 | ||
86 | To make writing the release notes easier, you can mark a pull request as a feature, fix, internal change, or minor. | ||
87 | Minor changes are excluded from the release notes, while the other types are distributed in their corresponding sections. | ||
88 | There are two ways to mark this: | ||
89 | |||
90 | * use a `feat: `, `feature: `, `fix: `, `internal: ` or `minor: ` prefix in the PR title | ||
91 | * write `changelog [feature|fix|internal|skip] [description]` in a comment or in the PR description; the description is optional, and will replace the title if included. | ||
92 | |||
93 | These comments don't have to be added by the PR author. | ||
94 | Editing a comment or the PR description or title is also fine, as long as it happens before the release. | ||
95 | |||
86 | **Rationale:** clean history is potentially useful, but rarely used. | 96 | **Rationale:** clean history is potentially useful, but rarely used. |
87 | But many users read changelogs. | 97 | But many users read changelogs. |
98 | Including a description and GIF suitable for the changelog means less work for the maintainers on the release day. | ||
88 | 99 | ||
89 | ## Clippy | 100 | ## Clippy |
90 | 101 | ||
@@ -152,6 +163,16 @@ Do not reuse marks between several tests. | |||
152 | 163 | ||
153 | **Rationale:** marks provide an easy way to find the canonical test for each bit of code. | 164 | **Rationale:** marks provide an easy way to find the canonical test for each bit of code. |
154 | This makes it much easier to understand. | 165 | This makes it much easier to understand. |
166 | More than one mark per test / code branch doesn't add significantly to understanding. | ||
167 | |||
168 | ## `#[should_panic]` | ||
169 | |||
170 | Do not use `#[should_panic]` tests. | ||
171 | Instead, explicitly check for `None`, `Err`, etc. | ||
172 | |||
173 | **Rationale:** `#[should_panic]` is a tool for library authors, to makes sure that API does not fail silently, when misused. | ||
174 | `rust-analyzer` is not a library, we don't need to test for API misuse, and we have to handle any user input without panics. | ||
175 | Panic messages in the logs from the `#[should_panic]` tests are confusing. | ||
155 | 176 | ||
156 | ## Function Preconditions | 177 | ## Function Preconditions |
157 | 178 | ||
@@ -330,7 +351,7 @@ When implementing `do_thing`, it might be very useful to create a context object | |||
330 | 351 | ||
331 | ```rust | 352 | ```rust |
332 | pub fn do_thing(arg1: Arg1, arg2: Arg2) -> Res { | 353 | pub fn do_thing(arg1: Arg1, arg2: Arg2) -> Res { |
333 | let mut ctx = Ctx { arg1, arg2 } | 354 | let mut ctx = Ctx { arg1, arg2 }; |
334 | ctx.run() | 355 | ctx.run() |
335 | } | 356 | } |
336 | 357 | ||
@@ -586,7 +607,7 @@ use super::{} | |||
586 | 607 | ||
587 | **Rationale:** consistency. | 608 | **Rationale:** consistency. |
588 | Reading order is important for new contributors. | 609 | Reading order is important for new contributors. |
589 | Grouping by crate allows to spot unwanted dependencies easier. | 610 | Grouping by crate allows spotting unwanted dependencies easier. |
590 | 611 | ||
591 | ## Import Style | 612 | ## Import Style |
592 | 613 | ||
@@ -779,7 +800,7 @@ assert!(x < y); | |||
779 | assert!(x > 0); | 800 | assert!(x > 0); |
780 | 801 | ||
781 | // BAD | 802 | // BAD |
782 | assert!(x >= lo && x <= hi>); | 803 | assert!(x >= lo && x <= hi); |
783 | assert!(r1 < l2 || l1 > r2); | 804 | assert!(r1 < l2 || l1 > r2); |
784 | assert!(y > x); | 805 | assert!(y > x); |
785 | assert!(0 > x); | 806 | assert!(0 > x); |
@@ -842,7 +863,26 @@ Re-using originally single-purpose function often leads to bad coupling. | |||
842 | 863 | ||
843 | ## Helper Variables | 864 | ## Helper Variables |
844 | 865 | ||
845 | Introduce helper variables freely, especially for multiline conditions. | 866 | Introduce helper variables freely, especially for multiline conditions: |
867 | |||
868 | ```rust | ||
869 | // GOOD | ||
870 | let rustfmt_not_installed = | ||
871 | captured_stderr.contains("not installed") || captured_stderr.contains("not available"); | ||
872 | |||
873 | match output.status.code() { | ||
874 | Some(1) if !rustfmt_not_installed => Ok(None), | ||
875 | _ => Err(format_err!("rustfmt failed:\n{}", captured_stderr)), | ||
876 | }; | ||
877 | |||
878 | // BAD | ||
879 | match output.status.code() { | ||
880 | Some(1) | ||
881 | if !captured_stderr.contains("not installed") | ||
882 | && !captured_stderr.contains("not available") => Ok(None), | ||
883 | _ => Err(format_err!("rustfmt failed:\n{}", captured_stderr)), | ||
884 | }; | ||
885 | ``` | ||
846 | 886 | ||
847 | **Rationale:** like blocks, single-use variables are a cognitively cheap abstraction, as they have access to all the context. | 887 | **Rationale:** like blocks, single-use variables are a cognitively cheap abstraction, as they have access to all the context. |
848 | Extra variables help during debugging, they make it easy to print/view important intermediate results. | 888 | Extra variables help during debugging, they make it easy to print/view important intermediate results. |