diff options
Diffstat (limited to 'crates/ra_ide/src/diagnostics.rs')
-rw-r--r-- | crates/ra_ide/src/diagnostics.rs | 127 |
1 files changed, 71 insertions, 56 deletions
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index a6b4c2c28..15dc50cf1 100644 --- a/crates/ra_ide/src/diagnostics.rs +++ b/crates/ra_ide/src/diagnostics.rs | |||
@@ -21,7 +21,7 @@ use ra_syntax::{ | |||
21 | }; | 21 | }; |
22 | use ra_text_edit::{TextEdit, TextEditBuilder}; | 22 | use ra_text_edit::{TextEdit, TextEditBuilder}; |
23 | 23 | ||
24 | use crate::{Diagnostic, FileId, FileSystemEdit, SourceChange, SourceFileEdit}; | 24 | use crate::{Diagnostic, FileId, FileSystemEdit, Fix, SourceChange, SourceFileEdit}; |
25 | 25 | ||
26 | #[derive(Debug, Copy, Clone)] | 26 | #[derive(Debug, Copy, Clone)] |
27 | pub enum Severity { | 27 | pub enum Severity { |
@@ -63,8 +63,8 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic> | |||
63 | .parent() | 63 | .parent() |
64 | .unwrap_or_else(|| RelativePath::new("")) | 64 | .unwrap_or_else(|| RelativePath::new("")) |
65 | .join(&d.candidate); | 65 | .join(&d.candidate); |
66 | let create_file = FileSystemEdit::CreateFile { source_root, path }; | 66 | let fix = |
67 | let fix = SourceChange::file_system_edit("create module", create_file); | 67 | Fix::new("Create module", FileSystemEdit::CreateFile { source_root, path }.into()); |
68 | res.borrow_mut().push(Diagnostic { | 68 | res.borrow_mut().push(Diagnostic { |
69 | range: sema.diagnostics_range(d).range, | 69 | range: sema.diagnostics_range(d).range, |
70 | message: d.message(), | 70 | message: d.message(), |
@@ -88,14 +88,12 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic> | |||
88 | field_list = field_list.append_field(&field); | 88 | field_list = field_list.append_field(&field); |
89 | } | 89 | } |
90 | 90 | ||
91 | let mut builder = TextEditBuilder::default(); | 91 | let edit = { |
92 | algo::diff(&d.ast(db).syntax(), &field_list.syntax()).into_text_edit(&mut builder); | 92 | let mut builder = TextEditBuilder::default(); |
93 | 93 | algo::diff(&d.ast(db).syntax(), &field_list.syntax()).into_text_edit(&mut builder); | |
94 | Some(SourceChange::source_file_edit_from( | 94 | builder.finish() |
95 | "fill struct fields", | 95 | }; |
96 | file_id, | 96 | Some(Fix::new("Fill struct fields", SourceFileEdit { file_id, edit }.into())) |
97 | builder.finish(), | ||
98 | )) | ||
99 | }; | 97 | }; |
100 | 98 | ||
101 | res.borrow_mut().push(Diagnostic { | 99 | res.borrow_mut().push(Diagnostic { |
@@ -117,7 +115,8 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic> | |||
117 | let node = d.ast(db); | 115 | let node = d.ast(db); |
118 | let replacement = format!("Ok({})", node.syntax()); | 116 | let replacement = format!("Ok({})", node.syntax()); |
119 | let edit = TextEdit::replace(node.syntax().text_range(), replacement); | 117 | let edit = TextEdit::replace(node.syntax().text_range(), replacement); |
120 | let fix = SourceChange::source_file_edit_from("wrap with ok", file_id, edit); | 118 | let source_change = SourceChange::source_file_edit_from(file_id, edit); |
119 | let fix = Fix::new("Wrap with ok", source_change); | ||
121 | res.borrow_mut().push(Diagnostic { | 120 | res.borrow_mut().push(Diagnostic { |
122 | range: sema.diagnostics_range(d).range, | 121 | range: sema.diagnostics_range(d).range, |
123 | message: d.message(), | 122 | message: d.message(), |
@@ -154,9 +153,9 @@ fn check_unnecessary_braces_in_use_statement( | |||
154 | range, | 153 | range, |
155 | message: "Unnecessary braces in use statement".to_string(), | 154 | message: "Unnecessary braces in use statement".to_string(), |
156 | severity: Severity::WeakWarning, | 155 | severity: Severity::WeakWarning, |
157 | fix: Some(SourceChange::source_file_edit( | 156 | fix: Some(Fix::new( |
158 | "Remove unnecessary braces", | 157 | "Remove unnecessary braces", |
159 | SourceFileEdit { file_id, edit }, | 158 | SourceFileEdit { file_id, edit }.into(), |
160 | )), | 159 | )), |
161 | }); | 160 | }); |
162 | } | 161 | } |
@@ -198,9 +197,9 @@ fn check_struct_shorthand_initialization( | |||
198 | range: record_field.syntax().text_range(), | 197 | range: record_field.syntax().text_range(), |
199 | message: "Shorthand struct initialization".to_string(), | 198 | message: "Shorthand struct initialization".to_string(), |
200 | severity: Severity::WeakWarning, | 199 | severity: Severity::WeakWarning, |
201 | fix: Some(SourceChange::source_file_edit( | 200 | fix: Some(Fix::new( |
202 | "use struct shorthand initialization", | 201 | "Use struct shorthand initialization", |
203 | SourceFileEdit { file_id, edit }, | 202 | SourceFileEdit { file_id, edit }.into(), |
204 | )), | 203 | )), |
205 | }); | 204 | }); |
206 | } | 205 | } |
@@ -240,8 +239,12 @@ mod tests { | |||
240 | let diagnostic = | 239 | let diagnostic = |
241 | diagnostics.pop().unwrap_or_else(|| panic!("no diagnostics for:\n{}\n", before)); | 240 | diagnostics.pop().unwrap_or_else(|| panic!("no diagnostics for:\n{}\n", before)); |
242 | let mut fix = diagnostic.fix.unwrap(); | 241 | let mut fix = diagnostic.fix.unwrap(); |
243 | let edit = fix.source_file_edits.pop().unwrap().edit; | 242 | let edit = fix.source_change.source_file_edits.pop().unwrap().edit; |
244 | let actual = edit.apply(&before); | 243 | let actual = { |
244 | let mut actual = before.to_string(); | ||
245 | edit.apply(&mut actual); | ||
246 | actual | ||
247 | }; | ||
245 | assert_eq_text!(after, &actual); | 248 | assert_eq_text!(after, &actual); |
246 | } | 249 | } |
247 | 250 | ||
@@ -254,9 +257,13 @@ mod tests { | |||
254 | let (analysis, file_position) = analysis_and_position(fixture); | 257 | let (analysis, file_position) = analysis_and_position(fixture); |
255 | let diagnostic = analysis.diagnostics(file_position.file_id).unwrap().pop().unwrap(); | 258 | let diagnostic = analysis.diagnostics(file_position.file_id).unwrap().pop().unwrap(); |
256 | let mut fix = diagnostic.fix.unwrap(); | 259 | let mut fix = diagnostic.fix.unwrap(); |
257 | let edit = fix.source_file_edits.pop().unwrap().edit; | 260 | let edit = fix.source_change.source_file_edits.pop().unwrap().edit; |
258 | let target_file_contents = analysis.file_text(file_position.file_id).unwrap(); | 261 | let target_file_contents = analysis.file_text(file_position.file_id).unwrap(); |
259 | let actual = edit.apply(&target_file_contents); | 262 | let actual = { |
263 | let mut actual = target_file_contents.to_string(); | ||
264 | edit.apply(&mut actual); | ||
265 | actual | ||
266 | }; | ||
260 | 267 | ||
261 | // Strip indent and empty lines from `after`, to match the behaviour of | 268 | // Strip indent and empty lines from `after`, to match the behaviour of |
262 | // `parse_fixture` called from `analysis_and_position`. | 269 | // `parse_fixture` called from `analysis_and_position`. |
@@ -287,8 +294,12 @@ mod tests { | |||
287 | let (analysis, file_id) = single_file(before); | 294 | let (analysis, file_id) = single_file(before); |
288 | let diagnostic = analysis.diagnostics(file_id).unwrap().pop().unwrap(); | 295 | let diagnostic = analysis.diagnostics(file_id).unwrap().pop().unwrap(); |
289 | let mut fix = diagnostic.fix.unwrap(); | 296 | let mut fix = diagnostic.fix.unwrap(); |
290 | let edit = fix.source_file_edits.pop().unwrap().edit; | 297 | let edit = fix.source_change.source_file_edits.pop().unwrap().edit; |
291 | let actual = edit.apply(&before); | 298 | let actual = { |
299 | let mut actual = before.to_string(); | ||
300 | edit.apply(&mut actual); | ||
301 | actual | ||
302 | }; | ||
292 | assert_eq_text!(after, &actual); | 303 | assert_eq_text!(after, &actual); |
293 | } | 304 | } |
294 | 305 | ||
@@ -604,22 +615,24 @@ mod tests { | |||
604 | Diagnostic { | 615 | Diagnostic { |
605 | message: "unresolved module", | 616 | message: "unresolved module", |
606 | range: 0..8, | 617 | range: 0..8, |
618 | severity: Error, | ||
607 | fix: Some( | 619 | fix: Some( |
608 | SourceChange { | 620 | Fix { |
609 | label: "create module", | 621 | label: "Create module", |
610 | source_file_edits: [], | 622 | source_change: SourceChange { |
611 | file_system_edits: [ | 623 | source_file_edits: [], |
612 | CreateFile { | 624 | file_system_edits: [ |
613 | source_root: SourceRootId( | 625 | CreateFile { |
614 | 0, | 626 | source_root: SourceRootId( |
615 | ), | 627 | 0, |
616 | path: "foo.rs", | 628 | ), |
617 | }, | 629 | path: "foo.rs", |
618 | ], | 630 | }, |
619 | cursor_position: None, | 631 | ], |
632 | is_snippet: false, | ||
633 | }, | ||
620 | }, | 634 | }, |
621 | ), | 635 | ), |
622 | severity: Error, | ||
623 | }, | 636 | }, |
624 | ] | 637 | ] |
625 | "###); | 638 | "###); |
@@ -651,31 +664,33 @@ mod tests { | |||
651 | assert_debug_snapshot!(diagnostics, @r###" | 664 | assert_debug_snapshot!(diagnostics, @r###" |
652 | [ | 665 | [ |
653 | Diagnostic { | 666 | Diagnostic { |
654 | message: "Missing structure fields:\n- b", | 667 | message: "Missing structure fields:\n- b\n", |
655 | range: 224..233, | 668 | range: 224..233, |
669 | severity: Error, | ||
656 | fix: Some( | 670 | fix: Some( |
657 | SourceChange { | 671 | Fix { |
658 | label: "fill struct fields", | 672 | label: "Fill struct fields", |
659 | source_file_edits: [ | 673 | source_change: SourceChange { |
660 | SourceFileEdit { | 674 | source_file_edits: [ |
661 | file_id: FileId( | 675 | SourceFileEdit { |
662 | 1, | 676 | file_id: FileId( |
663 | ), | 677 | 1, |
664 | edit: TextEdit { | 678 | ), |
665 | atoms: [ | 679 | edit: TextEdit { |
666 | AtomTextEdit { | 680 | indels: [ |
667 | delete: 3..9, | 681 | Indel { |
668 | insert: "{a:42, b: ()}", | 682 | insert: "{a:42, b: ()}", |
669 | }, | 683 | delete: 3..9, |
670 | ], | 684 | }, |
685 | ], | ||
686 | }, | ||
671 | }, | 687 | }, |
672 | }, | 688 | ], |
673 | ], | 689 | file_system_edits: [], |
674 | file_system_edits: [], | 690 | is_snippet: false, |
675 | cursor_position: None, | 691 | }, |
676 | }, | 692 | }, |
677 | ), | 693 | ), |
678 | severity: Error, | ||
679 | }, | 694 | }, |
680 | ] | 695 | ] |
681 | "###); | 696 | "###); |