diff --git a/CODE_STYLE.md b/CODE_STYLE.md new file mode 100644 index 00000000..82eb1115 --- /dev/null +++ b/CODE_STYLE.md @@ -0,0 +1,187 @@ +# Code style + +This is a description of a coding style that every contributor **must** follow. +Please, read the whole document before you start pushing code. + +## Generics + +All trait bounds should be written in `where`: + +```rust +// GOOD +pub fn new(user_id: i32, name: N, title: T, png_sticker: P, emojis: E) -> Self +where + N: Into, + T: Into, + P: Into, + E: Into, +{ ... } + +// BAD +pub fn new, + T: Into, + P: Into, + E: Into> + (user_id: i32, name: N, title: T, png_sticker: P, emojis: E) -> Self { ... } +``` + +```rust +// GOOD +impl Trait for Wrap +where + T: Trait +{ ... } + +// BAD +impl Trait for Wrap { ... } +``` + +## Use `Self` where possible + +When referring to the type for which block is implemented, prefer using `Self`, rather than the name of the type: + +```rust +impl ErrorKind { + // GOOD + fn print(&self) { + Self::Io => println!("Io"), + Self::Network => println!("Network"), + Self::Json => println!("Json"), + } + + // BAD + fn print(&self) { + ErrorKind::Io => println!("Io"), + ErrorKind::Network => println!("Network"), + ErrorKind::Json => println!("Json"), + } +} +``` + +```rust +impl<'a> AnswerCallbackQuery<'a> { + // GOOD + fn new(bot: &'a Bot, callback_query_id: C) -> Self + where + C: Into, + { ... } + + // BAD + fn new(bot: &'a Bot, callback_query_id: C) -> AnswerCallbackQuery<'a> + where + C: Into, + { ... } +} +``` + +**Rationale:** `Self` is generally shorter and it's easier to copy-paste code or rename the type. + +## Deriving traits (apply only to libraries) + +Derive `Debug`, `Clone`, `Copy`, `PartialEq`, `Eq` and `Hash` for public types when possible (in this order). + +**Rationale:** these traits can be useful for users and can be implemented for most types. + +Derive `Default` when there is a reasonable default value for the type. + +## Full paths for logging + +Always write `tracing::!(...)` instead of importing `use tracing::;` and invoking `!(...)`. + +```rust +// GOOD +tracing::warn!("Everything is on fire"); + +// BAD +use tracing::warn; + +warn!("Everything is on fire"); +``` + +**Rationale:** +- Less polluted import blocks +- Uniformity + +## `&str` -> `String` conversion + +Prefer using `.to_string()` or `.to_owned()`, rather than `.into()`, `String::from`, etc. + +**Rationale:** uniformity, intent clarity. + +## Order of imports + +```rust +// First core, alloc and/or std +use core::fmt; +use std::{...}; + +// Second, external crates (both crates.io crates and other rust-analyzer crates). +use crate_foo::{ ... }; +use crate_bar::{ ... }; + +// If applicable, the current sub-modules +mod x; +mod y; + +// Finally, the internal crate modules and submodules +use crate::{}; +use super::{}; + +// Re-exports are treated as item definitions rather than imports, so they go +// after imports and modules. Use them sparingly. +pub use crate::x::Z; +``` + +## Import Style + +When implementing traits from `core::fmt`/`std::fmt` import the module: + +```rust +// GOOD +use core::fmt; + +impl fmt::Display for RenameError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { .. } +} + +// BAD +impl core::fmt::Display for RenameError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { .. } +} +``` + +## If-let + +Avoid the `if let ... { } else { }` construct if possible, use `match` instead: + +```rust +// GOOD +match ctx.expected_type.as_ref() { + Some(expected_type) => completion_ty == expected_type && !expected_type.is_unit(), + None => false, +} + +// BAD +if let Some(expected_type) = ctx.expected_type.as_ref() { + completion_ty == expected_type && !expected_type.is_unit() +} else { + false +} +``` + +Use `if let ... { }` when a match arm is intentionally empty: + +```rust +// GOOD +if let Some(expected_type) = this.as_ref() { + // Handle it +} + +// BAD +match this.as_ref() { + Some(expected_type) => { + // Handle it + }, + None => (), +} +``` diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..547421e7 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,9 @@ +tab_spaces = 4 +newline_style = "Auto" +reorder_imports = true +reorder_modules = true +reorder_impl_items = false +indent_style = "Block" +normalize_comments = false +imports_granularity = "Module" +group_imports = "StdExternalCrate"