aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_ide/src/snapshots/highlight_doctest.html6
-rw-r--r--crates/ra_ide/src/syntax_highlighting/injection.rs14
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tests.rs6
-rw-r--r--crates/rust-analyzer/src/config.rs5
-rw-r--r--crates/rust-analyzer/src/diagnostics.rs6
-rw-r--r--crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_hint.snap86
-rw-r--r--crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_info.snap86
-rw-r--r--crates/rust-analyzer/src/diagnostics/to_proto.rs213
-rw-r--r--crates/rust-analyzer/src/main_loop.rs20
9 files changed, 408 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>) -&gt; <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>) -&gt; <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
54type RangesMap = BTreeMap<TextSize, TextSize>; 54type RangesMap = BTreeMap<TextSize, TextSize>;
55 55
56const RUSTDOC_FENCE: &'static str = "```";
57const 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
10use std::{ffi::OsString, path::PathBuf}; 10use std::{ffi::OsString, path::PathBuf};
11 11
12use crate::diagnostics::DiagnosticsConfig;
12use lsp_types::ClientCapabilities; 13use lsp_types::ClientCapabilities;
13use ra_flycheck::FlycheckConfig; 14use ra_flycheck::FlycheckConfig;
14use ra_ide::{AssistConfig, CompletionConfig, HoverConfig, InlayHintsConfig}; 15use 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;
11pub type CheckFixes = Arc<HashMap<FileId, Vec<Fix>>>; 11pub type CheckFixes = Arc<HashMap<FileId, Vec<Fix>>>;
12 12
13#[derive(Debug, Default, Clone)] 13#[derive(Debug, Default, Clone)]
14pub struct DiagnosticsConfig {
15 pub warnings_as_info: Vec<String>,
16 pub warnings_as_hint: Vec<String>,
17}
18
19#[derive(Debug, Default, Clone)]
14pub struct DiagnosticCollection { 20pub 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---
2source: crates/rust-analyzer/src/diagnostics/to_proto.rs
3expression: 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---
2source: crates/rust-analyzer/src/diagnostics/to_proto.rs
3expression: 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::{
9use ra_flycheck::{Applicability, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion}; 9use ra_flycheck::{Applicability, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion};
10use stdx::format_to; 10use stdx::format_to;
11 11
12use super::DiagnosticsConfig;
12use crate::{lsp_ext, to_proto::url_from_abs_path}; 13use 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
15fn map_level_to_severity(val: DiagnosticLevel) -> Option<DiagnosticSeverity> { 16fn 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`
174pub(crate) fn map_rust_diagnostic_to_lsp( 184pub(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 );