Generate features docs from source

This commit is contained in:
Aleksey Kladov 2020-05-31 01:54:54 +02:00
parent 383247a9ae
commit c8f27a4a88
15 changed files with 258 additions and 58 deletions

View file

@ -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<StructureNode> {
let mut res = Vec::new();
let mut stack = Vec::new();

View file

@ -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);

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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<Option<RangeInfo<Vec<NavigationTarget>>>> {
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`.

View file

@ -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,

View file

@ -110,6 +110,27 @@ fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex>
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<FileSymbol> {
/// Need to wrap Snapshot to provide `Clone` impl for `map_with`
struct Snap(salsa::Snapshot<RootDatabase>);

View file

@ -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 <kbd>Ctrl+Shift+P</kbd> to search for the corresponding action.
### Workspace Symbol <kbd>ctrl+t</kbd>
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 <kbd>ctrl+shift+o</kbd>
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 <kbd>ctrl+shift+p</kbd>
#### Run

View file

@ -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]
|===

View file

@ -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[]

View file

@ -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";

View file

@ -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::<Vec<_>>().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<Vec<Feature>> {
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<Feature>, 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(())
}
}

View file

@ -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" => {

View file

@ -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) {