aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide
diff options
context:
space:
mode:
authorKirill Bulatov <[email protected]>2020-08-08 23:59:26 +0100
committerKirill Bulatov <[email protected]>2020-08-11 13:09:08 +0100
commit9963f43d51071ea02f8f6d490b9c49882034b42c (patch)
tree7ecdbbd66fb8c988989e6de17c77ab14262589c0 /crates/ra_ide
parentcfbbd91a886e2394e7411f9d7f4966dcbd454764 (diff)
Refactor the diagnostics
Diffstat (limited to 'crates/ra_ide')
-rw-r--r--crates/ra_ide/src/diagnostics.rs76
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 @@
7use std::cell::RefCell; 7use std::cell::RefCell;
8 8
9use hir::{ 9use hir::{
10 diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSinkBuilder}, 10 diagnostics::{Diagnostic as _, DiagnosticSinkBuilder},
11 HasSource, HirDisplay, Semantics, VariantDef, 11 HasSource, HirDisplay, Semantics, VariantDef,
12}; 12};
13use itertools::Itertools; 13use 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