From c8f27a4a886413a15a2a6af4a87b39b901c873a8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 31 May 2020 01:54:54 +0200 Subject: [PATCH] Generate features docs from source --- crates/ra_ide/src/display/structure.rs | 13 +++ crates/ra_ide/src/extend_selection.rs | 10 ++ crates/ra_ide/src/goto_definition.rs | 9 ++ .../src/{impls.rs => goto_implementation.rs} | 9 ++ crates/ra_ide/src/goto_type_definition.rs | 3 + crates/ra_ide/src/lib.rs | 4 +- crates/ra_ide/src/typing.rs | 7 ++ crates/ra_ide_db/src/symbol_index.rs | 21 ++++ docs/user/features.md | 52 ---------- docs/user/generated_features.adoc | 98 +++++++++++++++++++ docs/user/readme.adoc | 5 +- xtask/src/codegen.rs | 5 +- xtask/src/codegen/gen_feature_docs.rs | 72 ++++++++++++++ xtask/src/main.rs | 1 + xtask/tests/tidy.rs | 7 ++ 15 files changed, 258 insertions(+), 58 deletions(-) rename crates/ra_ide/src/{impls.rs => goto_implementation.rs} (96%) create mode 100644 docs/user/generated_features.adoc create mode 100644 xtask/src/codegen/gen_feature_docs.rs diff --git a/crates/ra_ide/src/display/structure.rs b/crates/ra_ide/src/display/structure.rs index 967eee5d23..3f59b89bb4 100644 --- a/crates/ra_ide/src/display/structure.rs +++ b/crates/ra_ide/src/display/structure.rs @@ -18,6 +18,19 @@ pub struct StructureNode { pub deprecated: bool, } +// Feature: File Structure +// +// Provides a tree of the symbols defined in the file. Can be used to +// +// * fuzzy search symbol in a file (super useful) +// * draw breadcrumbs to describe the context around the cursor +// * draw outline of the file +// +// |=== +// | Editor | Shortcut +// +// | VS Code | kbd:[Ctrl+Shift+O] +// |=== pub fn file_structure(file: &SourceFile) -> Vec { let mut res = Vec::new(); let mut stack = Vec::new(); diff --git a/crates/ra_ide/src/extend_selection.rs b/crates/ra_ide/src/extend_selection.rs index 554594a436..cee0a19e19 100644 --- a/crates/ra_ide/src/extend_selection.rs +++ b/crates/ra_ide/src/extend_selection.rs @@ -14,6 +14,16 @@ use ra_syntax::{ use crate::FileRange; +// Feature: Extend Selection +// +// Extends the current selection to the encompassing syntactic construct +// (expression, statement, item, module, etc). It works with multiple cursors. +// +// |=== +// | Editor | Shortcut +// +// | VS Code | kbd:[Ctrl+Shift+→] +// |=== pub(crate) fn extend_selection(db: &RootDatabase, frange: FileRange) -> TextRange { let sema = Semantics::new(db); let src = sema.parse(frange.file_id); diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 90e85d4197..83ea5092c8 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -17,6 +17,15 @@ use crate::{ FilePosition, NavigationTarget, RangeInfo, }; +// Feature: Go To Definition +// +// Navigates to the definition of an identifier. +// +// |=== +// | Editor | Shortcut +// +// | VS Code | kbd:[F12] +// |=== pub(crate) fn goto_definition( db: &RootDatabase, position: FilePosition, diff --git a/crates/ra_ide/src/impls.rs b/crates/ra_ide/src/goto_implementation.rs similarity index 96% rename from crates/ra_ide/src/impls.rs rename to crates/ra_ide/src/goto_implementation.rs index ea2225f707..a5a296d228 100644 --- a/crates/ra_ide/src/impls.rs +++ b/crates/ra_ide/src/goto_implementation.rs @@ -6,6 +6,15 @@ use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; use crate::{display::ToNav, FilePosition, NavigationTarget, RangeInfo}; +// Feature: Go To Implementation +// +// Navigates to the impl block of structs, enums or traits. Also implemented as a code lens. +// +// |=== +// | Editor | Shortcut +// +// | VS Code | kbd:[Ctrl+F12] +// |=== pub(crate) fn goto_implementation( db: &RootDatabase, position: FilePosition, diff --git a/crates/ra_ide/src/goto_type_definition.rs b/crates/ra_ide/src/goto_type_definition.rs index a84637489e..eeadfa9ee7 100644 --- a/crates/ra_ide/src/goto_type_definition.rs +++ b/crates/ra_ide/src/goto_type_definition.rs @@ -5,6 +5,9 @@ use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffs use crate::{display::ToNav, FilePosition, NavigationTarget, RangeInfo}; +// Feature: Go To Type Definition +// +// Navigates to the type of an identifier. pub(crate) fn goto_type_definition( db: &RootDatabase, position: FilePosition, diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index d983cd9100..12d5716e83 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs @@ -23,6 +23,7 @@ mod completion; mod runnables; mod goto_definition; mod goto_type_definition; +mod goto_implementation; mod extend_selection; mod hover; mod call_hierarchy; @@ -30,7 +31,6 @@ mod call_info; mod syntax_highlighting; mod parent_module; mod references; -mod impls; mod diagnostics; mod syntax_tree; mod folding_ranges; @@ -373,7 +373,7 @@ impl Analysis { &self, position: FilePosition, ) -> Cancelable>>> { - self.with_db(|db| impls::goto_implementation(db, position)) + self.with_db(|db| goto_implementation::goto_implementation(db, position)) } /// Returns the type definitions for the symbol at `position`. diff --git a/crates/ra_ide/src/typing.rs b/crates/ra_ide/src/typing.rs index 39bb3b3579..67e2c33a00 100644 --- a/crates/ra_ide/src/typing.rs +++ b/crates/ra_ide/src/typing.rs @@ -32,6 +32,13 @@ pub(crate) use on_enter::on_enter; pub(crate) const TRIGGER_CHARS: &str = ".=>"; +// Feature: On Typing Assists +// +// Some features trigger on typing certain characters: +// +// - typing `let =` tries to smartly add `;` if `=` is followed by an existing expression +// - Enter inside comments automatically inserts `///` +// - typing `.` in a chain method call auto-indents pub(crate) fn on_char_typed( db: &RootDatabase, position: FilePosition, diff --git a/crates/ra_ide_db/src/symbol_index.rs b/crates/ra_ide_db/src/symbol_index.rs index 95be111345..acc31fe3b5 100644 --- a/crates/ra_ide_db/src/symbol_index.rs +++ b/crates/ra_ide_db/src/symbol_index.rs @@ -110,6 +110,27 @@ fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc Arc::new(SymbolIndex::new(symbols)) } +// Feature: Workspace Symbol +// +// Uses fuzzy-search to find types, modules and functions by name across your +// project and dependencies. This is **the** most useful feature, which improves code +// navigation tremendously. It mostly works on top of the built-in LSP +// functionality, however `#` and `*` symbols can be used to narrow down the +// search. Specifically, +// +// - `Foo` searches for `Foo` type in the current workspace +// - `foo#` searches for `foo` function in the current workspace +// - `Foo*` searches for `Foo` type among dependencies, including `stdlib` +// - `foo#*` searches for `foo` function among dependencies +// +// That is, `#` switches from "types" to all symbols, `*` switches from the current +// workspace to dependencies. +// +// |=== +// | Editor | Shortcut +// +// | VS Code | kbd:[Ctrl+T] +// |=== pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec { /// Need to wrap Snapshot to provide `Clone` impl for `map_with` struct Snap(salsa::Snapshot); diff --git a/docs/user/features.md b/docs/user/features.md index 12ecdec136..4d94022524 100644 --- a/docs/user/features.md +++ b/docs/user/features.md @@ -2,58 +2,6 @@ This document is an index of features that the rust-analyzer language server provides. Shortcuts are for the default VS Code layout. If there's no shortcut, you can use Ctrl+Shift+P to search for the corresponding action. -### Workspace Symbol ctrl+t - -Uses fuzzy-search to find types, modules and functions by name across your -project and dependencies. This is **the** most useful feature, which improves code -navigation tremendously. It mostly works on top of the built-in LSP -functionality, however `#` and `*` symbols can be used to narrow down the -search. Specifically, - -- `Foo` searches for `Foo` type in the current workspace -- `foo#` searches for `foo` function in the current workspace -- `Foo*` searches for `Foo` type among dependencies, including `stdlib` -- `foo#*` searches for `foo` function among dependencies - -That is, `#` switches from "types" to all symbols, `*` switches from the current -workspace to dependencies. - -### Document Symbol ctrl+shift+o - -Provides a tree of the symbols defined in the file. Can be used to - -* fuzzy search symbol in a file (super useful) -* draw breadcrumbs to describe the context around the cursor -* draw outline of the file - -### On Typing Assists - -Some features trigger on typing certain characters: - -- typing `let =` tries to smartly add `;` if `=` is followed by an existing expression -- Enter inside comments automatically inserts `///` -- typing `.` in a chain method call auto-indents - -### Extend Selection - -Extends the current selection to the encompassing syntactic construct -(expression, statement, item, module, etc). It works with multiple cursors. This -is a relatively new feature of LSP: -https://github.com/Microsoft/language-server-protocol/issues/613, check your -editor's LSP library to see if this feature is supported. - -### Go to Definition - -Navigates to the definition of an identifier. - -### Go to Implementation - -Navigates to the impl block of structs, enums or traits. Also implemented as a code lens. - -### Go to Type Defintion - -Navigates to the type of an identifier. - ### Commands ctrl+shift+p #### Run diff --git a/docs/user/generated_features.adoc b/docs/user/generated_features.adoc new file mode 100644 index 0000000000..e1eb5d88a8 --- /dev/null +++ b/docs/user/generated_features.adoc @@ -0,0 +1,98 @@ +=== Extend Selection +**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/extend_selection.rs[extend_selection.rs] + + +Extends the current selection to the encompassing syntactic construct +(expression, statement, item, module, etc). It works with multiple cursors. + +|=== +| Editor | Shortcut + +| VS Code | kbd:[Ctrl+Shift+→] +|=== + + +=== File Structure +**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/display/structure.rs[structure.rs] + + +Provides a tree of the symbols defined in the file. Can be used to + +* fuzzy search symbol in a file (super useful) +* draw breadcrumbs to describe the context around the cursor +* draw outline of the file + +|=== +| Editor | Shortcut + +| VS Code | kbd:[Ctrl+Shift+O] +|=== + + +=== Go To Definition +**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/goto_definition.rs[goto_definition.rs] + + +Navigates to the definition of an identifier. + +|=== +| Editor | Shortcut + +| VS Code | kbd:[F12] +|=== + + +=== Go To Implementation +**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/goto_implementation.rs[goto_implementation.rs] + + +Navigates to the impl block of structs, enums or traits. Also implemented as a code lens. + +|=== +| Editor | Shortcut + +| VS Code | kbd:[Ctrl+F12] +|=== + + +=== Go To Type Definition +**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/goto_type_definition.rs[goto_type_definition.rs] + + +Navigates to the type of an identifier. + + +=== On Typing Assists +**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/typing.rs[typing.rs] + + +Some features trigger on typing certain characters: + +- typing `let =` tries to smartly add `;` if `=` is followed by an existing expression +- Enter inside comments automatically inserts `///` +- typing `.` in a chain method call auto-indents + + +=== Workspace Symbol +**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide_db/src/symbol_index.rs[symbol_index.rs] + + +Uses fuzzy-search to find types, modules and functions by name across your +project and dependencies. This is **the** most useful feature, which improves code +navigation tremendously. It mostly works on top of the built-in LSP +functionality, however `#` and `*` symbols can be used to narrow down the +search. Specifically, + +- `Foo` searches for `Foo` type in the current workspace +- `foo#` searches for `foo` function in the current workspace +- `Foo*` searches for `Foo` type among dependencies, including `stdlib` +- `foo#*` searches for `foo` function among dependencies + +That is, `#` switches from "types" to all symbols, `*` switches from the current +workspace to dependencies. + +|=== +| Editor | Shortcut + +| VS Code | kbd:[Ctrl+T] +|=== diff --git a/docs/user/readme.adoc b/docs/user/readme.adoc index 64bd0feb13..7b159bfc6b 100644 --- a/docs/user/readme.adoc +++ b/docs/user/readme.adoc @@ -8,6 +8,7 @@ :important-caption: :heavy_exclamation_mark: :caution-caption: :fire: :warning-caption: :warning: +:experimental: // Master copy of this document lives in the https://github.com/rust-analyzer/rust-analyzer repository @@ -268,6 +269,6 @@ Gnome Builder currently has support for RLS, and there's no way to configure the 1. Rename, symlink or copy the `rust-analyzer` binary to `rls` and place it somewhere Builder can find (in `PATH`, or under `~/.cargo/bin`). 2. Enable the Rust Builder plugin. -== Usage +== Features -See https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/features.md[features.md]. +include::./generated_features.adoc[] diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index 2e8fd34943..3e2a66979d 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs @@ -8,14 +8,15 @@ mod gen_syntax; mod gen_parser_tests; mod gen_assists_docs; +mod gen_feature_docs; use std::{mem, path::Path}; use crate::{not_bash::fs2, Result}; pub use self::{ - gen_assists_docs::generate_assists_docs, gen_parser_tests::generate_parser_tests, - gen_syntax::generate_syntax, + gen_assists_docs::generate_assists_docs, gen_feature_docs::generate_feature_docs, + gen_parser_tests::generate_parser_tests, gen_syntax::generate_syntax, }; const GRAMMAR_DIR: &str = "crates/ra_parser/src/grammar"; diff --git a/xtask/src/codegen/gen_feature_docs.rs b/xtask/src/codegen/gen_feature_docs.rs new file mode 100644 index 0000000000..5831856487 --- /dev/null +++ b/xtask/src/codegen/gen_feature_docs.rs @@ -0,0 +1,72 @@ +//! Generates `assists.md` documentation. + +use std::{fmt, fs, path::PathBuf}; + +use crate::{ + codegen::{self, extract_comment_blocks_with_empty_lines, Mode}, + project_root, rust_files, Result, +}; + +pub fn generate_feature_docs(mode: Mode) -> Result<()> { + let features = Feature::collect()?; + let contents = features.into_iter().map(|it| it.to_string()).collect::>().join("\n\n"); + + let dst = project_root().join("docs/user/generated_features.adoc"); + codegen::update(&dst, &contents, mode)?; + Ok(()) +} + +#[derive(Debug)] +struct Feature { + id: String, + path: PathBuf, + doc: String, +} + +impl Feature { + fn collect() -> Result> { + let mut res = Vec::new(); + for path in rust_files(&project_root()) { + collect_file(&mut res, path)?; + } + res.sort_by(|lhs, rhs| lhs.id.cmp(&rhs.id)); + return Ok(res); + + fn collect_file(acc: &mut Vec, path: PathBuf) -> Result<()> { + let text = fs::read_to_string(&path)?; + let comment_blocks = extract_comment_blocks_with_empty_lines("Feature", &text); + + for block in comment_blocks { + let id = block.id; + assert!( + id.split_ascii_whitespace().all(|it| it.starts_with(char::is_uppercase)), + "bad feature: {}", + id + ); + let doc = block.contents.join("\n"); + acc.push(Feature { id, path: path.clone(), doc }) + } + + Ok(()) + } + } +} + +impl fmt::Display for Feature { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "=== {}", self.id)?; + let path = self.path.strip_prefix(&project_root()).unwrap(); + let name = self.path.file_name().unwrap(); + + //FIXME: generate line number as well + writeln!( + f, + "**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/{}[{}]", + path.display(), + name.to_str().unwrap(), + )?; + + writeln!(f, "\n{}", self.doc)?; + Ok(()) + } +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index dff3ce4a1d..9d7cdd1145 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -75,6 +75,7 @@ FLAGS: codegen::generate_syntax(Mode::Overwrite)?; codegen::generate_parser_tests(Mode::Overwrite)?; codegen::generate_assists_docs(Mode::Overwrite)?; + codegen::generate_feature_docs(Mode::Overwrite)?; Ok(()) } "format" => { diff --git a/xtask/tests/tidy.rs b/xtask/tests/tidy.rs index 2e9fcf07c5..06ff45d994 100644 --- a/xtask/tests/tidy.rs +++ b/xtask/tests/tidy.rs @@ -30,6 +30,13 @@ fn generated_assists_are_fresh() { } } +#[test] +fn generated_features_are_fresh() { + if let Err(error) = codegen::generate_feature_docs(Mode::Verify) { + panic!("{}. Please update features by running `cargo xtask codegen`", error); + } +} + #[test] fn check_code_formatting() { if let Err(error) = run_rustfmt(Mode::Verify) {