diff options
-rw-r--r-- | .cargo/config | 2 | ||||
-rw-r--r-- | ARCHITECTURE.md | 8 | ||||
-rw-r--r-- | crates/ra_ide_api/src/call_info.rs | 66 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion.rs | 19 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/completion_item.rs | 35 | ||||
-rw-r--r-- | crates/ra_ide_api/src/lib.rs | 3 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/conv.rs | 19 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 11 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/markdown.rs | 38 | ||||
-rw-r--r-- | editors/code/package.json | 28 |
11 files changed, 128 insertions, 102 deletions
diff --git a/.cargo/config b/.cargo/config index 3fba0f71d..b12f407e6 100644 --- a/.cargo/config +++ b/.cargo/config | |||
@@ -5,6 +5,8 @@ gen-syntax = "run --package tools --bin tools -- gen-syntax" | |||
5 | gen-tests = "run --package tools --bin tools -- gen-tests" | 5 | gen-tests = "run --package tools --bin tools -- gen-tests" |
6 | # Installs ra_lsp_server | 6 | # Installs ra_lsp_server |
7 | install-lsp = "install --path crates/ra_lsp_server --force" | 7 | install-lsp = "install --path crates/ra_lsp_server --force" |
8 | # Installs ra_lsp_server with the jemalloc feature | ||
9 | jinstall-lsp = "install --path crates/ra_lsp_server --force --features jemalloc" | ||
8 | # Installs the visual studio code extension | 10 | # Installs the visual studio code extension |
9 | install-code = "run --package tools --bin tools -- install-code" | 11 | install-code = "run --package tools --bin tools -- install-code" |
10 | # Formats the full repository or installs the git hook to do it automatically. | 12 | # Formats the full repository or installs the git hook to do it automatically. |
diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index cb8f01f78..8602de56d 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md | |||
@@ -178,7 +178,7 @@ VS Code plugin | |||
178 | 178 | ||
179 | To try out VS Code extensions, run `cargo install-code`. This installs both the | 179 | To try out VS Code extensions, run `cargo install-code`. This installs both the |
180 | `ra_lsp_server` binary and the VS Code extension. To install only the binary, use | 180 | `ra_lsp_server` binary and the VS Code extension. To install only the binary, use |
181 | `cargo install --path crates/ra_lsp_server --force` | 181 | `cargo install-lsp` (shorthand for `cargo install --path crates/ra_lsp_server --force`) |
182 | 182 | ||
183 | To see logs from the language server, set `RUST_LOG=info` env variable. To see | 183 | To see logs from the language server, set `RUST_LOG=info` env variable. To see |
184 | all communication between the server and the client, use | 184 | all communication between the server and the client, use |
@@ -186,12 +186,12 @@ all communication between the server and the client, use | |||
186 | 186 | ||
187 | There's `rust-analyzer: status` command which prints common high-level debug | 187 | There's `rust-analyzer: status` command which prints common high-level debug |
188 | info. In particular, it prints info about memory usage of various data | 188 | info. In particular, it prints info about memory usage of various data |
189 | structures, and, if compiled with jemalloc support (`cargo install --features | 189 | structures, and, if compiled with jemalloc support (`cargo jinstall-lsp` or |
190 | jemalloc`), the summary statistic about the heap. | 190 | `cargo install --path crates/ra_lsp_server --force --features jemalloc`), includes |
191 | statistic about the heap. | ||
191 | 192 | ||
192 | To run tests, just `cargo test`. | 193 | To run tests, just `cargo test`. |
193 | 194 | ||
194 | To work on the VS Code extension, launch code inside `editors/code` and use `F5` to | 195 | To work on the VS Code extension, launch code inside `editors/code` and use `F5` to |
195 | launch/debug. To automatically apply formatter and linter suggestions, use `npm | 196 | launch/debug. To automatically apply formatter and linter suggestions, use `npm |
196 | run fix`. | 197 | run fix`. |
197 | |||
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs index ee1e13799..2eb388e0e 100644 --- a/crates/ra_ide_api/src/call_info.rs +++ b/crates/ra_ide_api/src/call_info.rs | |||
@@ -3,9 +3,10 @@ use ra_db::SourceDatabase; | |||
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | AstNode, SyntaxNode, TextUnit, TextRange, | 4 | AstNode, SyntaxNode, TextUnit, TextRange, |
5 | SyntaxKind::FN_DEF, | 5 | SyntaxKind::FN_DEF, |
6 | ast::{self, ArgListOwner, DocCommentsOwner}, | 6 | ast::{self, ArgListOwner}, |
7 | algo::find_node_at_offset, | 7 | algo::find_node_at_offset, |
8 | }; | 8 | }; |
9 | use hir::Docs; | ||
9 | 10 | ||
10 | use crate::{FilePosition, CallInfo, db::RootDatabase}; | 11 | use crate::{FilePosition, CallInfo, db::RootDatabase}; |
11 | 12 | ||
@@ -26,7 +27,9 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal | |||
26 | let fn_file = db.parse(symbol.file_id); | 27 | let fn_file = db.parse(symbol.file_id); |
27 | let fn_def = symbol.ptr.to_node(&fn_file); | 28 | let fn_def = symbol.ptr.to_node(&fn_file); |
28 | let fn_def = ast::FnDef::cast(fn_def).unwrap(); | 29 | let fn_def = ast::FnDef::cast(fn_def).unwrap(); |
29 | let mut call_info = CallInfo::new(fn_def)?; | 30 | let function = hir::source_binder::function_from_source(db, symbol.file_id, fn_def)?; |
31 | |||
32 | let mut call_info = CallInfo::new(db, function, fn_def)?; | ||
30 | // If we have a calling expression let's find which argument we are on | 33 | // If we have a calling expression let's find which argument we are on |
31 | let num_params = call_info.parameters.len(); | 34 | let num_params = call_info.parameters.len(); |
32 | let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some(); | 35 | let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some(); |
@@ -110,46 +113,13 @@ impl<'a> FnCallNode<'a> { | |||
110 | } | 113 | } |
111 | 114 | ||
112 | impl CallInfo { | 115 | impl CallInfo { |
113 | fn new(node: &ast::FnDef) -> Option<Self> { | 116 | fn new(db: &RootDatabase, function: hir::Function, node: &ast::FnDef) -> Option<Self> { |
114 | let label: String = if let Some(body) = node.body() { | 117 | let label = crate::completion::function_label(node)?; |
115 | let body_range = body.syntax().range(); | 118 | let doc = function.docs(db); |
116 | let label: String = node | ||
117 | .syntax() | ||
118 | .children() | ||
119 | .filter(|child| !child.range().is_subrange(&body_range)) // Filter out body | ||
120 | .filter(|child| ast::Comment::cast(child).is_none()) // Filter out doc comments | ||
121 | .map(|node| node.text().to_string()) | ||
122 | .collect(); | ||
123 | label | ||
124 | } else { | ||
125 | node.syntax().text().to_string() | ||
126 | }; | ||
127 | |||
128 | let mut doc = None; | ||
129 | if let Some(docs) = node.doc_comment_text() { | ||
130 | // Massage markdown | ||
131 | let mut processed_lines = Vec::new(); | ||
132 | let mut in_code_block = false; | ||
133 | for line in docs.lines() { | ||
134 | if line.starts_with("```") { | ||
135 | in_code_block = !in_code_block; | ||
136 | } | ||
137 | |||
138 | let line = if in_code_block && line.starts_with("```") && !line.contains("rust") { | ||
139 | "```rust".into() | ||
140 | } else { | ||
141 | line.to_string() | ||
142 | }; | ||
143 | |||
144 | processed_lines.push(line); | ||
145 | } | ||
146 | |||
147 | doc = Some(processed_lines.join("\n")); | ||
148 | } | ||
149 | 119 | ||
150 | Some(CallInfo { | 120 | Some(CallInfo { |
151 | parameters: param_list(node), | 121 | parameters: param_list(node), |
152 | label: label.trim().to_owned(), | 122 | label, |
153 | doc, | 123 | doc, |
154 | active_parameter: None, | 124 | active_parameter: None, |
155 | }) | 125 | }) |
@@ -284,7 +254,7 @@ fn bar() { | |||
284 | assert_eq!(info.parameters, vec!["j".to_string()]); | 254 | assert_eq!(info.parameters, vec!["j".to_string()]); |
285 | assert_eq!(info.active_parameter, Some(0)); | 255 | assert_eq!(info.active_parameter, Some(0)); |
286 | assert_eq!(info.label, "fn foo(j: u32) -> u32".to_string()); | 256 | assert_eq!(info.label, "fn foo(j: u32) -> u32".to_string()); |
287 | assert_eq!(info.doc, Some("test".into())); | 257 | assert_eq!(info.doc.map(|it| it.into()), Some("test".to_string())); |
288 | } | 258 | } |
289 | 259 | ||
290 | #[test] | 260 | #[test] |
@@ -313,18 +283,18 @@ pub fn do() { | |||
313 | assert_eq!(info.active_parameter, Some(0)); | 283 | assert_eq!(info.active_parameter, Some(0)); |
314 | assert_eq!(info.label, "pub fn add_one(x: i32) -> i32".to_string()); | 284 | assert_eq!(info.label, "pub fn add_one(x: i32) -> i32".to_string()); |
315 | assert_eq!( | 285 | assert_eq!( |
316 | info.doc, | 286 | info.doc.map(|it| it.into()), |
317 | Some( | 287 | Some( |
318 | r#"Adds one to the number given. | 288 | r#"Adds one to the number given. |
319 | 289 | ||
320 | # Examples | 290 | # Examples |
321 | 291 | ||
322 | ```rust | 292 | ``` |
323 | let five = 5; | 293 | let five = 5; |
324 | 294 | ||
325 | assert_eq!(6, my_crate::add_one(5)); | 295 | assert_eq!(6, my_crate::add_one(5)); |
326 | ```"# | 296 | ```"# |
327 | .into() | 297 | .to_string() |
328 | ) | 298 | ) |
329 | ); | 299 | ); |
330 | } | 300 | } |
@@ -359,18 +329,18 @@ pub fn do_it() { | |||
359 | assert_eq!(info.active_parameter, Some(0)); | 329 | assert_eq!(info.active_parameter, Some(0)); |
360 | assert_eq!(info.label, "pub fn add_one(x: i32) -> i32".to_string()); | 330 | assert_eq!(info.label, "pub fn add_one(x: i32) -> i32".to_string()); |
361 | assert_eq!( | 331 | assert_eq!( |
362 | info.doc, | 332 | info.doc.map(|it| it.into()), |
363 | Some( | 333 | Some( |
364 | r#"Adds one to the number given. | 334 | r#"Adds one to the number given. |
365 | 335 | ||
366 | # Examples | 336 | # Examples |
367 | 337 | ||
368 | ```rust | 338 | ``` |
369 | let five = 5; | 339 | let five = 5; |
370 | 340 | ||
371 | assert_eq!(6, my_crate::add_one(5)); | 341 | assert_eq!(6, my_crate::add_one(5)); |
372 | ```"# | 342 | ```"# |
373 | .into() | 343 | .to_string() |
374 | ) | 344 | ) |
375 | ); | 345 | ); |
376 | } | 346 | } |
@@ -414,12 +384,12 @@ pub fn foo() { | |||
414 | ); | 384 | ); |
415 | assert_eq!(info.active_parameter, Some(1)); | 385 | assert_eq!(info.active_parameter, Some(1)); |
416 | assert_eq!( | 386 | assert_eq!( |
417 | info.doc, | 387 | info.doc.map(|it| it.into()), |
418 | Some( | 388 | Some( |
419 | r#"Method is called when writer finishes. | 389 | r#"Method is called when writer finishes. |
420 | 390 | ||
421 | By default this method stops actor's `Context`."# | 391 | By default this method stops actor's `Context`."# |
422 | .into() | 392 | .to_string() |
423 | ) | 393 | ) |
424 | ); | 394 | ); |
425 | } | 395 | } |
diff --git a/crates/ra_ide_api/src/completion.rs b/crates/ra_ide_api/src/completion.rs index b1867de42..722d94f3a 100644 --- a/crates/ra_ide_api/src/completion.rs +++ b/crates/ra_ide_api/src/completion.rs | |||
@@ -10,6 +10,7 @@ mod complete_scope; | |||
10 | mod complete_postfix; | 10 | mod complete_postfix; |
11 | 11 | ||
12 | use ra_db::SourceDatabase; | 12 | use ra_db::SourceDatabase; |
13 | use ra_syntax::ast::{self, AstNode}; | ||
13 | 14 | ||
14 | use crate::{ | 15 | use crate::{ |
15 | db, | 16 | db, |
@@ -61,3 +62,21 @@ pub(crate) fn completions(db: &db::RootDatabase, position: FilePosition) -> Opti | |||
61 | complete_postfix::complete_postfix(&mut acc, &ctx); | 62 | complete_postfix::complete_postfix(&mut acc, &ctx); |
62 | Some(acc) | 63 | Some(acc) |
63 | } | 64 | } |
65 | |||
66 | pub fn function_label(node: &ast::FnDef) -> Option<String> { | ||
67 | let label: String = if let Some(body) = node.body() { | ||
68 | let body_range = body.syntax().range(); | ||
69 | let label: String = node | ||
70 | .syntax() | ||
71 | .children() | ||
72 | .filter(|child| !child.range().is_subrange(&body_range)) // Filter out body | ||
73 | .filter(|child| ast::Comment::cast(child).is_none()) // Filter out comments | ||
74 | .map(|node| node.text().to_string()) | ||
75 | .collect(); | ||
76 | label | ||
77 | } else { | ||
78 | node.syntax().text().to_string() | ||
79 | }; | ||
80 | |||
81 | Some(label.trim().to_owned()) | ||
82 | } | ||
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index 49bd636a5..d3bc14894 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs | |||
@@ -1,12 +1,12 @@ | |||
1 | use hir::{Docs, Documentation}; | 1 | use hir::{Docs, Documentation}; |
2 | use ra_syntax::{ | 2 | use ra_syntax::TextRange; |
3 | ast::{self, AstNode}, | ||
4 | TextRange, | ||
5 | }; | ||
6 | use ra_text_edit::TextEdit; | 3 | use ra_text_edit::TextEdit; |
7 | use test_utils::tested_by; | 4 | use test_utils::tested_by; |
8 | 5 | ||
9 | use crate::completion::completion_context::CompletionContext; | 6 | use crate::completion::{ |
7 | completion_context::CompletionContext, | ||
8 | function_label, | ||
9 | }; | ||
10 | 10 | ||
11 | /// `CompletionItem` describes a single completion variant in the editor pop-up. | 11 | /// `CompletionItem` describes a single completion variant in the editor pop-up. |
12 | /// It is basically a POD with various properties. To construct a | 12 | /// It is basically a POD with various properties. To construct a |
@@ -97,8 +97,8 @@ impl CompletionItem { | |||
97 | self.detail.as_ref().map(|it| it.as_str()) | 97 | self.detail.as_ref().map(|it| it.as_str()) |
98 | } | 98 | } |
99 | /// A doc-comment | 99 | /// A doc-comment |
100 | pub fn documentation(&self) -> Option<&str> { | 100 | pub fn documentation(&self) -> Option<Documentation> { |
101 | self.documentation.as_ref().map(|it| it.contents()) | 101 | self.documentation.clone() |
102 | } | 102 | } |
103 | /// What string is used for filtering. | 103 | /// What string is used for filtering. |
104 | pub fn lookup(&self) -> &str { | 104 | pub fn lookup(&self) -> &str { |
@@ -252,7 +252,7 @@ impl Builder { | |||
252 | self.documentation = Some(docs); | 252 | self.documentation = Some(docs); |
253 | } | 253 | } |
254 | 254 | ||
255 | if let Some(label) = function_label(ctx, function) { | 255 | if let Some(label) = function_item_label(ctx, function) { |
256 | self.detail = Some(label); | 256 | self.detail = Some(label); |
257 | } | 257 | } |
258 | 258 | ||
@@ -292,24 +292,9 @@ impl Into<Vec<CompletionItem>> for Completions { | |||
292 | } | 292 | } |
293 | } | 293 | } |
294 | 294 | ||
295 | fn function_label(ctx: &CompletionContext, function: hir::Function) -> Option<String> { | 295 | fn function_item_label(ctx: &CompletionContext, function: hir::Function) -> Option<String> { |
296 | let node = function.source(ctx.db).1; | 296 | let node = function.source(ctx.db).1; |
297 | 297 | function_label(&node) | |
298 | let label: String = if let Some(body) = node.body() { | ||
299 | let body_range = body.syntax().range(); | ||
300 | let label: String = node | ||
301 | .syntax() | ||
302 | .children() | ||
303 | .filter(|child| !child.range().is_subrange(&body_range)) // Filter out body | ||
304 | .filter(|child| ast::Comment::cast(child).is_none()) // Filter out comments | ||
305 | .map(|node| node.text().to_string()) | ||
306 | .collect(); | ||
307 | label | ||
308 | } else { | ||
309 | node.syntax().text().to_string() | ||
310 | }; | ||
311 | |||
312 | Some(label.trim().to_owned()) | ||
313 | } | 298 | } |
314 | 299 | ||
315 | #[cfg(test)] | 300 | #[cfg(test)] |
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index 51947e4cc..09cf0216d 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs | |||
@@ -58,6 +58,7 @@ pub use ra_ide_api_light::{ | |||
58 | pub use ra_db::{ | 58 | pub use ra_db::{ |
59 | Canceled, CrateGraph, CrateId, FileId, FilePosition, FileRange, SourceRootId | 59 | Canceled, CrateGraph, CrateId, FileId, FilePosition, FileRange, SourceRootId |
60 | }; | 60 | }; |
61 | pub use hir::Documentation; | ||
61 | 62 | ||
62 | // We use jemalloc mainly to get heap usage statistics, actual performance | 63 | // We use jemalloc mainly to get heap usage statistics, actual performance |
63 | // differnece is not measures. | 64 | // differnece is not measures. |
@@ -266,7 +267,7 @@ impl<T> RangeInfo<T> { | |||
266 | #[derive(Debug)] | 267 | #[derive(Debug)] |
267 | pub struct CallInfo { | 268 | pub struct CallInfo { |
268 | pub label: String, | 269 | pub label: String, |
269 | pub doc: Option<String>, | 270 | pub doc: Option<Documentation>, |
270 | pub parameters: Vec<String>, | 271 | pub parameters: Vec<String>, |
271 | pub active_parameter: Option<usize>, | 272 | pub active_parameter: Option<usize>, |
272 | } | 273 | } |
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index 8c87f5195..c033ecdea 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs | |||
@@ -87,13 +87,6 @@ impl ConvWith for CompletionItem { | |||
87 | None | 87 | None |
88 | }; | 88 | }; |
89 | 89 | ||
90 | let documentation = self.documentation().map(|value| { | ||
91 | Documentation::MarkupContent(MarkupContent { | ||
92 | kind: MarkupKind::Markdown, | ||
93 | value: value.to_string(), | ||
94 | }) | ||
95 | }); | ||
96 | |||
97 | let mut res = lsp_types::CompletionItem { | 90 | let mut res = lsp_types::CompletionItem { |
98 | label: self.label().to_string(), | 91 | label: self.label().to_string(), |
99 | detail: self.detail().map(|it| it.to_string()), | 92 | detail: self.detail().map(|it| it.to_string()), |
@@ -101,7 +94,7 @@ impl ConvWith for CompletionItem { | |||
101 | kind: self.kind().map(|it| it.conv()), | 94 | kind: self.kind().map(|it| it.conv()), |
102 | text_edit: Some(text_edit), | 95 | text_edit: Some(text_edit), |
103 | additional_text_edits, | 96 | additional_text_edits, |
104 | documentation: documentation, | 97 | documentation: self.documentation().map(|it| it.conv()), |
105 | ..Default::default() | 98 | ..Default::default() |
106 | }; | 99 | }; |
107 | res.insert_text_format = Some(match self.insert_text_format() { | 100 | res.insert_text_format = Some(match self.insert_text_format() { |
@@ -160,6 +153,16 @@ impl ConvWith for Range { | |||
160 | } | 153 | } |
161 | } | 154 | } |
162 | 155 | ||
156 | impl Conv for ra_ide_api::Documentation { | ||
157 | type Output = lsp_types::Documentation; | ||
158 | fn conv(self) -> Documentation { | ||
159 | Documentation::MarkupContent(MarkupContent { | ||
160 | kind: MarkupKind::Markdown, | ||
161 | value: crate::markdown::sanitize_markdown(self).into(), | ||
162 | }) | ||
163 | } | ||
164 | } | ||
165 | |||
163 | impl ConvWith for TextEdit { | 166 | impl ConvWith for TextEdit { |
164 | type Ctx = LineIndex; | 167 | type Ctx = LineIndex; |
165 | type Output = Vec<lsp_types::TextEdit>; | 168 | type Output = Vec<lsp_types::TextEdit>; |
diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs index f93d4b37d..5b5f3b948 100644 --- a/crates/ra_lsp_server/src/lib.rs +++ b/crates/ra_lsp_server/src/lib.rs | |||
@@ -2,6 +2,7 @@ mod caps; | |||
2 | mod cargo_target_spec; | 2 | mod cargo_target_spec; |
3 | mod conv; | 3 | mod conv; |
4 | mod main_loop; | 4 | mod main_loop; |
5 | mod markdown; | ||
5 | mod project_model; | 6 | mod project_model; |
6 | pub mod req; | 7 | pub mod req; |
7 | mod server_world; | 8 | mod server_world; |
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 9478ebfb8..4f75f9a22 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use gen_lsp_server::ErrorCode; | 1 | use gen_lsp_server::ErrorCode; |
2 | use lsp_types::{ | 2 | use lsp_types::{ |
3 | CodeActionResponse, CodeLens, Command, Diagnostic, DiagnosticSeverity, | 3 | CodeActionResponse, CodeLens, Command, Diagnostic, DiagnosticSeverity, |
4 | DocumentFormattingParams, DocumentHighlight, DocumentSymbol, Documentation, FoldingRange, | 4 | DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange, |
5 | FoldingRangeKind, FoldingRangeParams, Hover, HoverContents, Location, MarkupContent, | 5 | FoldingRangeKind, FoldingRangeParams, Hover, HoverContents, Location, MarkupContent, |
6 | MarkupKind, ParameterInformation, ParameterLabel, Position, PrepareRenameResponse, Range, | 6 | MarkupKind, ParameterInformation, ParameterLabel, Position, PrepareRenameResponse, Range, |
7 | RenameParams, SignatureInformation, SymbolInformation, TextDocumentIdentifier, TextEdit, | 7 | RenameParams, SignatureInformation, SymbolInformation, TextDocumentIdentifier, TextEdit, |
@@ -401,12 +401,9 @@ pub fn handle_signature_help( | |||
401 | documentation: None, | 401 | documentation: None, |
402 | }) | 402 | }) |
403 | .collect(); | 403 | .collect(); |
404 | let documentation = call_info.doc.map(|value| { | 404 | |
405 | Documentation::MarkupContent(MarkupContent { | 405 | let documentation = call_info.doc.map(|it| it.conv()); |
406 | kind: MarkupKind::Markdown, | 406 | |
407 | value, | ||
408 | }) | ||
409 | }); | ||
410 | let sig_info = SignatureInformation { | 407 | let sig_info = SignatureInformation { |
411 | label: call_info.label, | 408 | label: call_info.label, |
412 | documentation, | 409 | documentation, |
diff --git a/crates/ra_lsp_server/src/markdown.rs b/crates/ra_lsp_server/src/markdown.rs new file mode 100644 index 000000000..f505755e8 --- /dev/null +++ b/crates/ra_lsp_server/src/markdown.rs | |||
@@ -0,0 +1,38 @@ | |||
1 | use ra_ide_api::Documentation; | ||
2 | |||
3 | pub(crate) fn sanitize_markdown(docs: Documentation) -> Documentation { | ||
4 | let docs: String = docs.into(); | ||
5 | |||
6 | // Massage markdown | ||
7 | let mut processed_lines = Vec::new(); | ||
8 | let mut in_code_block = false; | ||
9 | for line in docs.lines() { | ||
10 | if line.starts_with("```") { | ||
11 | in_code_block = !in_code_block; | ||
12 | } | ||
13 | |||
14 | let line = if in_code_block && line.starts_with("```") && !line.contains("rust") { | ||
15 | "```rust".into() | ||
16 | } else { | ||
17 | line.to_string() | ||
18 | }; | ||
19 | |||
20 | processed_lines.push(line); | ||
21 | } | ||
22 | |||
23 | Documentation::new(&processed_lines.join("\n")) | ||
24 | } | ||
25 | |||
26 | #[cfg(test)] | ||
27 | mod tests { | ||
28 | use super::*; | ||
29 | |||
30 | #[test] | ||
31 | fn test_codeblock_adds_rust() { | ||
32 | let comment = "```\nfn some_rust() {}\n```"; | ||
33 | assert_eq!( | ||
34 | sanitize_markdown(Documentation::new(comment)).contents(), | ||
35 | "```rust\nfn some_rust() {}\n```" | ||
36 | ); | ||
37 | } | ||
38 | } | ||
diff --git a/editors/code/package.json b/editors/code/package.json index 05c67d822..1ed834d62 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -44,7 +44,9 @@ | |||
44 | "vscode": "^1.1.26" | 44 | "vscode": "^1.1.26" |
45 | }, | 45 | }, |
46 | "activationEvents": [ | 46 | "activationEvents": [ |
47 | "onLanguage:rust" | 47 | "onLanguage:rust", |
48 | "onCommand:rust-analyzer.analyzerStatus", | ||
49 | "onCommand:rust-analyzer.collectGarbage" | ||
48 | ], | 50 | ], |
49 | "main": "./out/extension", | 51 | "main": "./out/extension", |
50 | "contributes": { | 52 | "contributes": { |
@@ -73,35 +75,43 @@ | |||
73 | "commands": [ | 75 | "commands": [ |
74 | { | 76 | { |
75 | "command": "rust-analyzer.syntaxTree", | 77 | "command": "rust-analyzer.syntaxTree", |
76 | "title": "rust-analyzer: syntax tree" | 78 | "title": "Show syntax tree for current file", |
79 | "category": "Rust Analyzer" | ||
77 | }, | 80 | }, |
78 | { | 81 | { |
79 | "command": "rust-analyzer.extendSelection", | 82 | "command": "rust-analyzer.extendSelection", |
80 | "title": "rust-analyzer: extend selection" | 83 | "title": "Extend selection", |
84 | "category": "Rust Analyzer" | ||
81 | }, | 85 | }, |
82 | { | 86 | { |
83 | "command": "rust-analyzer.matchingBrace", | 87 | "command": "rust-analyzer.matchingBrace", |
84 | "title": "rust-analyzer: matching brace" | 88 | "title": "Find matching brace", |
89 | "category": "Rust Analyzer" | ||
85 | }, | 90 | }, |
86 | { | 91 | { |
87 | "command": "rust-analyzer.parentModule", | 92 | "command": "rust-analyzer.parentModule", |
88 | "title": "rust-analyzer: parent module" | 93 | "title": "Locate parent module", |
94 | "category": "Rust Analyzer" | ||
89 | }, | 95 | }, |
90 | { | 96 | { |
91 | "command": "rust-analyzer.joinLines", | 97 | "command": "rust-analyzer.joinLines", |
92 | "title": "rust-analyzer: join lines" | 98 | "title": "Join lines", |
99 | "category": "Rust Analyzer" | ||
93 | }, | 100 | }, |
94 | { | 101 | { |
95 | "command": "rust-analyzer.run", | 102 | "command": "rust-analyzer.run", |
96 | "title": "rust-analyzer: run" | 103 | "title": "Run", |
104 | "category": "Rust Analyzer" | ||
97 | }, | 105 | }, |
98 | { | 106 | { |
99 | "command": "rust-analyzer.analyzerStatus", | 107 | "command": "rust-analyzer.analyzerStatus", |
100 | "title": "rust-analyzer: status" | 108 | "title": "Status", |
109 | "category": "Rust Analyzer" | ||
101 | }, | 110 | }, |
102 | { | 111 | { |
103 | "command": "rust-analyzer.collectGarbage", | 112 | "command": "rust-analyzer.collectGarbage", |
104 | "title": "rust-analyzer: run gc" | 113 | "title": "Run garbage collection", |
114 | "category": "Rust Analyzer" | ||
105 | } | 115 | } |
106 | ], | 116 | ], |
107 | "keybindings": [ | 117 | "keybindings": [ |