diff options
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r-- | crates/ra_ide/src/diagnostics.rs | 76 |
1 files changed, 39 insertions, 37 deletions
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index 0d2ff17e1..55593a8cb 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 _, DiagnosticSinkBuilder}, | 10 | diagnostics::{Diagnostic as _, DiagnosticSinkBuilder}, |
11 | HasSource, HirDisplay, Semantics, VariantDef, | 11 | HasSource, HirDisplay, Semantics, VariantDef, |
12 | }; | 12 | }; |
13 | use itertools::Itertools; | 13 | use itertools::Itertools; |
@@ -63,10 +63,10 @@ pub(crate) fn diagnostics( | |||
63 | .into(), | 63 | .into(), |
64 | ); | 64 | ); |
65 | res.borrow_mut().push(Diagnostic { | 65 | res.borrow_mut().push(Diagnostic { |
66 | range: sema.diagnostics_range(d).range, | 66 | range: sema.diagnostics_presentation_range(d).range, |
67 | message: d.message(), | 67 | message: d.message(), |
68 | severity: Severity::Error, | 68 | severity: Severity::Error, |
69 | fix: Some((fix, sema.diagnostics_fix_range(d).range)), | 69 | fix: Some((fix, sema.diagnostic_fix_source(d).syntax().text_range())), |
70 | }) | 70 | }) |
71 | }) | 71 | }) |
72 | .on::<hir::diagnostics::MissingFields, _>(|d| { | 72 | .on::<hir::diagnostics::MissingFields, _>(|d| { |
@@ -78,56 +78,58 @@ pub(crate) fn diagnostics( | |||
78 | let fix = if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) { | 78 | let fix = if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) { |
79 | None | 79 | None |
80 | } else { | 80 | } else { |
81 | let mut field_list = d.ast(db); | 81 | let record_expr = sema.diagnostic_fix_source(d); |
82 | for f in d.missed_fields.iter() { | 82 | if let Some(old_field_list) = record_expr.record_expr_field_list() { |
83 | let field = make::record_expr_field( | 83 | let mut new_field_list = old_field_list.clone(); |
84 | make::name_ref(&f.to_string()), | 84 | for f in d.missed_fields.iter() { |
85 | Some(make::expr_unit()), | 85 | let field = make::record_expr_field( |
86 | ); | 86 | make::name_ref(&f.to_string()), |
87 | field_list = field_list.append_field(&field); | 87 | Some(make::expr_unit()), |
88 | ); | ||
89 | new_field_list = new_field_list.append_field(&field); | ||
90 | } | ||
91 | |||
92 | let edit = { | ||
93 | let mut builder = TextEditBuilder::default(); | ||
94 | algo::diff(&old_field_list.syntax(), &new_field_list.syntax()) | ||
95 | .into_text_edit(&mut builder); | ||
96 | builder.finish() | ||
97 | }; | ||
98 | Some(( | ||
99 | Fix::new("Fill struct fields", SourceFileEdit { file_id, edit }.into()), | ||
100 | sema.original_range(&old_field_list.syntax()).range, | ||
101 | )) | ||
102 | } else { | ||
103 | None | ||
88 | } | 104 | } |
89 | |||
90 | let edit = { | ||
91 | let mut builder = TextEditBuilder::default(); | ||
92 | algo::diff(&d.ast(db).syntax(), &field_list.syntax()) | ||
93 | .into_text_edit(&mut builder); | ||
94 | builder.finish() | ||
95 | }; | ||
96 | Some(( | ||
97 | Fix::new("Fill struct fields", SourceFileEdit { file_id, edit }.into()), | ||
98 | sema.diagnostics_fix_range(d).range, | ||
99 | )) | ||
100 | }; | 105 | }; |
101 | 106 | ||
102 | res.borrow_mut().push(Diagnostic { | 107 | res.borrow_mut().push(Diagnostic { |
103 | range: sema.diagnostics_range(d).range, | 108 | range: sema.diagnostics_presentation_range(d).range, |
104 | message: d.message(), | 109 | message: d.message(), |
105 | severity: Severity::Error, | 110 | severity: Severity::Error, |
106 | fix, | 111 | fix, |
107 | }) | 112 | }) |
108 | }) | 113 | }) |
109 | .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| { | 114 | .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| { |
110 | let node = d.ast(db); | 115 | let tail_expr = sema.diagnostic_fix_source(d); |
111 | let replacement = format!("Ok({})", node.syntax()); | 116 | let tail_expr_range = tail_expr.syntax().text_range(); |
112 | let edit = TextEdit::replace(node.syntax().text_range(), replacement); | 117 | let edit = TextEdit::replace(tail_expr_range, format!("Ok({})", tail_expr.syntax())); |
113 | let source_change = SourceFileEdit { file_id, edit }.into(); | 118 | let source_change = SourceFileEdit { file_id, edit }.into(); |
114 | res.borrow_mut().push(Diagnostic { | 119 | res.borrow_mut().push(Diagnostic { |
115 | range: sema.diagnostics_range(d).range, | 120 | range: sema.diagnostics_presentation_range(d).range, |
116 | message: d.message(), | 121 | message: d.message(), |
117 | severity: Severity::Error, | 122 | severity: Severity::Error, |
118 | fix: Some(( | 123 | fix: Some((Fix::new("Wrap with ok", source_change), tail_expr_range)), |
119 | Fix::new("Wrap with ok", source_change), | ||
120 | sema.diagnostics_fix_range(d).range, | ||
121 | )), | ||
122 | }) | 124 | }) |
123 | }) | 125 | }) |
124 | .on::<hir::diagnostics::NoSuchField, _>(|d| { | 126 | .on::<hir::diagnostics::NoSuchField, _>(|d| { |
125 | res.borrow_mut().push(Diagnostic { | 127 | res.borrow_mut().push(Diagnostic { |
126 | range: sema.diagnostics_range(d).range, | 128 | range: sema.diagnostics_presentation_range(d).range, |
127 | message: d.message(), | 129 | message: d.message(), |
128 | severity: Severity::Error, | 130 | severity: Severity::Error, |
129 | fix: missing_struct_field_fix(&sema, file_id, d) | 131 | fix: missing_struct_field_fix(&sema, file_id, d) |
130 | .map(|fix| (fix, sema.diagnostics_fix_range(d).range)), | 132 | .map(|fix| (fix, sema.diagnostic_fix_source(d).syntax().text_range())), |
131 | }) | 133 | }) |
132 | }) | 134 | }) |
133 | // Only collect experimental diagnostics when they're enabled. | 135 | // Only collect experimental diagnostics when they're enabled. |
@@ -136,7 +138,7 @@ pub(crate) fn diagnostics( | |||
136 | .build(|d| { | 138 | .build(|d| { |
137 | res.borrow_mut().push(Diagnostic { | 139 | res.borrow_mut().push(Diagnostic { |
138 | message: d.message(), | 140 | message: d.message(), |
139 | range: sema.diagnostics_range(d).range, | 141 | range: sema.diagnostics_presentation_range(d).range, |
140 | severity: Severity::Error, | 142 | severity: Severity::Error, |
141 | fix: None, | 143 | fix: None, |
142 | }) | 144 | }) |
@@ -154,9 +156,9 @@ fn missing_struct_field_fix( | |||
154 | usage_file_id: FileId, | 156 | usage_file_id: FileId, |
155 | d: &hir::diagnostics::NoSuchField, | 157 | d: &hir::diagnostics::NoSuchField, |
156 | ) -> Option<Fix> { | 158 | ) -> Option<Fix> { |
157 | let record_expr = sema.ast(d); | 159 | let record_expr_field = sema.diagnostic_fix_source(d); |
158 | 160 | ||
159 | let record_lit = ast::RecordExpr::cast(record_expr.syntax().parent()?.parent()?)?; | 161 | let record_lit = ast::RecordExpr::cast(record_expr_field.syntax().parent()?.parent()?)?; |
160 | let def_id = sema.resolve_variant(record_lit)?; | 162 | let def_id = sema.resolve_variant(record_lit)?; |
161 | let module; | 163 | let module; |
162 | let def_file_id; | 164 | let def_file_id; |
@@ -184,12 +186,12 @@ fn missing_struct_field_fix( | |||
184 | }; | 186 | }; |
185 | let def_file_id = def_file_id.original_file(sema.db); | 187 | let def_file_id = def_file_id.original_file(sema.db); |
186 | 188 | ||
187 | let new_field_type = sema.type_of_expr(&record_expr.expr()?)?; | 189 | let new_field_type = sema.type_of_expr(&record_expr_field.expr()?)?; |
188 | if new_field_type.is_unknown() { | 190 | if new_field_type.is_unknown() { |
189 | return None; | 191 | return None; |
190 | } | 192 | } |
191 | let new_field = make::record_field( | 193 | let new_field = make::record_field( |
192 | record_expr.field_name()?, | 194 | record_expr_field.field_name()?, |
193 | make::ty(&new_field_type.display_source_code(sema.db, module.into()).ok()?), | 195 | make::ty(&new_field_type.display_source_code(sema.db, module.into()).ok()?), |
194 | ); | 196 | ); |
195 | 197 | ||