diff options
author | Kirill Bulatov <[email protected]> | 2020-08-08 23:59:26 +0100 |
---|---|---|
committer | Kirill Bulatov <[email protected]> | 2020-08-11 13:09:08 +0100 |
commit | 9963f43d51071ea02f8f6d490b9c49882034b42c (patch) | |
tree | 7ecdbbd66fb8c988989e6de17c77ab14262589c0 /crates/ra_hir_ty | |
parent | cfbbd91a886e2394e7411f9d7f4966dcbd454764 (diff) |
Refactor the diagnostics
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r-- | crates/ra_hir_ty/src/diagnostics.rs | 97 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/diagnostics/expr.rs | 12 |
2 files changed, 44 insertions, 65 deletions
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index efca09619..1e3a44637 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs | |||
@@ -9,7 +9,7 @@ use hir_def::DefWithBodyId; | |||
9 | use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; | 9 | use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; |
10 | use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile}; | 10 | use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile}; |
11 | use ra_prof::profile; | 11 | use ra_prof::profile; |
12 | use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; | 12 | use ra_syntax::{ast, AstPtr, SyntaxNodePtr}; |
13 | use stdx::format_to; | 13 | use stdx::format_to; |
14 | 14 | ||
15 | use crate::db::HirDatabase; | 15 | use crate::db::HirDatabase; |
@@ -37,7 +37,7 @@ impl Diagnostic for NoSuchField { | |||
37 | "no such field".to_string() | 37 | "no such field".to_string() |
38 | } | 38 | } |
39 | 39 | ||
40 | fn source(&self) -> InFile<SyntaxNodePtr> { | 40 | fn presentation(&self) -> InFile<SyntaxNodePtr> { |
41 | InFile::new(self.file, self.field.clone().into()) | 41 | InFile::new(self.file, self.field.clone().into()) |
42 | } | 42 | } |
43 | 43 | ||
@@ -49,7 +49,7 @@ impl Diagnostic for NoSuchField { | |||
49 | impl AstDiagnostic for NoSuchField { | 49 | impl AstDiagnostic for NoSuchField { |
50 | type AST = ast::RecordExprField; | 50 | type AST = ast::RecordExprField; |
51 | 51 | ||
52 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST { | 52 | fn fix_source(&self, db: &dyn AstDatabase) -> Self::AST { |
53 | let root = db.parse_or_expand(self.file).unwrap(); | 53 | let root = db.parse_or_expand(self.file).unwrap(); |
54 | self.field.to_node(&root) | 54 | self.field.to_node(&root) |
55 | } | 55 | } |
@@ -58,7 +58,7 @@ impl AstDiagnostic for NoSuchField { | |||
58 | #[derive(Debug)] | 58 | #[derive(Debug)] |
59 | pub struct MissingFields { | 59 | pub struct MissingFields { |
60 | pub file: HirFileId, | 60 | pub file: HirFileId, |
61 | pub field_list: AstPtr<ast::RecordExprFieldList>, | 61 | pub field_list_parent: AstPtr<ast::RecordExpr>, |
62 | pub field_list_parent_path: Option<AstPtr<ast::Path>>, | 62 | pub field_list_parent_path: Option<AstPtr<ast::Path>>, |
63 | pub missed_fields: Vec<Name>, | 63 | pub missed_fields: Vec<Name>, |
64 | } | 64 | } |
@@ -71,15 +71,16 @@ impl Diagnostic for MissingFields { | |||
71 | } | 71 | } |
72 | buf | 72 | buf |
73 | } | 73 | } |
74 | fn fix_source(&self) -> InFile<SyntaxNodePtr> { | ||
75 | InFile { file_id: self.file, value: self.field_list.clone().into() } | ||
76 | } | ||
77 | 74 | ||
78 | fn source(&self) -> InFile<SyntaxNodePtr> { | 75 | fn presentation(&self) -> InFile<SyntaxNodePtr> { |
79 | self.field_list_parent_path | 76 | InFile { |
80 | .clone() | 77 | file_id: self.file, |
81 | .map(|path| InFile { file_id: self.file, value: path.into() }) | 78 | value: self |
82 | .unwrap_or_else(|| self.fix_source()) | 79 | .field_list_parent_path |
80 | .clone() | ||
81 | .map(SyntaxNodePtr::from) | ||
82 | .unwrap_or_else(|| self.field_list_parent.clone().into()), | ||
83 | } | ||
83 | } | 84 | } |
84 | 85 | ||
85 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 86 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
@@ -88,18 +89,18 @@ impl Diagnostic for MissingFields { | |||
88 | } | 89 | } |
89 | 90 | ||
90 | impl AstDiagnostic for MissingFields { | 91 | impl AstDiagnostic for MissingFields { |
91 | type AST = ast::RecordExprFieldList; | 92 | type AST = ast::RecordExpr; |
92 | 93 | ||
93 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST { | 94 | fn fix_source(&self, db: &dyn AstDatabase) -> Self::AST { |
94 | let root = db.parse_or_expand(self.file).unwrap(); | 95 | let root = db.parse_or_expand(self.file).unwrap(); |
95 | self.field_list.to_node(&root) | 96 | self.field_list_parent.to_node(&root) |
96 | } | 97 | } |
97 | } | 98 | } |
98 | 99 | ||
99 | #[derive(Debug)] | 100 | #[derive(Debug)] |
100 | pub struct MissingPatFields { | 101 | pub struct MissingPatFields { |
101 | pub file: HirFileId, | 102 | pub file: HirFileId, |
102 | pub field_list: AstPtr<ast::RecordPatFieldList>, | 103 | pub field_list_parent: AstPtr<ast::RecordPat>, |
103 | pub field_list_parent_path: Option<AstPtr<ast::Path>>, | 104 | pub field_list_parent_path: Option<AstPtr<ast::Path>>, |
104 | pub missed_fields: Vec<Name>, | 105 | pub missed_fields: Vec<Name>, |
105 | } | 106 | } |
@@ -112,14 +113,13 @@ impl Diagnostic for MissingPatFields { | |||
112 | } | 113 | } |
113 | buf | 114 | buf |
114 | } | 115 | } |
115 | fn fix_source(&self) -> InFile<SyntaxNodePtr> { | 116 | fn presentation(&self) -> InFile<SyntaxNodePtr> { |
116 | InFile { file_id: self.file, value: self.field_list.clone().into() } | 117 | let value = self |
117 | } | 118 | .field_list_parent_path |
118 | fn source(&self) -> InFile<SyntaxNodePtr> { | ||
119 | self.field_list_parent_path | ||
120 | .clone() | 119 | .clone() |
121 | .map(|path| InFile { file_id: self.file, value: path.into() }) | 120 | .map(SyntaxNodePtr::from) |
122 | .unwrap_or_else(|| self.fix_source()) | 121 | .unwrap_or_else(|| self.field_list_parent.clone().into()); |
122 | InFile { file_id: self.file, value } | ||
123 | } | 123 | } |
124 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 124 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
125 | self | 125 | self |
@@ -137,7 +137,7 @@ impl Diagnostic for MissingMatchArms { | |||
137 | fn message(&self) -> String { | 137 | fn message(&self) -> String { |
138 | String::from("Missing match arm") | 138 | String::from("Missing match arm") |
139 | } | 139 | } |
140 | fn source(&self) -> InFile<SyntaxNodePtr> { | 140 | fn presentation(&self) -> InFile<SyntaxNodePtr> { |
141 | InFile { file_id: self.file, value: self.match_expr.clone().into() } | 141 | InFile { file_id: self.file, value: self.match_expr.clone().into() } |
142 | } | 142 | } |
143 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 143 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
@@ -155,7 +155,7 @@ impl Diagnostic for MissingOkInTailExpr { | |||
155 | fn message(&self) -> String { | 155 | fn message(&self) -> String { |
156 | "wrap return expression in Ok".to_string() | 156 | "wrap return expression in Ok".to_string() |
157 | } | 157 | } |
158 | fn source(&self) -> InFile<SyntaxNodePtr> { | 158 | fn presentation(&self) -> InFile<SyntaxNodePtr> { |
159 | InFile { file_id: self.file, value: self.expr.clone().into() } | 159 | InFile { file_id: self.file, value: self.expr.clone().into() } |
160 | } | 160 | } |
161 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 161 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
@@ -166,7 +166,7 @@ impl Diagnostic for MissingOkInTailExpr { | |||
166 | impl AstDiagnostic for MissingOkInTailExpr { | 166 | impl AstDiagnostic for MissingOkInTailExpr { |
167 | type AST = ast::Expr; | 167 | type AST = ast::Expr; |
168 | 168 | ||
169 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST { | 169 | fn fix_source(&self, db: &dyn AstDatabase) -> Self::AST { |
170 | let root = db.parse_or_expand(self.file).unwrap(); | 170 | let root = db.parse_or_expand(self.file).unwrap(); |
171 | self.expr.to_node(&root) | 171 | self.expr.to_node(&root) |
172 | } | 172 | } |
@@ -182,7 +182,7 @@ impl Diagnostic for BreakOutsideOfLoop { | |||
182 | fn message(&self) -> String { | 182 | fn message(&self) -> String { |
183 | "break outside of loop".to_string() | 183 | "break outside of loop".to_string() |
184 | } | 184 | } |
185 | fn source(&self) -> InFile<SyntaxNodePtr> { | 185 | fn presentation(&self) -> InFile<SyntaxNodePtr> { |
186 | InFile { file_id: self.file, value: self.expr.clone().into() } | 186 | InFile { file_id: self.file, value: self.expr.clone().into() } |
187 | } | 187 | } |
188 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 188 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
@@ -190,15 +190,6 @@ impl Diagnostic for BreakOutsideOfLoop { | |||
190 | } | 190 | } |
191 | } | 191 | } |
192 | 192 | ||
193 | impl AstDiagnostic for BreakOutsideOfLoop { | ||
194 | type AST = ast::Expr; | ||
195 | |||
196 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST { | ||
197 | let root = db.parse_or_expand(self.file).unwrap(); | ||
198 | self.expr.to_node(&root) | ||
199 | } | ||
200 | } | ||
201 | |||
202 | #[derive(Debug)] | 193 | #[derive(Debug)] |
203 | pub struct MissingUnsafe { | 194 | pub struct MissingUnsafe { |
204 | pub file: HirFileId, | 195 | pub file: HirFileId, |
@@ -209,7 +200,7 @@ impl Diagnostic for MissingUnsafe { | |||
209 | fn message(&self) -> String { | 200 | fn message(&self) -> String { |
210 | format!("This operation is unsafe and requires an unsafe function or block") | 201 | format!("This operation is unsafe and requires an unsafe function or block") |
211 | } | 202 | } |
212 | fn source(&self) -> InFile<SyntaxNodePtr> { | 203 | fn presentation(&self) -> InFile<SyntaxNodePtr> { |
213 | InFile { file_id: self.file, value: self.expr.clone().into() } | 204 | InFile { file_id: self.file, value: self.expr.clone().into() } |
214 | } | 205 | } |
215 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 206 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
@@ -217,15 +208,6 @@ impl Diagnostic for MissingUnsafe { | |||
217 | } | 208 | } |
218 | } | 209 | } |
219 | 210 | ||
220 | impl AstDiagnostic for MissingUnsafe { | ||
221 | type AST = ast::Expr; | ||
222 | |||
223 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST { | ||
224 | let root = db.parse_or_expand(self.file).unwrap(); | ||
225 | self.expr.to_node(&root) | ||
226 | } | ||
227 | } | ||
228 | |||
229 | #[derive(Debug)] | 211 | #[derive(Debug)] |
230 | pub struct MismatchedArgCount { | 212 | pub struct MismatchedArgCount { |
231 | pub file: HirFileId, | 213 | pub file: HirFileId, |
@@ -239,7 +221,7 @@ impl Diagnostic for MismatchedArgCount { | |||
239 | let s = if self.expected == 1 { "" } else { "s" }; | 221 | let s = if self.expected == 1 { "" } else { "s" }; |
240 | format!("Expected {} argument{}, found {}", self.expected, s, self.found) | 222 | format!("Expected {} argument{}, found {}", self.expected, s, self.found) |
241 | } | 223 | } |
242 | fn source(&self) -> InFile<SyntaxNodePtr> { | 224 | fn presentation(&self) -> InFile<SyntaxNodePtr> { |
243 | InFile { file_id: self.file, value: self.call_expr.clone().into() } | 225 | InFile { file_id: self.file, value: self.call_expr.clone().into() } |
244 | } | 226 | } |
245 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 227 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
@@ -250,19 +232,13 @@ impl Diagnostic for MismatchedArgCount { | |||
250 | } | 232 | } |
251 | } | 233 | } |
252 | 234 | ||
253 | impl AstDiagnostic for MismatchedArgCount { | ||
254 | type AST = ast::CallExpr; | ||
255 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST { | ||
256 | let root = db.parse_or_expand(self.file).unwrap(); | ||
257 | let node = self.source().value.to_node(&root); | ||
258 | ast::CallExpr::cast(node).unwrap() | ||
259 | } | ||
260 | } | ||
261 | |||
262 | #[cfg(test)] | 235 | #[cfg(test)] |
263 | mod tests { | 236 | mod tests { |
264 | use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId}; | 237 | use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId}; |
265 | use hir_expand::diagnostics::{Diagnostic, DiagnosticSinkBuilder}; | 238 | use hir_expand::{ |
239 | db::AstDatabase, | ||
240 | diagnostics::{Diagnostic, DiagnosticSinkBuilder}, | ||
241 | }; | ||
266 | use ra_db::{fixture::WithFixture, FileId, SourceDatabase, SourceDatabaseExt}; | 242 | use ra_db::{fixture::WithFixture, FileId, SourceDatabase, SourceDatabaseExt}; |
267 | use ra_syntax::{TextRange, TextSize}; | 243 | use ra_syntax::{TextRange, TextSize}; |
268 | use rustc_hash::FxHashMap; | 244 | use rustc_hash::FxHashMap; |
@@ -308,8 +284,11 @@ mod tests { | |||
308 | let mut actual: FxHashMap<FileId, Vec<(TextRange, String)>> = FxHashMap::default(); | 284 | let mut actual: FxHashMap<FileId, Vec<(TextRange, String)>> = FxHashMap::default(); |
309 | db.diagnostics(|d| { | 285 | db.diagnostics(|d| { |
310 | // FIXME: macros... | 286 | // FIXME: macros... |
311 | let file_id = d.source().file_id.original_file(&db); | 287 | let diagnostics_presentation = d.presentation(); |
312 | let range = d.syntax_node(&db).text_range(); | 288 | let root = db.parse_or_expand(diagnostics_presentation.file_id).unwrap(); |
289 | |||
290 | let file_id = diagnostics_presentation.file_id.original_file(&db); | ||
291 | let range = diagnostics_presentation.value.to_node(&root).text_range(); | ||
313 | let message = d.message().to_owned(); | 292 | let message = d.message().to_owned(); |
314 | actual.entry(file_id).or_default().push((range, message)); | 293 | actual.entry(file_id).or_default().push((range, message)); |
315 | }); | 294 | }); |
diff --git a/crates/ra_hir_ty/src/diagnostics/expr.rs b/crates/ra_hir_ty/src/diagnostics/expr.rs index 98959ab68..51adcecaf 100644 --- a/crates/ra_hir_ty/src/diagnostics/expr.rs +++ b/crates/ra_hir_ty/src/diagnostics/expr.rs | |||
@@ -100,8 +100,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
100 | 100 | ||
101 | if let Ok(source_ptr) = source_map.expr_syntax(id) { | 101 | if let Ok(source_ptr) = source_map.expr_syntax(id) { |
102 | let root = source_ptr.file_syntax(db.upcast()); | 102 | let root = source_ptr.file_syntax(db.upcast()); |
103 | if let ast::Expr::RecordExpr(record_lit) = &source_ptr.value.to_node(&root) { | 103 | if let ast::Expr::RecordExpr(record_expr) = &source_ptr.value.to_node(&root) { |
104 | if let Some(field_list) = record_lit.record_expr_field_list() { | 104 | if let Some(_) = record_expr.record_expr_field_list() { |
105 | let variant_data = variant_data(db.upcast(), variant_def); | 105 | let variant_data = variant_data(db.upcast(), variant_def); |
106 | let missed_fields = missed_fields | 106 | let missed_fields = missed_fields |
107 | .into_iter() | 107 | .into_iter() |
@@ -109,8 +109,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
109 | .collect(); | 109 | .collect(); |
110 | self.sink.push(MissingFields { | 110 | self.sink.push(MissingFields { |
111 | file: source_ptr.file_id, | 111 | file: source_ptr.file_id, |
112 | field_list: AstPtr::new(&field_list), | 112 | field_list_parent: AstPtr::new(&record_expr), |
113 | field_list_parent_path: record_lit.path().map(|path| AstPtr::new(&path)), | 113 | field_list_parent_path: record_expr.path().map(|path| AstPtr::new(&path)), |
114 | missed_fields, | 114 | missed_fields, |
115 | }) | 115 | }) |
116 | } | 116 | } |
@@ -132,7 +132,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
132 | if let Some(expr) = source_ptr.value.as_ref().left() { | 132 | if let Some(expr) = source_ptr.value.as_ref().left() { |
133 | let root = source_ptr.file_syntax(db.upcast()); | 133 | let root = source_ptr.file_syntax(db.upcast()); |
134 | if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) { | 134 | if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) { |
135 | if let Some(field_list) = record_pat.record_pat_field_list() { | 135 | if let Some(_) = record_pat.record_pat_field_list() { |
136 | let variant_data = variant_data(db.upcast(), variant_def); | 136 | let variant_data = variant_data(db.upcast(), variant_def); |
137 | let missed_fields = missed_fields | 137 | let missed_fields = missed_fields |
138 | .into_iter() | 138 | .into_iter() |
@@ -140,7 +140,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
140 | .collect(); | 140 | .collect(); |
141 | self.sink.push(MissingPatFields { | 141 | self.sink.push(MissingPatFields { |
142 | file: source_ptr.file_id, | 142 | file: source_ptr.file_id, |
143 | field_list: AstPtr::new(&field_list), | 143 | field_list_parent: AstPtr::new(&record_pat), |
144 | field_list_parent_path: record_pat | 144 | field_list_parent_path: record_pat |
145 | .path() | 145 | .path() |
146 | .map(|path| AstPtr::new(&path)), | 146 | .map(|path| AstPtr::new(&path)), |