Custom ranges for missing fields

This commit is contained in:
Kirill Bulatov 2020-07-27 18:45:08 +03:00
parent 26e102a567
commit 21e5224484
4 changed files with 56 additions and 8 deletions

View File

@ -36,8 +36,9 @@ pub trait AstDiagnostic {
impl dyn Diagnostic { impl dyn Diagnostic {
pub fn syntax_node(&self, db: &impl AstDatabase) -> SyntaxNode { pub fn syntax_node(&self, db: &impl AstDatabase) -> SyntaxNode {
let node = db.parse_or_expand(self.source().file_id).unwrap(); let source = self.source();
self.source().value.to_node(&node) let node = db.parse_or_expand(source.file_id).unwrap();
source.value.to_node(&node)
} }
pub fn downcast_ref<D: Diagnostic>(&self) -> Option<&D> { pub fn downcast_ref<D: Diagnostic>(&self) -> Option<&D> {

View File

@ -9,7 +9,7 @@ use hir_def::DefWithBodyId;
use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink};
use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile}; use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile};
use ra_prof::profile; use ra_prof::profile;
use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; use ra_syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr};
use stdx::format_to; use stdx::format_to;
use crate::db::HirDatabase; use crate::db::HirDatabase;
@ -61,6 +61,17 @@ pub struct MissingFields {
pub file: HirFileId, pub file: HirFileId,
pub field_list: AstPtr<ast::RecordExprFieldList>, pub field_list: AstPtr<ast::RecordExprFieldList>,
pub missed_fields: Vec<Name>, pub missed_fields: Vec<Name>,
pub list_parent_path: Option<AstPtr<ast::Path>>,
}
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<ast::Path> {
self.list_parent_path.as_ref().map(|path| path.to_node(&self.root(db)))
}
} }
impl Diagnostic for MissingFields { impl Diagnostic for MissingFields {
@ -83,9 +94,7 @@ impl AstDiagnostic for MissingFields {
type AST = ast::RecordExprFieldList; type AST = ast::RecordExprFieldList;
fn ast(&self, db: &dyn AstDatabase) -> Self::AST { fn ast(&self, db: &dyn AstDatabase) -> Self::AST {
let root = db.parse_or_expand(self.source().file_id).unwrap(); self.field_list.to_node(&self.root(db))
let node = self.source().value.to_node(&root);
ast::RecordExprFieldList::cast(node).unwrap()
} }
} }
@ -318,6 +327,41 @@ mod tests {
assert_eq!(annotations, actual); 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] #[test]
fn no_such_field_diagnostics() { fn no_such_field_diagnostics() {
check_diagnostics( check_diagnostics(

View File

@ -111,6 +111,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
file: source_ptr.file_id, file: source_ptr.file_id,
field_list: AstPtr::new(&field_list), field_list: AstPtr::new(&field_list),
missed_fields, missed_fields,
list_parent_path: record_lit.path().map(|path| AstPtr::new(&path)),
}) })
} }
} }

View File

@ -100,8 +100,10 @@ pub(crate) fn diagnostics(
}; };
res.borrow_mut().push(Diagnostic { res.borrow_mut().push(Diagnostic {
// TODO kb use a smaller range here range: d
range, .list_parent_ast(db)
.map(|path| path.syntax().text_range())
.unwrap_or(range),
message: d.message(), message: d.message(),
severity: Severity::Error, severity: Severity::Error,
fix, fix,