From d171838d63907d004ab935d6564bfeb4238d5540 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 27 Nov 2020 16:29:40 +0100 Subject: More accurately place proc-macro diagnostic --- crates/hir_def/src/diagnostics.rs | 5 ++++- crates/hir_def/src/nameres.rs | 41 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 4 deletions(-) (limited to 'crates/hir_def/src') diff --git a/crates/hir_def/src/diagnostics.rs b/crates/hir_def/src/diagnostics.rs index dd06e3f20..c71266dc0 100644 --- a/crates/hir_def/src/diagnostics.rs +++ b/crates/hir_def/src/diagnostics.rs @@ -6,7 +6,7 @@ use stdx::format_to; use cfg::{CfgExpr, CfgOptions, DnfExpr}; use hir_expand::diagnostics::{Diagnostic, DiagnosticCode, DiagnosticSink}; use hir_expand::{HirFileId, InFile}; -use syntax::{ast, AstPtr, SyntaxNodePtr}; +use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange}; use crate::{db::DefDatabase, DefWithBodyId}; @@ -137,6 +137,9 @@ impl Diagnostic for InactiveCode { pub struct UnresolvedProcMacro { pub file: HirFileId, pub node: SyntaxNodePtr, + /// If the diagnostic can be pinpointed more accurately than via `node`, this is the `TextRange` + /// to use instead. + pub precise_location: Option, pub macro_name: Option, } diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 3d65a46bf..ffd0381d4 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs @@ -287,7 +287,8 @@ mod diagnostics { use hir_expand::diagnostics::DiagnosticSink; use hir_expand::hygiene::Hygiene; use hir_expand::{InFile, MacroCallKind}; - use syntax::{ast, AstPtr, SyntaxNodePtr}; + use syntax::ast::AttrsOwner; + use syntax::{ast, AstNode, AstPtr, SyntaxKind, SyntaxNodePtr}; use crate::path::ModPath; use crate::{db::DefDatabase, diagnostics::*, nameres::LocalModuleId, AstId}; @@ -425,6 +426,7 @@ mod diagnostics { } DiagnosticKind::UnresolvedProcMacro { ast } => { + let mut precise_location = None; let (file, ast, name) = match ast { MacroCallKind::FnLike(ast) => { let node = ast.to_node(db.upcast()); @@ -432,14 +434,47 @@ mod diagnostics { } MacroCallKind::Attr(ast, name) => { let node = ast.to_node(db.upcast()); + + // Compute the precise location of the macro name's token in the derive + // list. + // FIXME: This does not handle paths to the macro, but neither does the + // rest of r-a. + let derive_attrs = + node.attrs().filter_map(|attr| match attr.as_simple_call() { + Some((name, args)) if name == "derive" => Some(args), + _ => None, + }); + 'outer: for attr in derive_attrs { + let tokens = + attr.syntax().children_with_tokens().filter_map(|elem| { + match elem { + syntax::NodeOrToken::Node(_) => None, + syntax::NodeOrToken::Token(tok) => Some(tok), + } + }); + for token in tokens { + if token.kind() == SyntaxKind::IDENT + && token.to_string() == *name + { + precise_location = Some(token.text_range()); + break 'outer; + } + } + } + ( ast.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), - Some(name.to_string()), + Some(name.clone()), ) } }; - sink.push(UnresolvedProcMacro { file, node: ast, macro_name: name }); + sink.push(UnresolvedProcMacro { + file, + node: ast, + precise_location, + macro_name: name, + }); } DiagnosticKind::MacroError { ast, message } => { -- cgit v1.2.3