From 21e5224484b9214648826e1b15aa9150c79a407c Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 27 Jul 2020 18:45:08 +0300 Subject: Custom ranges for missing fields --- crates/ra_hir_ty/src/diagnostics.rs | 52 +++++++++++++++++++++++++++++--- crates/ra_hir_ty/src/diagnostics/expr.rs | 1 + 2 files changed, 49 insertions(+), 4 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index 977c0525b..a5b00ed48 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; use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile}; use ra_prof::profile; -use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; +use ra_syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr}; use stdx::format_to; use crate::db::HirDatabase; @@ -61,6 +61,17 @@ pub struct MissingFields { pub file: HirFileId, pub field_list: AstPtr, pub missed_fields: Vec, + pub list_parent_path: Option>, +} + +impl MissingFields { + fn root(&self, db: &dyn AstDatabase) -> SyntaxNode { + db.parse_or_expand(self.file).unwrap() + } + + pub fn list_parent_ast(&self, db: &dyn AstDatabase) -> Option { + self.list_parent_path.as_ref().map(|path| path.to_node(&self.root(db))) + } } impl Diagnostic for MissingFields { @@ -83,9 +94,7 @@ impl AstDiagnostic for MissingFields { type AST = ast::RecordExprFieldList; fn ast(&self, db: &dyn AstDatabase) -> Self::AST { - let root = db.parse_or_expand(self.source().file_id).unwrap(); - let node = self.source().value.to_node(&root); - ast::RecordExprFieldList::cast(node).unwrap() + self.field_list.to_node(&self.root(db)) } } @@ -318,6 +327,41 @@ mod tests { assert_eq!(annotations, actual); } + #[test] + fn structure_name_highlighted_for_missing_fields() { + check_diagnostics( + r#" +struct Beefy { + one: i32, + two: i32, + three: i32, + four: i32, + five: i32, + six: i32, + seven: i32, + eight: i32, + nine: i32, + ten: i32, +} +fn baz() { + let zz = Beefy { + //^^^^^... Missing structure fields: + // | - seven + one: (), + two: (), + three: (), + four: (), + five: (), + six: (), + eight: (), + nine: (), + ten: (), + }; +} +"#, + ); + } + #[test] fn no_such_field_diagnostics() { check_diagnostics( diff --git a/crates/ra_hir_ty/src/diagnostics/expr.rs b/crates/ra_hir_ty/src/diagnostics/expr.rs index 95bbf2d95..3c37fc58e 100644 --- a/crates/ra_hir_ty/src/diagnostics/expr.rs +++ b/crates/ra_hir_ty/src/diagnostics/expr.rs @@ -111,6 +111,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { file: source_ptr.file_id, field_list: AstPtr::new(&field_list), missed_fields, + list_parent_path: record_lit.path().map(|path| AstPtr::new(&path)), }) } } -- cgit v1.2.3 From a61f2445cba2a48bb7ea6c8477e3198b297f3c67 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 27 Jul 2020 22:30:55 +0300 Subject: Less stubs --- crates/ra_hir_ty/src/diagnostics.rs | 38 ++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index a5b00ed48..73d241434 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; use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile}; use ra_prof::profile; -use ra_syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr}; +use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; use stdx::format_to; use crate::db::HirDatabase; @@ -64,16 +64,6 @@ pub struct MissingFields { pub list_parent_path: Option>, } -impl MissingFields { - fn root(&self, db: &dyn AstDatabase) -> SyntaxNode { - db.parse_or_expand(self.file).unwrap() - } - - pub fn list_parent_ast(&self, db: &dyn AstDatabase) -> Option { - self.list_parent_path.as_ref().map(|path| path.to_node(&self.root(db))) - } -} - impl Diagnostic for MissingFields { fn message(&self) -> String { let mut buf = String::from("Missing structure fields:\n"); @@ -85,16 +75,25 @@ impl Diagnostic for MissingFields { fn source(&self) -> InFile { InFile { file_id: self.file, value: self.field_list.clone().into() } } + fn as_any(&self) -> &(dyn Any + Send + 'static) { self } + + fn highlighting_source(&self) -> InFile { + self.list_parent_path + .clone() + .map(|path| InFile { file_id: self.file, value: path.into() }) + .unwrap_or_else(|| self.source()) + } } impl AstDiagnostic for MissingFields { type AST = ast::RecordExprFieldList; fn ast(&self, db: &dyn AstDatabase) -> Self::AST { - self.field_list.to_node(&self.root(db)) + let root = db.parse_or_expand(self.file).unwrap(); + self.field_list.to_node(&root) } } @@ -260,7 +259,10 @@ impl AstDiagnostic for MismatchedArgCount { #[cfg(test)] mod tests { use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId}; - use hir_expand::diagnostics::{Diagnostic, DiagnosticSinkBuilder}; + use hir_expand::{ + db::AstDatabase, + diagnostics::{Diagnostic, DiagnosticSinkBuilder}, + }; use ra_db::{fixture::WithFixture, FileId, SourceDatabase, SourceDatabaseExt}; use ra_syntax::{TextRange, TextSize}; use rustc_hash::FxHashMap; @@ -307,7 +309,9 @@ mod tests { db.diagnostics(|d| { // FXIME: macros... let file_id = d.source().file_id.original_file(&db); - let range = d.syntax_node(&db).text_range(); + let highlighting_source = d.highlighting_source(); + let node = db.parse_or_expand(highlighting_source.file_id).unwrap(); + let range = highlighting_source.value.to_node(&node).text_range(); let message = d.message().to_owned(); actual.entry(file_id).or_default().push((range, message)); }); @@ -345,7 +349,7 @@ struct Beefy { } fn baz() { let zz = Beefy { - //^^^^^... Missing structure fields: + //^^^^^ Missing structure fields: // | - seven one: (), two: (), @@ -370,8 +374,8 @@ struct S { foo: i32, bar: () } impl S { fn new() -> S { S { - //^... Missing structure fields: - //| - bar + //^ Missing structure fields: + //| - bar foo: 92, baz: 62, //^^^^^^^ no such field -- cgit v1.2.3 From ee1586c1ed058ff0f090b552d52fe6bbe2dd7f7f Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 27 Jul 2020 22:46:25 +0300 Subject: Better naming --- crates/ra_hir_ty/src/diagnostics.rs | 55 +++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 30 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index 73d241434..a4cede81d 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs @@ -37,7 +37,7 @@ impl Diagnostic for NoSuchField { "no such field".to_string() } - fn source(&self) -> InFile { + fn fix_source(&self) -> InFile { InFile::new(self.file, self.field.clone().into()) } @@ -50,9 +50,8 @@ impl AstDiagnostic for NoSuchField { type AST = ast::RecordExprField; fn ast(&self, db: &dyn AstDatabase) -> Self::AST { - let root = db.parse_or_expand(self.source().file_id).unwrap(); - let node = self.source().value.to_node(&root); - ast::RecordExprField::cast(node).unwrap() + let root = db.parse_or_expand(self.file).unwrap(); + self.field.to_node(&root) } } @@ -72,19 +71,19 @@ impl Diagnostic for MissingFields { } buf } - fn source(&self) -> InFile { + fn fix_source(&self) -> InFile { InFile { file_id: self.file, value: self.field_list.clone().into() } } - fn as_any(&self) -> &(dyn Any + Send + 'static) { - self - } - - fn highlighting_source(&self) -> InFile { + fn source(&self) -> InFile { self.list_parent_path .clone() .map(|path| InFile { file_id: self.file, value: path.into() }) - .unwrap_or_else(|| self.source()) + .unwrap_or_else(|| self.fix_source()) + } + + fn as_any(&self) -> &(dyn Any + Send + 'static) { + self } } @@ -112,7 +111,7 @@ impl Diagnostic for MissingPatFields { } buf } - fn source(&self) -> InFile { + fn fix_source(&self) -> InFile { InFile { file_id: self.file, value: self.field_list.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -131,7 +130,7 @@ impl Diagnostic for MissingMatchArms { fn message(&self) -> String { String::from("Missing match arm") } - fn source(&self) -> InFile { + fn fix_source(&self) -> InFile { InFile { file_id: self.file, value: self.match_expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -149,7 +148,7 @@ impl Diagnostic for MissingOkInTailExpr { fn message(&self) -> String { "wrap return expression in Ok".to_string() } - fn source(&self) -> InFile { + fn fix_source(&self) -> InFile { InFile { file_id: self.file, value: self.expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -162,8 +161,7 @@ impl AstDiagnostic for MissingOkInTailExpr { fn ast(&self, db: &dyn AstDatabase) -> Self::AST { let root = db.parse_or_expand(self.file).unwrap(); - let node = self.source().value.to_node(&root); - ast::Expr::cast(node).unwrap() + self.expr.to_node(&root) } } @@ -177,7 +175,7 @@ impl Diagnostic for BreakOutsideOfLoop { fn message(&self) -> String { "break outside of loop".to_string() } - fn source(&self) -> InFile { + fn fix_source(&self) -> InFile { InFile { file_id: self.file, value: self.expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -190,8 +188,7 @@ impl AstDiagnostic for BreakOutsideOfLoop { fn ast(&self, db: &dyn AstDatabase) -> Self::AST { let root = db.parse_or_expand(self.file).unwrap(); - let node = self.source().value.to_node(&root); - ast::Expr::cast(node).unwrap() + self.expr.to_node(&root) } } @@ -205,7 +202,7 @@ impl Diagnostic for MissingUnsafe { fn message(&self) -> String { format!("This operation is unsafe and requires an unsafe function or block") } - fn source(&self) -> InFile { + fn fix_source(&self) -> InFile { InFile { file_id: self.file, value: self.expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -217,9 +214,8 @@ impl AstDiagnostic for MissingUnsafe { type AST = ast::Expr; fn ast(&self, db: &dyn AstDatabase) -> Self::AST { - let root = db.parse_or_expand(self.source().file_id).unwrap(); - let node = self.source().value.to_node(&root); - ast::Expr::cast(node).unwrap() + let root = db.parse_or_expand(self.file).unwrap(); + self.expr.to_node(&root) } } @@ -236,7 +232,7 @@ impl Diagnostic for MismatchedArgCount { let s = if self.expected == 1 { "" } else { "s" }; format!("Expected {} argument{}, found {}", self.expected, s, self.found) } - fn source(&self) -> InFile { + fn fix_source(&self) -> InFile { InFile { file_id: self.file, value: self.call_expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -250,7 +246,7 @@ impl Diagnostic for MismatchedArgCount { impl AstDiagnostic for MismatchedArgCount { type AST = ast::CallExpr; fn ast(&self, db: &dyn AstDatabase) -> Self::AST { - let root = db.parse_or_expand(self.source().file_id).unwrap(); + let root = db.parse_or_expand(self.file).unwrap(); let node = self.source().value.to_node(&root); ast::CallExpr::cast(node).unwrap() } @@ -308,12 +304,11 @@ mod tests { let mut actual: FxHashMap> = FxHashMap::default(); db.diagnostics(|d| { // FXIME: macros... - let file_id = d.source().file_id.original_file(&db); - let highlighting_source = d.highlighting_source(); - let node = db.parse_or_expand(highlighting_source.file_id).unwrap(); - let range = highlighting_source.value.to_node(&node).text_range(); + let source = d.source(); + let root = db.parse_or_expand(source.file_id).unwrap(); + let range = source.value.to_node(&root).text_range(); let message = d.message().to_owned(); - actual.entry(file_id).or_default().push((range, message)); + actual.entry(source.file_id.original_file(&db)).or_default().push((range, message)); }); for (file_id, diags) in actual.iter_mut() { -- cgit v1.2.3 From cb0b13a583c0c20b57fd3529e2c01ab42bd8f04d Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 27 Jul 2020 23:32:16 +0300 Subject: Fix another missing fields diagnostics --- crates/ra_hir_ty/src/diagnostics.rs | 50 ++++++------------------- crates/ra_hir_ty/src/diagnostics/expr.rs | 5 ++- crates/ra_hir_ty/src/diagnostics/match_check.rs | 8 ++-- 3 files changed, 19 insertions(+), 44 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index a4cede81d..48b578fb0 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs @@ -59,8 +59,8 @@ impl AstDiagnostic for NoSuchField { pub struct MissingFields { pub file: HirFileId, pub field_list: AstPtr, + pub field_list_parent_path: Option>, pub missed_fields: Vec, - pub list_parent_path: Option>, } impl Diagnostic for MissingFields { @@ -76,7 +76,7 @@ impl Diagnostic for MissingFields { } fn source(&self) -> InFile { - self.list_parent_path + self.field_list_parent_path .clone() .map(|path| InFile { file_id: self.file, value: path.into() }) .unwrap_or_else(|| self.fix_source()) @@ -100,6 +100,7 @@ impl AstDiagnostic for MissingFields { pub struct MissingPatFields { pub file: HirFileId, pub field_list: AstPtr, + pub field_list_parent_path: Option>, pub missed_fields: Vec, } @@ -114,6 +115,12 @@ impl Diagnostic for MissingPatFields { fn fix_source(&self) -> InFile { InFile { file_id: self.file, value: self.field_list.clone().into() } } + fn source(&self) -> InFile { + self.field_list_parent_path + .clone() + .map(|path| InFile { file_id: self.file, value: path.into() }) + .unwrap_or_else(|| self.fix_source()) + } fn as_any(&self) -> &(dyn Any + Send + 'static) { self } @@ -326,41 +333,6 @@ mod tests { assert_eq!(annotations, actual); } - #[test] - fn structure_name_highlighted_for_missing_fields() { - check_diagnostics( - r#" -struct Beefy { - one: i32, - two: i32, - three: i32, - four: i32, - five: i32, - six: i32, - seven: i32, - eight: i32, - nine: i32, - ten: i32, -} -fn baz() { - let zz = Beefy { - //^^^^^ Missing structure fields: - // | - seven - one: (), - two: (), - three: (), - four: (), - five: (), - six: (), - eight: (), - nine: (), - ten: (), - }; -} -"#, - ); - } - #[test] fn no_such_field_diagnostics() { check_diagnostics( @@ -491,8 +463,8 @@ impl Foo { struct S { foo: i32, bar: () } fn baz(s: S) { let S { foo: _ } = s; - //^^^^^^^^^^ Missing structure fields: - // | - bar + //^ Missing structure fields: + //| - bar } "#, ); diff --git a/crates/ra_hir_ty/src/diagnostics/expr.rs b/crates/ra_hir_ty/src/diagnostics/expr.rs index 3c37fc58e..98959ab68 100644 --- a/crates/ra_hir_ty/src/diagnostics/expr.rs +++ b/crates/ra_hir_ty/src/diagnostics/expr.rs @@ -110,8 +110,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> { self.sink.push(MissingFields { file: source_ptr.file_id, field_list: AstPtr::new(&field_list), + field_list_parent_path: record_lit.path().map(|path| AstPtr::new(&path)), missed_fields, - list_parent_path: record_lit.path().map(|path| AstPtr::new(&path)), }) } } @@ -141,6 +141,9 @@ impl<'a, 'b> ExprValidator<'a, 'b> { self.sink.push(MissingPatFields { file: source_ptr.file_id, field_list: AstPtr::new(&field_list), + field_list_parent_path: record_pat + .path() + .map(|path| AstPtr::new(&path)), missed_fields, }) } diff --git a/crates/ra_hir_ty/src/diagnostics/match_check.rs b/crates/ra_hir_ty/src/diagnostics/match_check.rs index 507edcb7d..deca244db 100644 --- a/crates/ra_hir_ty/src/diagnostics/match_check.rs +++ b/crates/ra_hir_ty/src/diagnostics/match_check.rs @@ -1161,15 +1161,15 @@ fn main() { //^ Missing match arm match a { Either::A { } => (), - //^^^ Missing structure fields: - // | - foo + //^^^^^^^^^ Missing structure fields: + // | - foo Either::B => (), } match a { //^ Missing match arm Either::A { } => (), - } //^^^ Missing structure fields: - // | - foo + } //^^^^^^^^^ Missing structure fields: + // | - foo match a { Either::A { foo: true } => (), -- cgit v1.2.3 From 21184a1b2a4bea57a7666432749b171414136c60 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 27 Jul 2020 23:56:57 +0300 Subject: Restore accidentally removed public method --- crates/ra_hir_ty/src/diagnostics.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index 48b578fb0..9d29f3071 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs @@ -262,10 +262,7 @@ impl AstDiagnostic for MismatchedArgCount { #[cfg(test)] mod tests { use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId}; - use hir_expand::{ - db::AstDatabase, - diagnostics::{Diagnostic, DiagnosticSinkBuilder}, - }; + use hir_expand::diagnostics::{Diagnostic, DiagnosticSinkBuilder}; use ra_db::{fixture::WithFixture, FileId, SourceDatabase, SourceDatabaseExt}; use ra_syntax::{TextRange, TextSize}; use rustc_hash::FxHashMap; @@ -310,12 +307,11 @@ mod tests { let mut actual: FxHashMap> = FxHashMap::default(); db.diagnostics(|d| { - // FXIME: macros... - let source = d.source(); - let root = db.parse_or_expand(source.file_id).unwrap(); - let range = source.value.to_node(&root).text_range(); + // FIXME: macros... + let file_id = d.source().file_id.original_file(&db); + let range = d.syntax_node(&db).text_range(); let message = d.message().to_owned(); - actual.entry(source.file_id.original_file(&db)).or_default().push((range, message)); + actual.entry(file_id).or_default().push((range, message)); }); for (file_id, diags) in actual.iter_mut() { -- cgit v1.2.3 From cfbbd91a886e2394e7411f9d7f4966dcbd454764 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 28 Jul 2020 10:24:59 +0300 Subject: Require source implementations for Diagnostic --- crates/ra_hir_ty/src/diagnostics.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index 9d29f3071..efca09619 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs @@ -37,7 +37,7 @@ impl Diagnostic for NoSuchField { "no such field".to_string() } - fn fix_source(&self) -> InFile { + fn source(&self) -> InFile { InFile::new(self.file, self.field.clone().into()) } @@ -137,7 +137,7 @@ impl Diagnostic for MissingMatchArms { fn message(&self) -> String { String::from("Missing match arm") } - fn fix_source(&self) -> InFile { + fn source(&self) -> InFile { InFile { file_id: self.file, value: self.match_expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -155,7 +155,7 @@ impl Diagnostic for MissingOkInTailExpr { fn message(&self) -> String { "wrap return expression in Ok".to_string() } - fn fix_source(&self) -> InFile { + fn source(&self) -> InFile { InFile { file_id: self.file, value: self.expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -182,7 +182,7 @@ impl Diagnostic for BreakOutsideOfLoop { fn message(&self) -> String { "break outside of loop".to_string() } - fn fix_source(&self) -> InFile { + fn source(&self) -> InFile { InFile { file_id: self.file, value: self.expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -209,7 +209,7 @@ impl Diagnostic for MissingUnsafe { fn message(&self) -> String { format!("This operation is unsafe and requires an unsafe function or block") } - fn fix_source(&self) -> InFile { + fn source(&self) -> InFile { InFile { file_id: self.file, value: self.expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -239,7 +239,7 @@ impl Diagnostic for MismatchedArgCount { let s = if self.expected == 1 { "" } else { "s" }; format!("Expected {} argument{}, found {}", self.expected, s, self.found) } - fn fix_source(&self) -> InFile { + fn source(&self) -> InFile { InFile { file_id: self.file, value: self.call_expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { -- cgit v1.2.3 From 9963f43d51071ea02f8f6d490b9c49882034b42c Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 9 Aug 2020 01:59:26 +0300 Subject: Refactor the diagnostics --- crates/ra_hir_ty/src/diagnostics.rs | 97 +++++++++++++------------------- crates/ra_hir_ty/src/diagnostics/expr.rs | 12 ++-- 2 files changed, 44 insertions(+), 65 deletions(-) (limited to 'crates/ra_hir_ty') 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; use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile}; use ra_prof::profile; -use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; +use ra_syntax::{ast, AstPtr, SyntaxNodePtr}; use stdx::format_to; use crate::db::HirDatabase; @@ -37,7 +37,7 @@ impl Diagnostic for NoSuchField { "no such field".to_string() } - fn source(&self) -> InFile { + fn presentation(&self) -> InFile { InFile::new(self.file, self.field.clone().into()) } @@ -49,7 +49,7 @@ impl Diagnostic for NoSuchField { impl AstDiagnostic for NoSuchField { type AST = ast::RecordExprField; - fn ast(&self, db: &dyn AstDatabase) -> Self::AST { + fn fix_source(&self, db: &dyn AstDatabase) -> Self::AST { let root = db.parse_or_expand(self.file).unwrap(); self.field.to_node(&root) } @@ -58,7 +58,7 @@ impl AstDiagnostic for NoSuchField { #[derive(Debug)] pub struct MissingFields { pub file: HirFileId, - pub field_list: AstPtr, + pub field_list_parent: AstPtr, pub field_list_parent_path: Option>, pub missed_fields: Vec, } @@ -71,15 +71,16 @@ impl Diagnostic for MissingFields { } buf } - fn fix_source(&self) -> InFile { - InFile { file_id: self.file, value: self.field_list.clone().into() } - } - fn source(&self) -> InFile { - self.field_list_parent_path - .clone() - .map(|path| InFile { file_id: self.file, value: path.into() }) - .unwrap_or_else(|| self.fix_source()) + fn presentation(&self) -> InFile { + InFile { + file_id: self.file, + value: self + .field_list_parent_path + .clone() + .map(SyntaxNodePtr::from) + .unwrap_or_else(|| self.field_list_parent.clone().into()), + } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -88,18 +89,18 @@ impl Diagnostic for MissingFields { } impl AstDiagnostic for MissingFields { - type AST = ast::RecordExprFieldList; + type AST = ast::RecordExpr; - fn ast(&self, db: &dyn AstDatabase) -> Self::AST { + fn fix_source(&self, db: &dyn AstDatabase) -> Self::AST { let root = db.parse_or_expand(self.file).unwrap(); - self.field_list.to_node(&root) + self.field_list_parent.to_node(&root) } } #[derive(Debug)] pub struct MissingPatFields { pub file: HirFileId, - pub field_list: AstPtr, + pub field_list_parent: AstPtr, pub field_list_parent_path: Option>, pub missed_fields: Vec, } @@ -112,14 +113,13 @@ impl Diagnostic for MissingPatFields { } buf } - fn fix_source(&self) -> InFile { - InFile { file_id: self.file, value: self.field_list.clone().into() } - } - fn source(&self) -> InFile { - self.field_list_parent_path + fn presentation(&self) -> InFile { + let value = self + .field_list_parent_path .clone() - .map(|path| InFile { file_id: self.file, value: path.into() }) - .unwrap_or_else(|| self.fix_source()) + .map(SyntaxNodePtr::from) + .unwrap_or_else(|| self.field_list_parent.clone().into()); + InFile { file_id: self.file, value } } fn as_any(&self) -> &(dyn Any + Send + 'static) { self @@ -137,7 +137,7 @@ impl Diagnostic for MissingMatchArms { fn message(&self) -> String { String::from("Missing match arm") } - fn source(&self) -> InFile { + fn presentation(&self) -> InFile { InFile { file_id: self.file, value: self.match_expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -155,7 +155,7 @@ impl Diagnostic for MissingOkInTailExpr { fn message(&self) -> String { "wrap return expression in Ok".to_string() } - fn source(&self) -> InFile { + fn presentation(&self) -> InFile { InFile { file_id: self.file, value: self.expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -166,7 +166,7 @@ impl Diagnostic for MissingOkInTailExpr { impl AstDiagnostic for MissingOkInTailExpr { type AST = ast::Expr; - fn ast(&self, db: &dyn AstDatabase) -> Self::AST { + fn fix_source(&self, db: &dyn AstDatabase) -> Self::AST { let root = db.parse_or_expand(self.file).unwrap(); self.expr.to_node(&root) } @@ -182,7 +182,7 @@ impl Diagnostic for BreakOutsideOfLoop { fn message(&self) -> String { "break outside of loop".to_string() } - fn source(&self) -> InFile { + fn presentation(&self) -> InFile { InFile { file_id: self.file, value: self.expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -190,15 +190,6 @@ impl Diagnostic for BreakOutsideOfLoop { } } -impl AstDiagnostic for BreakOutsideOfLoop { - type AST = ast::Expr; - - fn ast(&self, db: &dyn AstDatabase) -> Self::AST { - let root = db.parse_or_expand(self.file).unwrap(); - self.expr.to_node(&root) - } -} - #[derive(Debug)] pub struct MissingUnsafe { pub file: HirFileId, @@ -209,7 +200,7 @@ impl Diagnostic for MissingUnsafe { fn message(&self) -> String { format!("This operation is unsafe and requires an unsafe function or block") } - fn source(&self) -> InFile { + fn presentation(&self) -> InFile { InFile { file_id: self.file, value: self.expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -217,15 +208,6 @@ impl Diagnostic for MissingUnsafe { } } -impl AstDiagnostic for MissingUnsafe { - type AST = ast::Expr; - - fn ast(&self, db: &dyn AstDatabase) -> Self::AST { - let root = db.parse_or_expand(self.file).unwrap(); - self.expr.to_node(&root) - } -} - #[derive(Debug)] pub struct MismatchedArgCount { pub file: HirFileId, @@ -239,7 +221,7 @@ impl Diagnostic for MismatchedArgCount { let s = if self.expected == 1 { "" } else { "s" }; format!("Expected {} argument{}, found {}", self.expected, s, self.found) } - fn source(&self) -> InFile { + fn presentation(&self) -> InFile { InFile { file_id: self.file, value: self.call_expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -250,19 +232,13 @@ impl Diagnostic for MismatchedArgCount { } } -impl AstDiagnostic for MismatchedArgCount { - type AST = ast::CallExpr; - fn ast(&self, db: &dyn AstDatabase) -> Self::AST { - let root = db.parse_or_expand(self.file).unwrap(); - let node = self.source().value.to_node(&root); - ast::CallExpr::cast(node).unwrap() - } -} - #[cfg(test)] mod tests { use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId}; - use hir_expand::diagnostics::{Diagnostic, DiagnosticSinkBuilder}; + use hir_expand::{ + db::AstDatabase, + diagnostics::{Diagnostic, DiagnosticSinkBuilder}, + }; use ra_db::{fixture::WithFixture, FileId, SourceDatabase, SourceDatabaseExt}; use ra_syntax::{TextRange, TextSize}; use rustc_hash::FxHashMap; @@ -308,8 +284,11 @@ mod tests { let mut actual: FxHashMap> = FxHashMap::default(); db.diagnostics(|d| { // FIXME: macros... - let file_id = d.source().file_id.original_file(&db); - let range = d.syntax_node(&db).text_range(); + let diagnostics_presentation = d.presentation(); + let root = db.parse_or_expand(diagnostics_presentation.file_id).unwrap(); + + let file_id = diagnostics_presentation.file_id.original_file(&db); + let range = diagnostics_presentation.value.to_node(&root).text_range(); let message = d.message().to_owned(); actual.entry(file_id).or_default().push((range, message)); }); 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> { if let Ok(source_ptr) = source_map.expr_syntax(id) { let root = source_ptr.file_syntax(db.upcast()); - if let ast::Expr::RecordExpr(record_lit) = &source_ptr.value.to_node(&root) { - if let Some(field_list) = record_lit.record_expr_field_list() { + if let ast::Expr::RecordExpr(record_expr) = &source_ptr.value.to_node(&root) { + if let Some(_) = record_expr.record_expr_field_list() { let variant_data = variant_data(db.upcast(), variant_def); let missed_fields = missed_fields .into_iter() @@ -109,8 +109,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> { .collect(); self.sink.push(MissingFields { file: source_ptr.file_id, - field_list: AstPtr::new(&field_list), - field_list_parent_path: record_lit.path().map(|path| AstPtr::new(&path)), + field_list_parent: AstPtr::new(&record_expr), + field_list_parent_path: record_expr.path().map(|path| AstPtr::new(&path)), missed_fields, }) } @@ -132,7 +132,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { if let Some(expr) = source_ptr.value.as_ref().left() { let root = source_ptr.file_syntax(db.upcast()); if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) { - if let Some(field_list) = record_pat.record_pat_field_list() { + if let Some(_) = record_pat.record_pat_field_list() { let variant_data = variant_data(db.upcast(), variant_def); let missed_fields = missed_fields .into_iter() @@ -140,7 +140,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { .collect(); self.sink.push(MissingPatFields { file: source_ptr.file_id, - field_list: AstPtr::new(&field_list), + field_list_parent: AstPtr::new(&record_pat), field_list_parent_path: record_pat .path() .map(|path| AstPtr::new(&path)), -- cgit v1.2.3 From 936861993935d5b2c78b953e2f4b719e1992bd73 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 10 Aug 2020 22:53:10 +0300 Subject: Make the fix AST source Optional --- crates/ra_hir_ty/src/diagnostics.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index 1e3a44637..b34ba5bfc 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs @@ -6,7 +6,7 @@ mod unsafe_check; use std::any::Any; use hir_def::DefWithBodyId; -use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; +use hir_expand::diagnostics::{Diagnostic, DiagnosticSink, DiagnosticWithFix}; use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile}; use ra_prof::profile; use ra_syntax::{ast, AstPtr, SyntaxNodePtr}; @@ -46,12 +46,12 @@ impl Diagnostic for NoSuchField { } } -impl AstDiagnostic for NoSuchField { +impl DiagnosticWithFix for NoSuchField { type AST = ast::RecordExprField; - fn fix_source(&self, db: &dyn AstDatabase) -> Self::AST { - let root = db.parse_or_expand(self.file).unwrap(); - self.field.to_node(&root) + fn fix_source(&self, db: &dyn AstDatabase) -> Option { + let root = db.parse_or_expand(self.file)?; + Some(self.field.to_node(&root)) } } @@ -88,12 +88,12 @@ impl Diagnostic for MissingFields { } } -impl AstDiagnostic for MissingFields { +impl DiagnosticWithFix for MissingFields { type AST = ast::RecordExpr; - fn fix_source(&self, db: &dyn AstDatabase) -> Self::AST { - let root = db.parse_or_expand(self.file).unwrap(); - self.field_list_parent.to_node(&root) + fn fix_source(&self, db: &dyn AstDatabase) -> Option { + let root = db.parse_or_expand(self.file)?; + Some(self.field_list_parent.to_node(&root)) } } @@ -163,12 +163,12 @@ impl Diagnostic for MissingOkInTailExpr { } } -impl AstDiagnostic for MissingOkInTailExpr { +impl DiagnosticWithFix for MissingOkInTailExpr { type AST = ast::Expr; - fn fix_source(&self, db: &dyn AstDatabase) -> Self::AST { - let root = db.parse_or_expand(self.file).unwrap(); - self.expr.to_node(&root) + fn fix_source(&self, db: &dyn AstDatabase) -> Option { + let root = db.parse_or_expand(self.file)?; + Some(self.expr.to_node(&root)) } } -- cgit v1.2.3 From 29fbc8e02180aac1f4d7819a9626206aa64028a0 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 11 Aug 2020 00:37:23 +0300 Subject: Move the DiagnosticsWithFix trait on the ide level --- crates/ra_hir_ty/src/diagnostics.rs | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index b34ba5bfc..24435e8a7 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs @@ -6,8 +6,8 @@ mod unsafe_check; use std::any::Any; use hir_def::DefWithBodyId; -use hir_expand::diagnostics::{Diagnostic, DiagnosticSink, DiagnosticWithFix}; -use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile}; +use hir_expand::diagnostics::{Diagnostic, DiagnosticSink}; +use hir_expand::{name::Name, HirFileId, InFile}; use ra_prof::profile; use ra_syntax::{ast, AstPtr, SyntaxNodePtr}; use stdx::format_to; @@ -46,15 +46,6 @@ impl Diagnostic for NoSuchField { } } -impl DiagnosticWithFix for NoSuchField { - type AST = ast::RecordExprField; - - fn fix_source(&self, db: &dyn AstDatabase) -> Option { - let root = db.parse_or_expand(self.file)?; - Some(self.field.to_node(&root)) - } -} - #[derive(Debug)] pub struct MissingFields { pub file: HirFileId, @@ -88,15 +79,6 @@ impl Diagnostic for MissingFields { } } -impl DiagnosticWithFix for MissingFields { - type AST = ast::RecordExpr; - - fn fix_source(&self, db: &dyn AstDatabase) -> Option { - let root = db.parse_or_expand(self.file)?; - Some(self.field_list_parent.to_node(&root)) - } -} - #[derive(Debug)] pub struct MissingPatFields { pub file: HirFileId, @@ -163,15 +145,6 @@ impl Diagnostic for MissingOkInTailExpr { } } -impl DiagnosticWithFix for MissingOkInTailExpr { - type AST = ast::Expr; - - fn fix_source(&self, db: &dyn AstDatabase) -> Option { - let root = db.parse_or_expand(self.file)?; - Some(self.expr.to_node(&root)) - } -} - #[derive(Debug)] pub struct BreakOutsideOfLoop { pub file: HirFileId, -- cgit v1.2.3 From db12ccee96bf37367b39ad99638d06da7123c088 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 11 Aug 2020 17:15:11 +0300 Subject: Better naming and docs --- crates/ra_hir_ty/src/diagnostics.rs | 39 +++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index 24435e8a7..7ab7f79db 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs @@ -37,7 +37,7 @@ impl Diagnostic for NoSuchField { "no such field".to_string() } - fn presentation(&self) -> InFile { + fn display_source(&self) -> InFile { InFile::new(self.file, self.field.clone().into()) } @@ -63,7 +63,7 @@ impl Diagnostic for MissingFields { buf } - fn presentation(&self) -> InFile { + fn display_source(&self) -> InFile { InFile { file_id: self.file, value: self @@ -95,13 +95,15 @@ impl Diagnostic for MissingPatFields { } buf } - fn presentation(&self) -> InFile { - let value = self - .field_list_parent_path - .clone() - .map(SyntaxNodePtr::from) - .unwrap_or_else(|| self.field_list_parent.clone().into()); - InFile { file_id: self.file, value } + fn display_source(&self) -> InFile { + InFile { + file_id: self.file, + value: self + .field_list_parent_path + .clone() + .map(SyntaxNodePtr::from) + .unwrap_or_else(|| self.field_list_parent.clone().into()), + } } fn as_any(&self) -> &(dyn Any + Send + 'static) { self @@ -119,7 +121,7 @@ impl Diagnostic for MissingMatchArms { fn message(&self) -> String { String::from("Missing match arm") } - fn presentation(&self) -> InFile { + fn display_source(&self) -> InFile { InFile { file_id: self.file, value: self.match_expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -137,7 +139,7 @@ impl Diagnostic for MissingOkInTailExpr { fn message(&self) -> String { "wrap return expression in Ok".to_string() } - fn presentation(&self) -> InFile { + fn display_source(&self) -> InFile { InFile { file_id: self.file, value: self.expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -155,7 +157,7 @@ impl Diagnostic for BreakOutsideOfLoop { fn message(&self) -> String { "break outside of loop".to_string() } - fn presentation(&self) -> InFile { + fn display_source(&self) -> InFile { InFile { file_id: self.file, value: self.expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -173,7 +175,7 @@ impl Diagnostic for MissingUnsafe { fn message(&self) -> String { format!("This operation is unsafe and requires an unsafe function or block") } - fn presentation(&self) -> InFile { + fn display_source(&self) -> InFile { InFile { file_id: self.file, value: self.expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -194,7 +196,7 @@ impl Diagnostic for MismatchedArgCount { let s = if self.expected == 1 { "" } else { "s" }; format!("Expected {} argument{}, found {}", self.expected, s, self.found) } - fn presentation(&self) -> InFile { + fn display_source(&self) -> InFile { InFile { file_id: self.file, value: self.call_expr.clone().into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -256,12 +258,11 @@ mod tests { let mut actual: FxHashMap> = FxHashMap::default(); db.diagnostics(|d| { + let src = d.display_source(); + let root = db.parse_or_expand(src.file_id).unwrap(); // FIXME: macros... - let diagnostics_presentation = d.presentation(); - let root = db.parse_or_expand(diagnostics_presentation.file_id).unwrap(); - - let file_id = diagnostics_presentation.file_id.original_file(&db); - let range = diagnostics_presentation.value.to_node(&root).text_range(); + let file_id = src.file_id.original_file(&db); + let range = src.value.to_node(&root).text_range(); let message = d.message().to_owned(); actual.entry(file_id).or_default().push((range, message)); }); -- cgit v1.2.3