diff options
10 files changed, 426 insertions, 34 deletions
diff --git a/crates/ra_ide/src/snapshots/highlight_doctest.html b/crates/ra_ide/src/snapshots/highlight_doctest.html index 5228df267..13a5d1b12 100644 --- a/crates/ra_ide/src/snapshots/highlight_doctest.html +++ b/crates/ra_ide/src/snapshots/highlight_doctest.html | |||
@@ -73,9 +73,13 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
73 | <span class="comment">///</span> | 73 | <span class="comment">///</span> |
74 | <span class="comment">/// ```</span> | 74 | <span class="comment">/// ```</span> |
75 | <span class="comment">///</span> | 75 | <span class="comment">///</span> |
76 | <span class="comment">/// ```</span> | 76 | <span class="comment">/// ```rust,no_run</span> |
77 | <span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">foobar</span> = <span class="struct">Foo</span>::<span class="function">new</span>().<span class="function">bar</span>(); | 77 | <span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">foobar</span> = <span class="struct">Foo</span>::<span class="function">new</span>().<span class="function">bar</span>(); |
78 | <span class="comment">/// ```</span> | 78 | <span class="comment">/// ```</span> |
79 | <span class="comment">///</span> | ||
80 | <span class="comment">/// ```sh</span> | ||
81 | <span class="comment">/// echo 1</span> | ||
82 | <span class="comment">/// ```</span> | ||
79 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration">foo</span>(&<span class="self_keyword">self</span>) -> <span class="builtin_type">bool</span> { | 83 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration">foo</span>(&<span class="self_keyword">self</span>) -> <span class="builtin_type">bool</span> { |
80 | <span class="bool_literal">true</span> | 84 | <span class="bool_literal">true</span> |
81 | } | 85 | } |
diff --git a/crates/ra_ide/src/syntax_highlighting/injection.rs b/crates/ra_ide/src/syntax_highlighting/injection.rs index a02ffe59e..929a5cc5c 100644 --- a/crates/ra_ide/src/syntax_highlighting/injection.rs +++ b/crates/ra_ide/src/syntax_highlighting/injection.rs | |||
@@ -53,6 +53,10 @@ pub(super) fn highlight_injection( | |||
53 | /// Mapping from extracted documentation code to original code | 53 | /// Mapping from extracted documentation code to original code |
54 | type RangesMap = BTreeMap<TextSize, TextSize>; | 54 | type RangesMap = BTreeMap<TextSize, TextSize>; |
55 | 55 | ||
56 | const RUSTDOC_FENCE: &'static str = "```"; | ||
57 | const RUSTDOC_FENCE_TOKENS: &[&'static str] = | ||
58 | &["", "rust", "should_panic", "ignore", "no_run", "compile_fail", "edition2015", "edition2018"]; | ||
59 | |||
56 | /// Extracts Rust code from documentation comments as well as a mapping from | 60 | /// Extracts Rust code from documentation comments as well as a mapping from |
57 | /// the extracted source code back to the original source ranges. | 61 | /// the extracted source code back to the original source ranges. |
58 | /// Lastly, a vector of new comment highlight ranges (spanning only the | 62 | /// Lastly, a vector of new comment highlight ranges (spanning only the |
@@ -67,6 +71,7 @@ pub(super) fn extract_doc_comments( | |||
67 | // Mapping from extracted documentation code to original code | 71 | // Mapping from extracted documentation code to original code |
68 | let mut range_mapping: RangesMap = BTreeMap::new(); | 72 | let mut range_mapping: RangesMap = BTreeMap::new(); |
69 | let mut line_start = TextSize::try_from(prefix.len()).unwrap(); | 73 | let mut line_start = TextSize::try_from(prefix.len()).unwrap(); |
74 | let mut is_codeblock = false; | ||
70 | let mut is_doctest = false; | 75 | let mut is_doctest = false; |
71 | // Replace the original, line-spanning comment ranges by new, only comment-prefix | 76 | // Replace the original, line-spanning comment ranges by new, only comment-prefix |
72 | // spanning comment ranges. | 77 | // spanning comment ranges. |
@@ -76,8 +81,13 @@ pub(super) fn extract_doc_comments( | |||
76 | .filter_map(|el| el.into_token().and_then(ast::Comment::cast)) | 81 | .filter_map(|el| el.into_token().and_then(ast::Comment::cast)) |
77 | .filter(|comment| comment.kind().doc.is_some()) | 82 | .filter(|comment| comment.kind().doc.is_some()) |
78 | .filter(|comment| { | 83 | .filter(|comment| { |
79 | if comment.text().contains("```") { | 84 | if let Some(idx) = comment.text().find(RUSTDOC_FENCE) { |
80 | is_doctest = !is_doctest; | 85 | is_codeblock = !is_codeblock; |
86 | // Check whether code is rust by inspecting fence guards | ||
87 | let guards = &comment.text()[idx + RUSTDOC_FENCE.len()..]; | ||
88 | let is_rust = | ||
89 | guards.split(',').all(|sub| RUSTDOC_FENCE_TOKENS.contains(&sub.trim())); | ||
90 | is_doctest = is_codeblock && is_rust; | ||
81 | false | 91 | false |
82 | } else { | 92 | } else { |
83 | is_doctest | 93 | is_doctest |
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs index 062b3ff4a..ebf5b50ac 100644 --- a/crates/ra_ide/src/syntax_highlighting/tests.rs +++ b/crates/ra_ide/src/syntax_highlighting/tests.rs | |||
@@ -329,9 +329,13 @@ impl Foo { | |||
329 | /// | 329 | /// |
330 | /// ``` | 330 | /// ``` |
331 | /// | 331 | /// |
332 | /// ``` | 332 | /// ```rust,no_run |
333 | /// let foobar = Foo::new().bar(); | 333 | /// let foobar = Foo::new().bar(); |
334 | /// ``` | 334 | /// ``` |
335 | /// | ||
336 | /// ```sh | ||
337 | /// echo 1 | ||
338 | /// ``` | ||
335 | pub fn foo(&self) -> bool { | 339 | pub fn foo(&self) -> bool { |
336 | true | 340 | true |
337 | } | 341 | } |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 0e7a937a0..0df7427cb 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | use std::{ffi::OsString, path::PathBuf}; | 10 | use std::{ffi::OsString, path::PathBuf}; |
11 | 11 | ||
12 | use crate::diagnostics::DiagnosticsConfig; | ||
12 | use lsp_types::ClientCapabilities; | 13 | use lsp_types::ClientCapabilities; |
13 | use ra_flycheck::FlycheckConfig; | 14 | use ra_flycheck::FlycheckConfig; |
14 | use ra_ide::{AssistConfig, CompletionConfig, HoverConfig, InlayHintsConfig}; | 15 | use ra_ide::{AssistConfig, CompletionConfig, HoverConfig, InlayHintsConfig}; |
@@ -20,6 +21,7 @@ pub struct Config { | |||
20 | pub client_caps: ClientCapsConfig, | 21 | pub client_caps: ClientCapsConfig, |
21 | 22 | ||
22 | pub publish_diagnostics: bool, | 23 | pub publish_diagnostics: bool, |
24 | pub diagnostics: DiagnosticsConfig, | ||
23 | pub lru_capacity: Option<usize>, | 25 | pub lru_capacity: Option<usize>, |
24 | pub proc_macro_srv: Option<(PathBuf, Vec<OsString>)>, | 26 | pub proc_macro_srv: Option<(PathBuf, Vec<OsString>)>, |
25 | pub files: FilesConfig, | 27 | pub files: FilesConfig, |
@@ -136,6 +138,7 @@ impl Default for Config { | |||
136 | 138 | ||
137 | with_sysroot: true, | 139 | with_sysroot: true, |
138 | publish_diagnostics: true, | 140 | publish_diagnostics: true, |
141 | diagnostics: DiagnosticsConfig::default(), | ||
139 | lru_capacity: None, | 142 | lru_capacity: None, |
140 | proc_macro_srv: None, | 143 | proc_macro_srv: None, |
141 | files: FilesConfig { watcher: FilesWatcher::Notify, exclude: Vec::new() }, | 144 | files: FilesConfig { watcher: FilesWatcher::Notify, exclude: Vec::new() }, |
@@ -184,6 +187,8 @@ impl Config { | |||
184 | 187 | ||
185 | set(value, "/withSysroot", &mut self.with_sysroot); | 188 | set(value, "/withSysroot", &mut self.with_sysroot); |
186 | set(value, "/diagnostics/enable", &mut self.publish_diagnostics); | 189 | set(value, "/diagnostics/enable", &mut self.publish_diagnostics); |
190 | set(value, "/diagnostics/warningsAsInfo", &mut self.diagnostics.warnings_as_info); | ||
191 | set(value, "/diagnostics/warningsAsHint", &mut self.diagnostics.warnings_as_hint); | ||
187 | set(value, "/lruCapacity", &mut self.lru_capacity); | 192 | set(value, "/lruCapacity", &mut self.lru_capacity); |
188 | self.files.watcher = match get(value, "/files/watcher") { | 193 | self.files.watcher = match get(value, "/files/watcher") { |
189 | Some("client") => FilesWatcher::Client, | 194 | Some("client") => FilesWatcher::Client, |
diff --git a/crates/rust-analyzer/src/diagnostics.rs b/crates/rust-analyzer/src/diagnostics.rs index 25856c543..290609e7f 100644 --- a/crates/rust-analyzer/src/diagnostics.rs +++ b/crates/rust-analyzer/src/diagnostics.rs | |||
@@ -11,6 +11,12 @@ use crate::lsp_ext; | |||
11 | pub type CheckFixes = Arc<HashMap<FileId, Vec<Fix>>>; | 11 | pub type CheckFixes = Arc<HashMap<FileId, Vec<Fix>>>; |
12 | 12 | ||
13 | #[derive(Debug, Default, Clone)] | 13 | #[derive(Debug, Default, Clone)] |
14 | pub struct DiagnosticsConfig { | ||
15 | pub warnings_as_info: Vec<String>, | ||
16 | pub warnings_as_hint: Vec<String>, | ||
17 | } | ||
18 | |||
19 | #[derive(Debug, Default, Clone)] | ||
14 | pub struct DiagnosticCollection { | 20 | pub struct DiagnosticCollection { |
15 | pub native: HashMap<FileId, Vec<Diagnostic>>, | 21 | pub native: HashMap<FileId, Vec<Diagnostic>>, |
16 | pub check: HashMap<FileId, Vec<Diagnostic>>, | 22 | pub check: HashMap<FileId, Vec<Diagnostic>>, |
diff --git a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_hint.snap b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_hint.snap new file mode 100644 index 000000000..f0273315e --- /dev/null +++ b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_hint.snap | |||
@@ -0,0 +1,86 @@ | |||
1 | --- | ||
2 | source: crates/rust-analyzer/src/diagnostics/to_proto.rs | ||
3 | expression: diag | ||
4 | --- | ||
5 | [ | ||
6 | MappedRustDiagnostic { | ||
7 | location: Location { | ||
8 | uri: "file:///test/driver/subcommand/repl.rs", | ||
9 | range: Range { | ||
10 | start: Position { | ||
11 | line: 290, | ||
12 | character: 8, | ||
13 | }, | ||
14 | end: Position { | ||
15 | line: 290, | ||
16 | character: 11, | ||
17 | }, | ||
18 | }, | ||
19 | }, | ||
20 | diagnostic: Diagnostic { | ||
21 | range: Range { | ||
22 | start: Position { | ||
23 | line: 290, | ||
24 | character: 8, | ||
25 | }, | ||
26 | end: Position { | ||
27 | line: 290, | ||
28 | character: 11, | ||
29 | }, | ||
30 | }, | ||
31 | severity: Some( | ||
32 | Hint, | ||
33 | ), | ||
34 | code: Some( | ||
35 | String( | ||
36 | "unused_variables", | ||
37 | ), | ||
38 | ), | ||
39 | source: Some( | ||
40 | "rustc", | ||
41 | ), | ||
42 | message: "unused variable: `foo`\n#[warn(unused_variables)] on by default", | ||
43 | related_information: None, | ||
44 | tags: Some( | ||
45 | [ | ||
46 | Unnecessary, | ||
47 | ], | ||
48 | ), | ||
49 | }, | ||
50 | fixes: [ | ||
51 | CodeAction { | ||
52 | title: "consider prefixing with an underscore", | ||
53 | id: None, | ||
54 | group: None, | ||
55 | kind: Some( | ||
56 | "quickfix", | ||
57 | ), | ||
58 | command: None, | ||
59 | edit: Some( | ||
60 | SnippetWorkspaceEdit { | ||
61 | changes: Some( | ||
62 | { | ||
63 | "file:///test/driver/subcommand/repl.rs": [ | ||
64 | TextEdit { | ||
65 | range: Range { | ||
66 | start: Position { | ||
67 | line: 290, | ||
68 | character: 8, | ||
69 | }, | ||
70 | end: Position { | ||
71 | line: 290, | ||
72 | character: 11, | ||
73 | }, | ||
74 | }, | ||
75 | new_text: "_foo", | ||
76 | }, | ||
77 | ], | ||
78 | }, | ||
79 | ), | ||
80 | document_changes: None, | ||
81 | }, | ||
82 | ), | ||
83 | }, | ||
84 | ], | ||
85 | }, | ||
86 | ] | ||
diff --git a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_info.snap b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_info.snap new file mode 100644 index 000000000..85fd050fd --- /dev/null +++ b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_info.snap | |||
@@ -0,0 +1,86 @@ | |||
1 | --- | ||
2 | source: crates/rust-analyzer/src/diagnostics/to_proto.rs | ||
3 | expression: diag | ||
4 | --- | ||
5 | [ | ||
6 | MappedRustDiagnostic { | ||
7 | location: Location { | ||
8 | uri: "file:///test/driver/subcommand/repl.rs", | ||
9 | range: Range { | ||
10 | start: Position { | ||
11 | line: 290, | ||
12 | character: 8, | ||
13 | }, | ||
14 | end: Position { | ||
15 | line: 290, | ||
16 | character: 11, | ||
17 | }, | ||
18 | }, | ||
19 | }, | ||
20 | diagnostic: Diagnostic { | ||
21 | range: Range { | ||
22 | start: Position { | ||
23 | line: 290, | ||
24 | character: 8, | ||
25 | }, | ||
26 | end: Position { | ||
27 | line: 290, | ||
28 | character: 11, | ||
29 | }, | ||
30 | }, | ||
31 | severity: Some( | ||
32 | Information, | ||
33 | ), | ||
34 | code: Some( | ||
35 | String( | ||
36 | "unused_variables", | ||
37 | ), | ||
38 | ), | ||
39 | source: Some( | ||
40 | "rustc", | ||
41 | ), | ||
42 | message: "unused variable: `foo`\n#[warn(unused_variables)] on by default", | ||
43 | related_information: None, | ||
44 | tags: Some( | ||
45 | [ | ||
46 | Unnecessary, | ||
47 | ], | ||
48 | ), | ||
49 | }, | ||
50 | fixes: [ | ||
51 | CodeAction { | ||
52 | title: "consider prefixing with an underscore", | ||
53 | id: None, | ||
54 | group: None, | ||
55 | kind: Some( | ||
56 | "quickfix", | ||
57 | ), | ||
58 | command: None, | ||
59 | edit: Some( | ||
60 | SnippetWorkspaceEdit { | ||
61 | changes: Some( | ||
62 | { | ||
63 | "file:///test/driver/subcommand/repl.rs": [ | ||
64 | TextEdit { | ||
65 | range: Range { | ||
66 | start: Position { | ||
67 | line: 290, | ||
68 | character: 8, | ||
69 | }, | ||
70 | end: Position { | ||
71 | line: 290, | ||
72 | character: 11, | ||
73 | }, | ||
74 | }, | ||
75 | new_text: "_foo", | ||
76 | }, | ||
77 | ], | ||
78 | }, | ||
79 | ), | ||
80 | document_changes: None, | ||
81 | }, | ||
82 | ), | ||
83 | }, | ||
84 | ], | ||
85 | }, | ||
86 | ] | ||
diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs index 24ff9b280..ba74f15f3 100644 --- a/crates/rust-analyzer/src/diagnostics/to_proto.rs +++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs | |||
@@ -9,14 +9,24 @@ use lsp_types::{ | |||
9 | use ra_flycheck::{Applicability, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion}; | 9 | use ra_flycheck::{Applicability, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion}; |
10 | use stdx::format_to; | 10 | use stdx::format_to; |
11 | 11 | ||
12 | use super::DiagnosticsConfig; | ||
12 | use crate::{lsp_ext, to_proto::url_from_abs_path}; | 13 | use crate::{lsp_ext, to_proto::url_from_abs_path}; |
13 | 14 | ||
14 | /// Converts a Rust level string to a LSP severity | 15 | /// Determines the LSP severity from a diagnostic |
15 | fn map_level_to_severity(val: DiagnosticLevel) -> Option<DiagnosticSeverity> { | 16 | fn map_diagnostic_to_severity( |
16 | let res = match val { | 17 | config: &DiagnosticsConfig, |
18 | val: &ra_flycheck::Diagnostic, | ||
19 | ) -> Option<DiagnosticSeverity> { | ||
20 | let res = match val.level { | ||
17 | DiagnosticLevel::Ice => DiagnosticSeverity::Error, | 21 | DiagnosticLevel::Ice => DiagnosticSeverity::Error, |
18 | DiagnosticLevel::Error => DiagnosticSeverity::Error, | 22 | DiagnosticLevel::Error => DiagnosticSeverity::Error, |
19 | DiagnosticLevel::Warning => DiagnosticSeverity::Warning, | 23 | DiagnosticLevel::Warning => match &val.code { |
24 | Some(code) if config.warnings_as_hint.contains(&code.code) => DiagnosticSeverity::Hint, | ||
25 | Some(code) if config.warnings_as_info.contains(&code.code) => { | ||
26 | DiagnosticSeverity::Information | ||
27 | } | ||
28 | _ => DiagnosticSeverity::Warning, | ||
29 | }, | ||
20 | DiagnosticLevel::Note => DiagnosticSeverity::Information, | 30 | DiagnosticLevel::Note => DiagnosticSeverity::Information, |
21 | DiagnosticLevel::Help => DiagnosticSeverity::Hint, | 31 | DiagnosticLevel::Help => DiagnosticSeverity::Hint, |
22 | DiagnosticLevel::Unknown => return None, | 32 | DiagnosticLevel::Unknown => return None, |
@@ -172,6 +182,7 @@ pub(crate) struct MappedRustDiagnostic { | |||
172 | /// | 182 | /// |
173 | /// If the diagnostic has no primary span this will return `None` | 183 | /// If the diagnostic has no primary span this will return `None` |
174 | pub(crate) fn map_rust_diagnostic_to_lsp( | 184 | pub(crate) fn map_rust_diagnostic_to_lsp( |
185 | config: &DiagnosticsConfig, | ||
175 | rd: &ra_flycheck::Diagnostic, | 186 | rd: &ra_flycheck::Diagnostic, |
176 | workspace_root: &Path, | 187 | workspace_root: &Path, |
177 | ) -> Vec<MappedRustDiagnostic> { | 188 | ) -> Vec<MappedRustDiagnostic> { |
@@ -180,7 +191,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( | |||
180 | return Vec::new(); | 191 | return Vec::new(); |
181 | } | 192 | } |
182 | 193 | ||
183 | let severity = map_level_to_severity(rd.level); | 194 | let severity = map_diagnostic_to_severity(config, rd); |
184 | 195 | ||
185 | let mut source = String::from("rustc"); | 196 | let mut source = String::from("rustc"); |
186 | let mut code = rd.code.as_ref().map(|c| c.code.clone()); | 197 | let mut code = rd.code.as_ref().map(|c| c.code.clone()); |
@@ -328,7 +339,7 @@ mod tests { | |||
328 | ); | 339 | ); |
329 | 340 | ||
330 | let workspace_root = Path::new("/test/"); | 341 | let workspace_root = Path::new("/test/"); |
331 | let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root); | 342 | let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root); |
332 | insta::assert_debug_snapshot!(diag); | 343 | insta::assert_debug_snapshot!(diag); |
333 | } | 344 | } |
334 | 345 | ||
@@ -410,7 +421,183 @@ mod tests { | |||
410 | ); | 421 | ); |
411 | 422 | ||
412 | let workspace_root = Path::new("/test/"); | 423 | let workspace_root = Path::new("/test/"); |
413 | let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root); | 424 | let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root); |
425 | insta::assert_debug_snapshot!(diag); | ||
426 | } | ||
427 | |||
428 | #[test] | ||
429 | #[cfg(not(windows))] | ||
430 | fn snap_rustc_unused_variable_as_info() { | ||
431 | let diag = parse_diagnostic( | ||
432 | r##"{ | ||
433 | "message": "unused variable: `foo`", | ||
434 | "code": { | ||
435 | "code": "unused_variables", | ||
436 | "explanation": null | ||
437 | }, | ||
438 | "level": "warning", | ||
439 | "spans": [ | ||
440 | { | ||
441 | "file_name": "driver/subcommand/repl.rs", | ||
442 | "byte_start": 9228, | ||
443 | "byte_end": 9231, | ||
444 | "line_start": 291, | ||
445 | "line_end": 291, | ||
446 | "column_start": 9, | ||
447 | "column_end": 12, | ||
448 | "is_primary": true, | ||
449 | "text": [ | ||
450 | { | ||
451 | "text": " let foo = 42;", | ||
452 | "highlight_start": 9, | ||
453 | "highlight_end": 12 | ||
454 | } | ||
455 | ], | ||
456 | "label": null, | ||
457 | "suggested_replacement": null, | ||
458 | "suggestion_applicability": null, | ||
459 | "expansion": null | ||
460 | } | ||
461 | ], | ||
462 | "children": [ | ||
463 | { | ||
464 | "message": "#[warn(unused_variables)] on by default", | ||
465 | "code": null, | ||
466 | "level": "note", | ||
467 | "spans": [], | ||
468 | "children": [], | ||
469 | "rendered": null | ||
470 | }, | ||
471 | { | ||
472 | "message": "consider prefixing with an underscore", | ||
473 | "code": null, | ||
474 | "level": "help", | ||
475 | "spans": [ | ||
476 | { | ||
477 | "file_name": "driver/subcommand/repl.rs", | ||
478 | "byte_start": 9228, | ||
479 | "byte_end": 9231, | ||
480 | "line_start": 291, | ||
481 | "line_end": 291, | ||
482 | "column_start": 9, | ||
483 | "column_end": 12, | ||
484 | "is_primary": true, | ||
485 | "text": [ | ||
486 | { | ||
487 | "text": " let foo = 42;", | ||
488 | "highlight_start": 9, | ||
489 | "highlight_end": 12 | ||
490 | } | ||
491 | ], | ||
492 | "label": null, | ||
493 | "suggested_replacement": "_foo", | ||
494 | "suggestion_applicability": "MachineApplicable", | ||
495 | "expansion": null | ||
496 | } | ||
497 | ], | ||
498 | "children": [], | ||
499 | "rendered": null | ||
500 | } | ||
501 | ], | ||
502 | "rendered": "warning: unused variable: `foo`\n --> driver/subcommand/repl.rs:291:9\n |\n291 | let foo = 42;\n | ^^^ help: consider prefixing with an underscore: `_foo`\n |\n = note: #[warn(unused_variables)] on by default\n\n" | ||
503 | }"##, | ||
504 | ); | ||
505 | |||
506 | let config = DiagnosticsConfig { | ||
507 | warnings_as_info: vec!["unused_variables".to_string()], | ||
508 | ..DiagnosticsConfig::default() | ||
509 | }; | ||
510 | |||
511 | let workspace_root = Path::new("/test/"); | ||
512 | let diag = map_rust_diagnostic_to_lsp(&config, &diag, workspace_root); | ||
513 | insta::assert_debug_snapshot!(diag); | ||
514 | } | ||
515 | |||
516 | #[test] | ||
517 | #[cfg(not(windows))] | ||
518 | fn snap_rustc_unused_variable_as_hint() { | ||
519 | let diag = parse_diagnostic( | ||
520 | r##"{ | ||
521 | "message": "unused variable: `foo`", | ||
522 | "code": { | ||
523 | "code": "unused_variables", | ||
524 | "explanation": null | ||
525 | }, | ||
526 | "level": "warning", | ||
527 | "spans": [ | ||
528 | { | ||
529 | "file_name": "driver/subcommand/repl.rs", | ||
530 | "byte_start": 9228, | ||
531 | "byte_end": 9231, | ||
532 | "line_start": 291, | ||
533 | "line_end": 291, | ||
534 | "column_start": 9, | ||
535 | "column_end": 12, | ||
536 | "is_primary": true, | ||
537 | "text": [ | ||
538 | { | ||
539 | "text": " let foo = 42;", | ||
540 | "highlight_start": 9, | ||
541 | "highlight_end": 12 | ||
542 | } | ||
543 | ], | ||
544 | "label": null, | ||
545 | "suggested_replacement": null, | ||
546 | "suggestion_applicability": null, | ||
547 | "expansion": null | ||
548 | } | ||
549 | ], | ||
550 | "children": [ | ||
551 | { | ||
552 | "message": "#[warn(unused_variables)] on by default", | ||
553 | "code": null, | ||
554 | "level": "note", | ||
555 | "spans": [], | ||
556 | "children": [], | ||
557 | "rendered": null | ||
558 | }, | ||
559 | { | ||
560 | "message": "consider prefixing with an underscore", | ||
561 | "code": null, | ||
562 | "level": "help", | ||
563 | "spans": [ | ||
564 | { | ||
565 | "file_name": "driver/subcommand/repl.rs", | ||
566 | "byte_start": 9228, | ||
567 | "byte_end": 9231, | ||
568 | "line_start": 291, | ||
569 | "line_end": 291, | ||
570 | "column_start": 9, | ||
571 | "column_end": 12, | ||
572 | "is_primary": true, | ||
573 | "text": [ | ||
574 | { | ||
575 | "text": " let foo = 42;", | ||
576 | "highlight_start": 9, | ||
577 | "highlight_end": 12 | ||
578 | } | ||
579 | ], | ||
580 | "label": null, | ||
581 | "suggested_replacement": "_foo", | ||
582 | "suggestion_applicability": "MachineApplicable", | ||
583 | "expansion": null | ||
584 | } | ||
585 | ], | ||
586 | "children": [], | ||
587 | "rendered": null | ||
588 | } | ||
589 | ], | ||
590 | "rendered": "warning: unused variable: `foo`\n --> driver/subcommand/repl.rs:291:9\n |\n291 | let foo = 42;\n | ^^^ help: consider prefixing with an underscore: `_foo`\n |\n = note: #[warn(unused_variables)] on by default\n\n" | ||
591 | }"##, | ||
592 | ); | ||
593 | |||
594 | let config = DiagnosticsConfig { | ||
595 | warnings_as_hint: vec!["unused_variables".to_string()], | ||
596 | ..DiagnosticsConfig::default() | ||
597 | }; | ||
598 | |||
599 | let workspace_root = Path::new("/test/"); | ||
600 | let diag = map_rust_diagnostic_to_lsp(&config, &diag, workspace_root); | ||
414 | insta::assert_debug_snapshot!(diag); | 601 | insta::assert_debug_snapshot!(diag); |
415 | } | 602 | } |
416 | 603 | ||
@@ -534,7 +721,7 @@ mod tests { | |||
534 | ); | 721 | ); |
535 | 722 | ||
536 | let workspace_root = Path::new("/test/"); | 723 | let workspace_root = Path::new("/test/"); |
537 | let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root); | 724 | let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root); |
538 | insta::assert_debug_snapshot!(diag); | 725 | insta::assert_debug_snapshot!(diag); |
539 | } | 726 | } |
540 | 727 | ||
@@ -654,7 +841,7 @@ mod tests { | |||
654 | ); | 841 | ); |
655 | 842 | ||
656 | let workspace_root = Path::new("/test/"); | 843 | let workspace_root = Path::new("/test/"); |
657 | let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root); | 844 | let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root); |
658 | insta::assert_debug_snapshot!(diag); | 845 | insta::assert_debug_snapshot!(diag); |
659 | } | 846 | } |
660 | 847 | ||
@@ -697,7 +884,7 @@ mod tests { | |||
697 | ); | 884 | ); |
698 | 885 | ||
699 | let workspace_root = Path::new("/test/"); | 886 | let workspace_root = Path::new("/test/"); |
700 | let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root); | 887 | let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root); |
701 | insta::assert_debug_snapshot!(diag); | 888 | insta::assert_debug_snapshot!(diag); |
702 | } | 889 | } |
703 | 890 | ||
@@ -968,7 +1155,7 @@ mod tests { | |||
968 | ); | 1155 | ); |
969 | 1156 | ||
970 | let workspace_root = Path::new("/test/"); | 1157 | let workspace_root = Path::new("/test/"); |
971 | let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root); | 1158 | let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root); |
972 | insta::assert_debug_snapshot!(diag); | 1159 | insta::assert_debug_snapshot!(diag); |
973 | } | 1160 | } |
974 | 1161 | ||
@@ -1197,7 +1384,7 @@ mod tests { | |||
1197 | ); | 1384 | ); |
1198 | 1385 | ||
1199 | let workspace_root = Path::new("/test/"); | 1386 | let workspace_root = Path::new("/test/"); |
1200 | let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root); | 1387 | let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root); |
1201 | insta::assert_debug_snapshot!(diag); | 1388 | insta::assert_debug_snapshot!(diag); |
1202 | } | 1389 | } |
1203 | 1390 | ||
@@ -1330,7 +1517,7 @@ mod tests { | |||
1330 | ); | 1517 | ); |
1331 | 1518 | ||
1332 | let workspace_root = Path::new("/test/"); | 1519 | let workspace_root = Path::new("/test/"); |
1333 | let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root); | 1520 | let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root); |
1334 | insta::assert_debug_snapshot!(diag); | 1521 | insta::assert_debug_snapshot!(diag); |
1335 | } | 1522 | } |
1336 | } | 1523 | } |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index cc9bb1726..80cfd3c28 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -669,14 +669,11 @@ fn apply_document_changes( | |||
669 | mut line_index: Cow<'_, LineIndex>, | 669 | mut line_index: Cow<'_, LineIndex>, |
670 | content_changes: Vec<TextDocumentContentChangeEvent>, | 670 | content_changes: Vec<TextDocumentContentChangeEvent>, |
671 | ) { | 671 | ) { |
672 | // Remove when https://github.com/rust-analyzer/rust-analyzer/issues/4263 is fixed. | ||
673 | let backup_text = old_text.clone(); | ||
674 | let backup_changes = content_changes.clone(); | ||
675 | |||
676 | // The changes we got must be applied sequentially, but can cross lines so we | 672 | // The changes we got must be applied sequentially, but can cross lines so we |
677 | // have to keep our line index updated. | 673 | // have to keep our line index updated. |
678 | // Some clients (e.g. Code) sort the ranges in reverse. As an optimization, we | 674 | // Some clients (e.g. Code) sort the ranges in reverse. As an optimization, we |
679 | // remember the last valid line in the index and only rebuild it if needed. | 675 | // remember the last valid line in the index and only rebuild it if needed. |
676 | // The VFS will normalize the end of lines to `\n`. | ||
680 | enum IndexValid { | 677 | enum IndexValid { |
681 | All, | 678 | All, |
682 | UpToLineExclusive(u64), | 679 | UpToLineExclusive(u64), |
@@ -700,19 +697,7 @@ fn apply_document_changes( | |||
700 | } | 697 | } |
701 | index_valid = IndexValid::UpToLineExclusive(range.start.line); | 698 | index_valid = IndexValid::UpToLineExclusive(range.start.line); |
702 | let range = from_proto::text_range(&line_index, range); | 699 | let range = from_proto::text_range(&line_index, range); |
703 | let mut text = old_text.to_owned(); | 700 | old_text.replace_range(Range::<usize>::from(range), &change.text); |
704 | match std::panic::catch_unwind(move || { | ||
705 | text.replace_range(Range::<usize>::from(range), &change.text); | ||
706 | text | ||
707 | }) { | ||
708 | Ok(t) => *old_text = t, | ||
709 | Err(e) => { | ||
710 | eprintln!("Bug in incremental text synchronization. Please report the following output on https://github.com/rust-analyzer/rust-analyzer/issues/4263"); | ||
711 | dbg!(&backup_text); | ||
712 | dbg!(&backup_changes); | ||
713 | std::panic::resume_unwind(e); | ||
714 | } | ||
715 | } | ||
716 | } | 701 | } |
717 | None => { | 702 | None => { |
718 | *old_text = change.text; | 703 | *old_text = change.text; |
@@ -734,6 +719,7 @@ fn on_check_task( | |||
734 | 719 | ||
735 | CheckTask::AddDiagnostic { workspace_root, diagnostic } => { | 720 | CheckTask::AddDiagnostic { workspace_root, diagnostic } => { |
736 | let diagnostics = crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp( | 721 | let diagnostics = crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp( |
722 | &global_state.config.diagnostics, | ||
737 | &diagnostic, | 723 | &diagnostic, |
738 | &workspace_root, | 724 | &workspace_root, |
739 | ); | 725 | ); |
diff --git a/editors/code/package.json b/editors/code/package.json index e2027970d..3acc375f6 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -525,6 +525,24 @@ | |||
525 | "markdownDescription": "Internal config for debugging, disables loading of sysroot crates", | 525 | "markdownDescription": "Internal config for debugging, disables loading of sysroot crates", |
526 | "type": "boolean", | 526 | "type": "boolean", |
527 | "default": true | 527 | "default": true |
528 | }, | ||
529 | "rust-analyzer.diagnostics.warningsAsInfo": { | ||
530 | "type": "array", | ||
531 | "uniqueItems": true, | ||
532 | "items": { | ||
533 | "type": "string" | ||
534 | }, | ||
535 | "description": "List of warnings that should be displayed with info severity.\nThe warnings will be indicated by a blue squiggly underline in code and a blue icon in the problems panel.", | ||
536 | "default": [] | ||
537 | }, | ||
538 | "rust-analyzer.diagnostics.warningsAsHint": { | ||
539 | "type": "array", | ||
540 | "uniqueItems": true, | ||
541 | "items": { | ||
542 | "type": "string" | ||
543 | }, | ||
544 | "description": "List of warnings warnings that should be displayed with hint severity.\nThe warnings will be indicated by faded text or three dots in code and will not show up in te problems panel.", | ||
545 | "default": [] | ||
528 | } | 546 | } |
529 | } | 547 | } |
530 | }, | 548 | }, |