diff options
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r-- | crates/ra_ide/src/diagnostics.rs | 139 |
1 files changed, 71 insertions, 68 deletions
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index e029af0dc..8e715faa4 100644 --- a/crates/ra_ide/src/diagnostics.rs +++ b/crates/ra_ide/src/diagnostics.rs | |||
@@ -7,7 +7,7 @@ | |||
7 | use std::cell::RefCell; | 7 | use std::cell::RefCell; |
8 | 8 | ||
9 | use hir::{ | 9 | use hir::{ |
10 | diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSink}, | 10 | diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSinkBuilder}, |
11 | HasSource, HirDisplay, Semantics, VariantDef, | 11 | HasSource, HirDisplay, Semantics, VariantDef, |
12 | }; | 12 | }; |
13 | use itertools::Itertools; | 13 | use itertools::Itertools; |
@@ -48,79 +48,82 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic> | |||
48 | check_struct_shorthand_initialization(&mut res, file_id, &node); | 48 | check_struct_shorthand_initialization(&mut res, file_id, &node); |
49 | } | 49 | } |
50 | let res = RefCell::new(res); | 50 | let res = RefCell::new(res); |
51 | let mut sink = DiagnosticSink::new(|d| { | 51 | let mut sink = DiagnosticSinkBuilder::new() |
52 | res.borrow_mut().push(Diagnostic { | 52 | .on::<hir::diagnostics::UnresolvedModule, _>(|d| { |
53 | message: d.message(), | 53 | let original_file = d.source().file_id.original_file(db); |
54 | range: sema.diagnostics_range(d).range, | 54 | let fix = Fix::new( |
55 | severity: Severity::Error, | 55 | "Create module", |
56 | fix: None, | 56 | FileSystemEdit::CreateFile { anchor: original_file, dst: d.candidate.clone() } |
57 | .into(), | ||
58 | ); | ||
59 | res.borrow_mut().push(Diagnostic { | ||
60 | range: sema.diagnostics_range(d).range, | ||
61 | message: d.message(), | ||
62 | severity: Severity::Error, | ||
63 | fix: Some(fix), | ||
64 | }) | ||
57 | }) | 65 | }) |
58 | }) | 66 | .on::<hir::diagnostics::MissingFields, _>(|d| { |
59 | .on::<hir::diagnostics::UnresolvedModule, _>(|d| { | 67 | // Note that although we could add a diagnostics to |
60 | let original_file = d.source().file_id.original_file(db); | 68 | // fill the missing tuple field, e.g : |
61 | let fix = Fix::new( | 69 | // `struct A(usize);` |
62 | "Create module", | 70 | // `let a = A { 0: () }` |
63 | FileSystemEdit::CreateFile { anchor: original_file, dst: d.candidate.clone() }.into(), | 71 | // but it is uncommon usage and it should not be encouraged. |
64 | ); | 72 | let fix = if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) { |
65 | res.borrow_mut().push(Diagnostic { | 73 | None |
66 | range: sema.diagnostics_range(d).range, | 74 | } else { |
67 | message: d.message(), | 75 | let mut field_list = d.ast(db); |
68 | severity: Severity::Error, | 76 | for f in d.missed_fields.iter() { |
69 | fix: Some(fix), | 77 | let field = |
70 | }) | 78 | make::record_field(make::name_ref(&f.to_string()), Some(make::expr_unit())); |
71 | }) | 79 | field_list = field_list.append_field(&field); |
72 | .on::<hir::diagnostics::MissingFields, _>(|d| { | 80 | } |
73 | // Note that although we could add a diagnostics to | 81 | |
74 | // fill the missing tuple field, e.g : | 82 | let edit = { |
75 | // `struct A(usize);` | 83 | let mut builder = TextEditBuilder::default(); |
76 | // `let a = A { 0: () }` | 84 | algo::diff(&d.ast(db).syntax(), &field_list.syntax()) |
77 | // but it is uncommon usage and it should not be encouraged. | 85 | .into_text_edit(&mut builder); |
78 | let fix = if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) { | 86 | builder.finish() |
79 | None | 87 | }; |
80 | } else { | 88 | Some(Fix::new("Fill struct fields", SourceFileEdit { file_id, edit }.into())) |
81 | let mut field_list = d.ast(db); | ||
82 | for f in d.missed_fields.iter() { | ||
83 | let field = | ||
84 | make::record_field(make::name_ref(&f.to_string()), Some(make::expr_unit())); | ||
85 | field_list = field_list.append_field(&field); | ||
86 | } | ||
87 | |||
88 | let edit = { | ||
89 | let mut builder = TextEditBuilder::default(); | ||
90 | algo::diff(&d.ast(db).syntax(), &field_list.syntax()).into_text_edit(&mut builder); | ||
91 | builder.finish() | ||
92 | }; | 89 | }; |
93 | Some(Fix::new("Fill struct fields", SourceFileEdit { file_id, edit }.into())) | ||
94 | }; | ||
95 | 90 | ||
96 | res.borrow_mut().push(Diagnostic { | 91 | res.borrow_mut().push(Diagnostic { |
97 | range: sema.diagnostics_range(d).range, | 92 | range: sema.diagnostics_range(d).range, |
98 | message: d.message(), | 93 | message: d.message(), |
99 | severity: Severity::Error, | 94 | severity: Severity::Error, |
100 | fix, | 95 | fix, |
96 | }) | ||
101 | }) | 97 | }) |
102 | }) | 98 | .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| { |
103 | .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| { | 99 | let node = d.ast(db); |
104 | let node = d.ast(db); | 100 | let replacement = format!("Ok({})", node.syntax()); |
105 | let replacement = format!("Ok({})", node.syntax()); | 101 | let edit = TextEdit::replace(node.syntax().text_range(), replacement); |
106 | let edit = TextEdit::replace(node.syntax().text_range(), replacement); | 102 | let source_change = SourceFileEdit { file_id, edit }.into(); |
107 | let source_change = SourceFileEdit { file_id, edit }.into(); | 103 | let fix = Fix::new("Wrap with ok", source_change); |
108 | let fix = Fix::new("Wrap with ok", source_change); | 104 | res.borrow_mut().push(Diagnostic { |
109 | res.borrow_mut().push(Diagnostic { | 105 | range: sema.diagnostics_range(d).range, |
110 | range: sema.diagnostics_range(d).range, | 106 | message: d.message(), |
111 | message: d.message(), | 107 | severity: Severity::Error, |
112 | severity: Severity::Error, | 108 | fix: Some(fix), |
113 | fix: Some(fix), | 109 | }) |
114 | }) | 110 | }) |
115 | }) | 111 | .on::<hir::diagnostics::NoSuchField, _>(|d| { |
116 | .on::<hir::diagnostics::NoSuchField, _>(|d| { | 112 | res.borrow_mut().push(Diagnostic { |
117 | res.borrow_mut().push(Diagnostic { | 113 | range: sema.diagnostics_range(d).range, |
118 | range: sema.diagnostics_range(d).range, | 114 | message: d.message(), |
119 | message: d.message(), | 115 | severity: Severity::Error, |
120 | severity: Severity::Error, | 116 | fix: missing_struct_field_fix(&sema, file_id, d), |
121 | fix: missing_struct_field_fix(&sema, file_id, d), | 117 | }) |
122 | }) | 118 | }) |
123 | }); | 119 | .build(|d| { |
120 | res.borrow_mut().push(Diagnostic { | ||
121 | message: d.message(), | ||
122 | range: sema.diagnostics_range(d).range, | ||
123 | severity: Severity::Error, | ||
124 | fix: None, | ||
125 | }) | ||
126 | }); | ||
124 | 127 | ||
125 | if let Some(m) = sema.to_module_def(file_id) { | 128 | if let Some(m) = sema.to_module_def(file_id) { |
126 | m.diagnostics(db, &mut sink); | 129 | m.diagnostics(db, &mut sink); |