mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
More accurately place proc-macro diagnostic
This commit is contained in:
parent
0432aa0ed7
commit
d171838d63
4 changed files with 49 additions and 9 deletions
|
@ -6,7 +6,7 @@ use stdx::format_to;
|
||||||
use cfg::{CfgExpr, CfgOptions, DnfExpr};
|
use cfg::{CfgExpr, CfgOptions, DnfExpr};
|
||||||
use hir_expand::diagnostics::{Diagnostic, DiagnosticCode, DiagnosticSink};
|
use hir_expand::diagnostics::{Diagnostic, DiagnosticCode, DiagnosticSink};
|
||||||
use hir_expand::{HirFileId, InFile};
|
use hir_expand::{HirFileId, InFile};
|
||||||
use syntax::{ast, AstPtr, SyntaxNodePtr};
|
use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange};
|
||||||
|
|
||||||
use crate::{db::DefDatabase, DefWithBodyId};
|
use crate::{db::DefDatabase, DefWithBodyId};
|
||||||
|
|
||||||
|
@ -137,6 +137,9 @@ impl Diagnostic for InactiveCode {
|
||||||
pub struct UnresolvedProcMacro {
|
pub struct UnresolvedProcMacro {
|
||||||
pub file: HirFileId,
|
pub file: HirFileId,
|
||||||
pub node: SyntaxNodePtr,
|
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<TextRange>,
|
||||||
pub macro_name: Option<String>,
|
pub macro_name: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -287,7 +287,8 @@ mod diagnostics {
|
||||||
use hir_expand::diagnostics::DiagnosticSink;
|
use hir_expand::diagnostics::DiagnosticSink;
|
||||||
use hir_expand::hygiene::Hygiene;
|
use hir_expand::hygiene::Hygiene;
|
||||||
use hir_expand::{InFile, MacroCallKind};
|
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::path::ModPath;
|
||||||
use crate::{db::DefDatabase, diagnostics::*, nameres::LocalModuleId, AstId};
|
use crate::{db::DefDatabase, diagnostics::*, nameres::LocalModuleId, AstId};
|
||||||
|
@ -425,6 +426,7 @@ mod diagnostics {
|
||||||
}
|
}
|
||||||
|
|
||||||
DiagnosticKind::UnresolvedProcMacro { ast } => {
|
DiagnosticKind::UnresolvedProcMacro { ast } => {
|
||||||
|
let mut precise_location = None;
|
||||||
let (file, ast, name) = match ast {
|
let (file, ast, name) = match ast {
|
||||||
MacroCallKind::FnLike(ast) => {
|
MacroCallKind::FnLike(ast) => {
|
||||||
let node = ast.to_node(db.upcast());
|
let node = ast.to_node(db.upcast());
|
||||||
|
@ -432,14 +434,47 @@ mod diagnostics {
|
||||||
}
|
}
|
||||||
MacroCallKind::Attr(ast, name) => {
|
MacroCallKind::Attr(ast, name) => {
|
||||||
let node = ast.to_node(db.upcast());
|
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,
|
ast.file_id,
|
||||||
SyntaxNodePtr::from(AstPtr::new(&node)),
|
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 } => {
|
DiagnosticKind::MacroError { ast, message } => {
|
||||||
|
|
|
@ -143,11 +143,13 @@ pub(crate) fn diagnostics(
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.on::<hir::diagnostics::UnresolvedProcMacro, _>(|d| {
|
.on::<hir::diagnostics::UnresolvedProcMacro, _>(|d| {
|
||||||
|
// Use more accurate position if available.
|
||||||
|
let display_range =
|
||||||
|
d.precise_location.unwrap_or_else(|| sema.diagnostics_display_range(d).range);
|
||||||
|
|
||||||
// FIXME: it would be nice to tell the user whether proc macros are currently disabled
|
// FIXME: it would be nice to tell the user whether proc macros are currently disabled
|
||||||
res.borrow_mut().push(
|
res.borrow_mut()
|
||||||
Diagnostic::hint(sema.diagnostics_display_range(d).range, d.message())
|
.push(Diagnostic::hint(display_range, d.message()).with_code(Some(d.code())));
|
||||||
.with_code(Some(d.code())),
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
// Only collect experimental diagnostics when they're enabled.
|
// Only collect experimental diagnostics when they're enabled.
|
||||||
.filter(|diag| !(diag.is_experimental() && config.disable_experimental))
|
.filter(|diag| !(diag.is_experimental() && config.disable_experimental))
|
||||||
|
|
|
@ -18,7 +18,7 @@ This diagnostic is triggered if item name doesn't follow https://doc.rust-lang.o
|
||||||
|
|
||||||
|
|
||||||
=== macro-error
|
=== macro-error
|
||||||
**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/hir_def/src/diagnostics.rs#L164[diagnostics.rs]
|
**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/hir_def/src/diagnostics.rs#L167[diagnostics.rs]
|
||||||
|
|
||||||
This diagnostic is shown for macro expansion errors.
|
This diagnostic is shown for macro expansion errors.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue