mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-10 07:04:22 +00:00
Improve proc macro errors a bit
Distinguish between - there is no build data (for some reason?) - there is build data, but the cargo package didn't build a proc macro dylib - there is a proc macro dylib, but it didn't contain the proc macro we expected - the name did not resolve to any macro (this is now an unresolved_macro_call even for attributes) I changed the handling of disabled attribute macro expansion to immediately ignore the macro and report an unresolved_proc_macro, because otherwise they would now result in loud unresolved_macro_call errors. I hope this doesn't break anything. Also try to improve error ranges for unresolved_macro_call / macro_error by reusing the code for unresolved_proc_macro. It's not perfect but probably better than before.
This commit is contained in:
parent
32b40ded0f
commit
c80c34867f
10 changed files with 164 additions and 163 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -538,6 +538,7 @@ dependencies = [
|
||||||
"mbe",
|
"mbe",
|
||||||
"profile",
|
"profile",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
|
"stdx",
|
||||||
"syntax",
|
"syntax",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tt",
|
"tt",
|
||||||
|
|
|
@ -436,7 +436,7 @@ impl DefCollector<'_> {
|
||||||
let mut unresolved_macros = mem::take(&mut self.unresolved_macros);
|
let mut unresolved_macros = mem::take(&mut self.unresolved_macros);
|
||||||
let pos = unresolved_macros.iter().position(|directive| {
|
let pos = unresolved_macros.iter().position(|directive| {
|
||||||
if let MacroDirectiveKind::Attr { ast_id, mod_item, attr, tree } = &directive.kind {
|
if let MacroDirectiveKind::Attr { ast_id, mod_item, attr, tree } = &directive.kind {
|
||||||
self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro(
|
self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
|
||||||
directive.module_id,
|
directive.module_id,
|
||||||
MacroCallKind::Attr {
|
MacroCallKind::Attr {
|
||||||
ast_id: ast_id.ast_id,
|
ast_id: ast_id.ast_id,
|
||||||
|
@ -444,7 +444,7 @@ impl DefCollector<'_> {
|
||||||
invoc_attr_index: attr.id.ast_index,
|
invoc_attr_index: attr.id.ast_index,
|
||||||
is_derive: false,
|
is_derive: false,
|
||||||
},
|
},
|
||||||
None,
|
attr.path().clone(),
|
||||||
));
|
));
|
||||||
|
|
||||||
self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), attr.id);
|
self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), attr.id);
|
||||||
|
@ -1218,10 +1218,6 @@ impl DefCollector<'_> {
|
||||||
return recollect_without(self);
|
return recollect_without(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.db.enable_proc_attr_macros() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not resolved to a derive helper or the derive attribute, so try to treat as a normal attribute.
|
// Not resolved to a derive helper or the derive attribute, so try to treat as a normal attribute.
|
||||||
let call_id = attr_macro_as_call_id(
|
let call_id = attr_macro_as_call_id(
|
||||||
self.db,
|
self.db,
|
||||||
|
@ -1233,6 +1229,15 @@ impl DefCollector<'_> {
|
||||||
);
|
);
|
||||||
let loc: MacroCallLoc = self.db.lookup_intern_macro_call(call_id);
|
let loc: MacroCallLoc = self.db.lookup_intern_macro_call(call_id);
|
||||||
|
|
||||||
|
if !self.db.enable_proc_attr_macros() {
|
||||||
|
self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro(
|
||||||
|
directive.module_id,
|
||||||
|
loc.kind,
|
||||||
|
Some(loc.def.krate),
|
||||||
|
));
|
||||||
|
return recollect_without(self);
|
||||||
|
}
|
||||||
|
|
||||||
// Skip #[test]/#[bench] expansion, which would merely result in more memory usage
|
// Skip #[test]/#[bench] expansion, which would merely result in more memory usage
|
||||||
// due to duplicating functions into macro expansions
|
// due to duplicating functions into macro expansions
|
||||||
if matches!(
|
if matches!(
|
||||||
|
|
|
@ -20,6 +20,7 @@ hashbrown = { version = "0.12.1", features = [
|
||||||
"inline-more",
|
"inline-more",
|
||||||
], default-features = false }
|
], default-features = false }
|
||||||
|
|
||||||
|
stdx = { path = "../stdx", version = "0.0.0" }
|
||||||
base-db = { path = "../base-db", version = "0.0.0" }
|
base-db = { path = "../base-db", version = "0.0.0" }
|
||||||
cfg = { path = "../cfg", version = "0.0.0" }
|
cfg = { path = "../cfg", version = "0.0.0" }
|
||||||
syntax = { path = "../syntax", version = "0.0.0" }
|
syntax = { path = "../syntax", version = "0.0.0" }
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! Proc Macro Expander stub
|
//! Proc Macro Expander stub
|
||||||
|
|
||||||
use base_db::{CrateId, ProcMacroExpansionError, ProcMacroId, ProcMacroKind};
|
use base_db::{CrateId, ProcMacroExpansionError, ProcMacroId, ProcMacroKind};
|
||||||
|
use stdx::never;
|
||||||
|
|
||||||
use crate::{db::AstDatabase, ExpandError, ExpandResult};
|
use crate::{db::AstDatabase, ExpandError, ExpandResult};
|
||||||
|
|
||||||
|
@ -36,18 +37,20 @@ impl ProcMacroExpander {
|
||||||
let krate_graph = db.crate_graph();
|
let krate_graph = db.crate_graph();
|
||||||
let proc_macros = match &krate_graph[self.krate].proc_macro {
|
let proc_macros = match &krate_graph[self.krate].proc_macro {
|
||||||
Ok(proc_macros) => proc_macros,
|
Ok(proc_macros) => proc_macros,
|
||||||
Err(e) => {
|
Err(_) => {
|
||||||
return ExpandResult::only_err(ExpandError::Other(
|
never!("Non-dummy expander even though there are no proc macros");
|
||||||
e.clone().into_boxed_str(),
|
return ExpandResult::only_err(ExpandError::Other("Internal error".into()));
|
||||||
))
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let proc_macro = match proc_macros.get(id.0 as usize) {
|
let proc_macro = match proc_macros.get(id.0 as usize) {
|
||||||
Some(proc_macro) => proc_macro,
|
Some(proc_macro) => proc_macro,
|
||||||
None => {
|
None => {
|
||||||
return ExpandResult::only_err(ExpandError::Other(
|
never!(
|
||||||
"No proc-macro found.".into(),
|
"Proc macro index out of bounds: the length is {} but the index is {}",
|
||||||
))
|
proc_macros.len(),
|
||||||
|
id.0
|
||||||
|
);
|
||||||
|
return ExpandResult::only_err(ExpandError::Other("Internal error".into()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ pub struct UnresolvedImport {
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct UnresolvedMacroCall {
|
pub struct UnresolvedMacroCall {
|
||||||
pub macro_call: InFile<SyntaxNodePtr>,
|
pub macro_call: InFile<SyntaxNodePtr>,
|
||||||
|
pub precise_location: Option<TextRange>,
|
||||||
pub path: ModPath,
|
pub path: ModPath,
|
||||||
pub is_bang: bool,
|
pub is_bang: bool,
|
||||||
}
|
}
|
||||||
|
@ -95,6 +96,7 @@ pub struct UnresolvedProcMacro {
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct MacroError {
|
pub struct MacroError {
|
||||||
pub node: InFile<SyntaxNodePtr>,
|
pub node: InFile<SyntaxNodePtr>,
|
||||||
|
pub precise_location: Option<TextRange>,
|
||||||
pub message: String,
|
pub message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ use rustc_hash::FxHashSet;
|
||||||
use stdx::{format_to, impl_from, never};
|
use stdx::{format_to, impl_from, never};
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, HasAttrs as _, HasDocComments, HasName},
|
ast::{self, HasAttrs as _, HasDocComments, HasName},
|
||||||
AstNode, AstPtr, SmolStr, SyntaxNodePtr, T,
|
AstNode, AstPtr, SmolStr, SyntaxNodePtr, TextRange, T,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::db::{DefDatabase, HirDatabase};
|
use crate::db::{DefDatabase, HirDatabase};
|
||||||
|
@ -628,67 +628,7 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag:
|
||||||
}
|
}
|
||||||
|
|
||||||
DefDiagnosticKind::UnresolvedProcMacro { ast, krate } => {
|
DefDiagnosticKind::UnresolvedProcMacro { ast, krate } => {
|
||||||
let (node, precise_location, macro_name, kind) = match ast {
|
let (node, precise_location, macro_name, kind) = precise_macro_call_location(ast, db);
|
||||||
MacroCallKind::FnLike { ast_id, .. } => {
|
|
||||||
let node = ast_id.to_node(db.upcast());
|
|
||||||
(
|
|
||||||
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
|
|
||||||
node.path().map(|it| it.syntax().text_range()),
|
|
||||||
node.path().and_then(|it| it.segment()).map(|it| it.to_string()),
|
|
||||||
MacroKind::ProcMacro,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
MacroCallKind::Derive { ast_id, derive_attr_index, derive_index } => {
|
|
||||||
let node = ast_id.to_node(db.upcast());
|
|
||||||
// Compute the precise location of the macro name's token in the derive
|
|
||||||
// list.
|
|
||||||
let token = (|| {
|
|
||||||
let derive_attr = node
|
|
||||||
.doc_comments_and_attrs()
|
|
||||||
.nth(*derive_attr_index as usize)
|
|
||||||
.and_then(Either::left)?;
|
|
||||||
let token_tree = derive_attr.meta()?.token_tree()?;
|
|
||||||
let group_by = token_tree
|
|
||||||
.syntax()
|
|
||||||
.children_with_tokens()
|
|
||||||
.filter_map(|elem| match elem {
|
|
||||||
syntax::NodeOrToken::Token(tok) => Some(tok),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.group_by(|t| t.kind() == T![,]);
|
|
||||||
let (_, mut group) = group_by
|
|
||||||
.into_iter()
|
|
||||||
.filter(|&(comma, _)| !comma)
|
|
||||||
.nth(*derive_index as usize)?;
|
|
||||||
group.find(|t| t.kind() == T![ident])
|
|
||||||
})();
|
|
||||||
(
|
|
||||||
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
|
|
||||||
token.as_ref().map(|tok| tok.text_range()),
|
|
||||||
token.as_ref().map(ToString::to_string),
|
|
||||||
MacroKind::Derive,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
|
|
||||||
let node = ast_id.to_node(db.upcast());
|
|
||||||
let attr = node
|
|
||||||
.doc_comments_and_attrs()
|
|
||||||
.nth((*invoc_attr_index) as usize)
|
|
||||||
.and_then(Either::left)
|
|
||||||
.unwrap_or_else(|| panic!("cannot find attribute #{}", invoc_attr_index));
|
|
||||||
|
|
||||||
(
|
|
||||||
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
|
|
||||||
Some(attr.syntax().text_range()),
|
|
||||||
attr.path()
|
|
||||||
.and_then(|path| path.segment())
|
|
||||||
.and_then(|seg| seg.name_ref())
|
|
||||||
.as_ref()
|
|
||||||
.map(ToString::to_string),
|
|
||||||
MacroKind::Attr,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
acc.push(
|
acc.push(
|
||||||
UnresolvedProcMacro { node, precise_location, macro_name, kind, krate: *krate }
|
UnresolvedProcMacro { node, precise_location, macro_name, kind, krate: *krate }
|
||||||
.into(),
|
.into(),
|
||||||
|
@ -696,10 +636,11 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag:
|
||||||
}
|
}
|
||||||
|
|
||||||
DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
|
DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
|
||||||
let node = ast.to_node(db.upcast());
|
let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
|
||||||
acc.push(
|
acc.push(
|
||||||
UnresolvedMacroCall {
|
UnresolvedMacroCall {
|
||||||
macro_call: InFile::new(node.file_id, SyntaxNodePtr::new(&node.value)),
|
macro_call: node,
|
||||||
|
precise_location,
|
||||||
path: path.clone(),
|
path: path.clone(),
|
||||||
is_bang: matches!(ast, MacroCallKind::FnLike { .. }),
|
is_bang: matches!(ast, MacroCallKind::FnLike { .. }),
|
||||||
}
|
}
|
||||||
|
@ -708,23 +649,8 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag:
|
||||||
}
|
}
|
||||||
|
|
||||||
DefDiagnosticKind::MacroError { ast, message } => {
|
DefDiagnosticKind::MacroError { ast, message } => {
|
||||||
let node = match ast {
|
let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
|
||||||
MacroCallKind::FnLike { ast_id, .. } => {
|
acc.push(MacroError { node, precise_location, message: message.clone() }.into());
|
||||||
let node = ast_id.to_node(db.upcast());
|
|
||||||
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))
|
|
||||||
}
|
|
||||||
MacroCallKind::Derive { ast_id, .. } => {
|
|
||||||
// FIXME: point to the attribute instead, this creates very large diagnostics
|
|
||||||
let node = ast_id.to_node(db.upcast());
|
|
||||||
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))
|
|
||||||
}
|
|
||||||
MacroCallKind::Attr { ast_id, .. } => {
|
|
||||||
// FIXME: point to the attribute instead, this creates very large diagnostics
|
|
||||||
let node = ast_id.to_node(db.upcast());
|
|
||||||
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
acc.push(MacroError { node, message: message.clone() }.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
|
DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
|
||||||
|
@ -771,6 +697,78 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn precise_macro_call_location(
|
||||||
|
ast: &MacroCallKind,
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
) -> (InFile<SyntaxNodePtr>, Option<TextRange>, Option<String>, MacroKind) {
|
||||||
|
// FIXME: maaybe we actually want slightly different ranges for the different macro diagnostics
|
||||||
|
// - e.g. the full attribute for macro errors, but only the name for name resolution
|
||||||
|
match ast {
|
||||||
|
MacroCallKind::FnLike { ast_id, .. } => {
|
||||||
|
let node = ast_id.to_node(db.upcast());
|
||||||
|
(
|
||||||
|
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
|
||||||
|
node.path()
|
||||||
|
.and_then(|it| it.segment())
|
||||||
|
.and_then(|it| it.name_ref())
|
||||||
|
.map(|it| it.syntax().text_range()),
|
||||||
|
node.path().and_then(|it| it.segment()).map(|it| it.to_string()),
|
||||||
|
MacroKind::ProcMacro,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
MacroCallKind::Derive { ast_id, derive_attr_index, derive_index } => {
|
||||||
|
let node = ast_id.to_node(db.upcast());
|
||||||
|
// Compute the precise location of the macro name's token in the derive
|
||||||
|
// list.
|
||||||
|
let token = (|| {
|
||||||
|
let derive_attr = node
|
||||||
|
.doc_comments_and_attrs()
|
||||||
|
.nth(*derive_attr_index as usize)
|
||||||
|
.and_then(Either::left)?;
|
||||||
|
let token_tree = derive_attr.meta()?.token_tree()?;
|
||||||
|
let group_by = token_tree
|
||||||
|
.syntax()
|
||||||
|
.children_with_tokens()
|
||||||
|
.filter_map(|elem| match elem {
|
||||||
|
syntax::NodeOrToken::Token(tok) => Some(tok),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.group_by(|t| t.kind() == T![,]);
|
||||||
|
let (_, mut group) = group_by
|
||||||
|
.into_iter()
|
||||||
|
.filter(|&(comma, _)| !comma)
|
||||||
|
.nth(*derive_index as usize)?;
|
||||||
|
group.find(|t| t.kind() == T![ident])
|
||||||
|
})();
|
||||||
|
(
|
||||||
|
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
|
||||||
|
token.as_ref().map(|tok| tok.text_range()),
|
||||||
|
token.as_ref().map(ToString::to_string),
|
||||||
|
MacroKind::Derive,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
|
||||||
|
let node = ast_id.to_node(db.upcast());
|
||||||
|
let attr = node
|
||||||
|
.doc_comments_and_attrs()
|
||||||
|
.nth((*invoc_attr_index) as usize)
|
||||||
|
.and_then(Either::left)
|
||||||
|
.unwrap_or_else(|| panic!("cannot find attribute #{}", invoc_attr_index));
|
||||||
|
|
||||||
|
(
|
||||||
|
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
|
||||||
|
Some(attr.syntax().text_range()),
|
||||||
|
attr.path()
|
||||||
|
.and_then(|path| path.segment())
|
||||||
|
.and_then(|seg| seg.name_ref())
|
||||||
|
.as_ref()
|
||||||
|
.map(ToString::to_string),
|
||||||
|
MacroKind::Attr,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl HasVisibility for Module {
|
impl HasVisibility for Module {
|
||||||
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
||||||
let def_map = self.id.def_map(db.upcast());
|
let def_map = self.id.def_map(db.upcast());
|
||||||
|
@ -1156,6 +1154,7 @@ impl DefWithBody {
|
||||||
BodyDiagnostic::MacroError { node, message } => acc.push(
|
BodyDiagnostic::MacroError { node, message } => acc.push(
|
||||||
MacroError {
|
MacroError {
|
||||||
node: node.clone().map(|it| it.into()),
|
node: node.clone().map(|it| it.into()),
|
||||||
|
precise_location: None,
|
||||||
message: message.to_string(),
|
message: message.to_string(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
|
@ -1173,6 +1172,7 @@ impl DefWithBody {
|
||||||
BodyDiagnostic::UnresolvedMacroCall { node, path } => acc.push(
|
BodyDiagnostic::UnresolvedMacroCall { node, path } => acc.push(
|
||||||
UnresolvedMacroCall {
|
UnresolvedMacroCall {
|
||||||
macro_call: node.clone().map(|ast_ptr| ast_ptr.into()),
|
macro_call: node.clone().map(|ast_ptr| ast_ptr.into()),
|
||||||
|
precise_location: None,
|
||||||
path: path.clone(),
|
path: path.clone(),
|
||||||
is_bang: true,
|
is_bang: true,
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,12 @@ use crate::{Diagnostic, DiagnosticsContext};
|
||||||
//
|
//
|
||||||
// This diagnostic is shown for macro expansion errors.
|
// This diagnostic is shown for macro expansion errors.
|
||||||
pub(crate) fn macro_error(ctx: &DiagnosticsContext<'_>, d: &hir::MacroError) -> Diagnostic {
|
pub(crate) fn macro_error(ctx: &DiagnosticsContext<'_>, d: &hir::MacroError) -> Diagnostic {
|
||||||
Diagnostic::new(
|
// Use more accurate position if available.
|
||||||
"macro-error",
|
let display_range = d
|
||||||
d.message.clone(),
|
.precise_location
|
||||||
ctx.sema.diagnostics_display_range(d.node.clone()).range,
|
.unwrap_or_else(|| ctx.sema.diagnostics_display_range(d.node.clone()).range);
|
||||||
)
|
|
||||||
.experimental()
|
Diagnostic::new("macro-error", d.message.clone(), display_range).experimental()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -30,10 +30,10 @@ macro_rules! include { () => {} }
|
||||||
macro_rules! compile_error { () => {} }
|
macro_rules! compile_error { () => {} }
|
||||||
|
|
||||||
include!("doesntexist");
|
include!("doesntexist");
|
||||||
//^^^^^^^^^^^^^^^^^^^^^^^^ error: failed to load file `doesntexist`
|
//^^^^^^^ error: failed to load file `doesntexist`
|
||||||
|
|
||||||
compile_error!("compile_error macro works");
|
compile_error!("compile_error macro works");
|
||||||
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: compile_error macro works
|
//^^^^^^^^^^^^^ error: compile_error macro works
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ macro_rules! env { () => {} }
|
||||||
macro_rules! concat { () => {} }
|
macro_rules! concat { () => {} }
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/out.rs"));
|
include!(concat!(env!("OUT_DIR"), "/out.rs"));
|
||||||
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `OUT_DIR` not set, enable "build scripts" to fix
|
//^^^^^^^ error: `OUT_DIR` not set, enable "build scripts" to fix
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -153,23 +153,23 @@ fn main() {
|
||||||
// Test a handful of built-in (eager) macros:
|
// Test a handful of built-in (eager) macros:
|
||||||
|
|
||||||
include!(invalid);
|
include!(invalid);
|
||||||
//^^^^^^^^^^^^^^^^^ error: could not convert tokens
|
//^^^^^^^ error: could not convert tokens
|
||||||
include!("does not exist");
|
include!("does not exist");
|
||||||
//^^^^^^^^^^^^^^^^^^^^^^^^^^ error: failed to load file `does not exist`
|
//^^^^^^^ error: failed to load file `does not exist`
|
||||||
|
|
||||||
env!(invalid);
|
env!(invalid);
|
||||||
//^^^^^^^^^^^^^ error: could not convert tokens
|
//^^^ error: could not convert tokens
|
||||||
|
|
||||||
env!("OUT_DIR");
|
env!("OUT_DIR");
|
||||||
//^^^^^^^^^^^^^^^ error: `OUT_DIR` not set, enable "build scripts" to fix
|
//^^^ error: `OUT_DIR` not set, enable "build scripts" to fix
|
||||||
|
|
||||||
compile_error!("compile_error works");
|
compile_error!("compile_error works");
|
||||||
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: compile_error works
|
//^^^^^^^^^^^^^ error: compile_error works
|
||||||
|
|
||||||
// Lazy:
|
// Lazy:
|
||||||
|
|
||||||
format_args!();
|
format_args!();
|
||||||
//^^^^^^^^^^^^^^ error: no rule matches input tokens
|
//^^^^^^^^^^^ error: no rule matches input tokens
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
@ -186,7 +186,7 @@ fn f() {
|
||||||
m!();
|
m!();
|
||||||
|
|
||||||
m!(hi);
|
m!(hi);
|
||||||
//^^^^^^ error: leftover tokens
|
//^ error: leftover tokens
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
use hir::{db::AstDatabase, InFile};
|
|
||||||
use syntax::{ast, AstNode, SyntaxNodePtr};
|
|
||||||
|
|
||||||
use crate::{Diagnostic, DiagnosticsContext};
|
use crate::{Diagnostic, DiagnosticsContext};
|
||||||
|
|
||||||
// Diagnostic: unresolved-macro-call
|
// Diagnostic: unresolved-macro-call
|
||||||
|
@ -11,25 +8,16 @@ pub(crate) fn unresolved_macro_call(
|
||||||
ctx: &DiagnosticsContext<'_>,
|
ctx: &DiagnosticsContext<'_>,
|
||||||
d: &hir::UnresolvedMacroCall,
|
d: &hir::UnresolvedMacroCall,
|
||||||
) -> Diagnostic {
|
) -> Diagnostic {
|
||||||
let last_path_segment = ctx.sema.db.parse_or_expand(d.macro_call.file_id).and_then(|root| {
|
// Use more accurate position if available.
|
||||||
let node = d.macro_call.value.to_node(&root);
|
let display_range = d
|
||||||
if let Some(macro_call) = ast::MacroCall::cast(node) {
|
.precise_location
|
||||||
macro_call
|
.unwrap_or_else(|| ctx.sema.diagnostics_display_range(d.macro_call.clone()).range);
|
||||||
.path()
|
|
||||||
.and_then(|it| it.segment())
|
|
||||||
.and_then(|it| it.name_ref())
|
|
||||||
.map(|it| InFile::new(d.macro_call.file_id, SyntaxNodePtr::new(it.syntax())))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let diagnostics = last_path_segment.unwrap_or_else(|| d.macro_call.clone().map(|it| it.into()));
|
|
||||||
|
|
||||||
let bang = if d.is_bang { "!" } else { "" };
|
let bang = if d.is_bang { "!" } else { "" };
|
||||||
Diagnostic::new(
|
Diagnostic::new(
|
||||||
"unresolved-macro-call",
|
"unresolved-macro-call",
|
||||||
format!("unresolved macro `{}{}`", d.path, bang),
|
format!("unresolved macro `{}{}`", d.path, bang),
|
||||||
ctx.sema.diagnostics_display_range(diagnostics).range,
|
display_range,
|
||||||
)
|
)
|
||||||
.experimental()
|
.experimental()
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,8 +172,8 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
|
||||||
prelude: true,
|
prelude: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
proc_macro: Ok(
|
proc_macro: Err(
|
||||||
[],
|
"no build data",
|
||||||
),
|
),
|
||||||
origin: CratesIo {
|
origin: CratesIo {
|
||||||
repo: None,
|
repo: None,
|
||||||
|
@ -247,8 +247,8 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
|
||||||
prelude: true,
|
prelude: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
proc_macro: Ok(
|
proc_macro: Err(
|
||||||
[],
|
"no build data",
|
||||||
),
|
),
|
||||||
origin: CratesIo {
|
origin: CratesIo {
|
||||||
repo: None,
|
repo: None,
|
||||||
|
@ -312,8 +312,8 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
dependencies: [],
|
dependencies: [],
|
||||||
proc_macro: Ok(
|
proc_macro: Err(
|
||||||
[],
|
"no build data",
|
||||||
),
|
),
|
||||||
origin: CratesIo {
|
origin: CratesIo {
|
||||||
repo: Some(
|
repo: Some(
|
||||||
|
@ -389,8 +389,8 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
|
||||||
prelude: true,
|
prelude: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
proc_macro: Ok(
|
proc_macro: Err(
|
||||||
[],
|
"no build data",
|
||||||
),
|
),
|
||||||
origin: CratesIo {
|
origin: CratesIo {
|
||||||
repo: None,
|
repo: None,
|
||||||
|
@ -464,8 +464,8 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
|
||||||
prelude: true,
|
prelude: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
proc_macro: Ok(
|
proc_macro: Err(
|
||||||
[],
|
"no build data",
|
||||||
),
|
),
|
||||||
origin: CratesIo {
|
origin: CratesIo {
|
||||||
repo: None,
|
repo: None,
|
||||||
|
@ -554,8 +554,8 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
|
||||||
prelude: true,
|
prelude: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
proc_macro: Ok(
|
proc_macro: Err(
|
||||||
[],
|
"no build data",
|
||||||
),
|
),
|
||||||
origin: CratesIo {
|
origin: CratesIo {
|
||||||
repo: None,
|
repo: None,
|
||||||
|
@ -631,8 +631,8 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
|
||||||
prelude: true,
|
prelude: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
proc_macro: Ok(
|
proc_macro: Err(
|
||||||
[],
|
"no build data",
|
||||||
),
|
),
|
||||||
origin: CratesIo {
|
origin: CratesIo {
|
||||||
repo: None,
|
repo: None,
|
||||||
|
@ -696,8 +696,8 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
dependencies: [],
|
dependencies: [],
|
||||||
proc_macro: Ok(
|
proc_macro: Err(
|
||||||
[],
|
"no build data",
|
||||||
),
|
),
|
||||||
origin: CratesIo {
|
origin: CratesIo {
|
||||||
repo: Some(
|
repo: Some(
|
||||||
|
@ -775,8 +775,8 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
|
||||||
prelude: true,
|
prelude: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
proc_macro: Ok(
|
proc_macro: Err(
|
||||||
[],
|
"no build data",
|
||||||
),
|
),
|
||||||
origin: CratesIo {
|
origin: CratesIo {
|
||||||
repo: None,
|
repo: None,
|
||||||
|
@ -852,8 +852,8 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
|
||||||
prelude: true,
|
prelude: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
proc_macro: Ok(
|
proc_macro: Err(
|
||||||
[],
|
"no build data",
|
||||||
),
|
),
|
||||||
origin: CratesIo {
|
origin: CratesIo {
|
||||||
repo: None,
|
repo: None,
|
||||||
|
@ -933,8 +933,8 @@ fn cargo_hello_world_project_model() {
|
||||||
prelude: true,
|
prelude: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
proc_macro: Ok(
|
proc_macro: Err(
|
||||||
[],
|
"no build data",
|
||||||
),
|
),
|
||||||
origin: CratesIo {
|
origin: CratesIo {
|
||||||
repo: None,
|
repo: None,
|
||||||
|
@ -1010,8 +1010,8 @@ fn cargo_hello_world_project_model() {
|
||||||
prelude: true,
|
prelude: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
proc_macro: Ok(
|
proc_macro: Err(
|
||||||
[],
|
"no build data",
|
||||||
),
|
),
|
||||||
origin: CratesIo {
|
origin: CratesIo {
|
||||||
repo: None,
|
repo: None,
|
||||||
|
@ -1075,8 +1075,8 @@ fn cargo_hello_world_project_model() {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
dependencies: [],
|
dependencies: [],
|
||||||
proc_macro: Ok(
|
proc_macro: Err(
|
||||||
[],
|
"no build data",
|
||||||
),
|
),
|
||||||
origin: CratesIo {
|
origin: CratesIo {
|
||||||
repo: Some(
|
repo: Some(
|
||||||
|
@ -1154,8 +1154,8 @@ fn cargo_hello_world_project_model() {
|
||||||
prelude: true,
|
prelude: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
proc_macro: Ok(
|
proc_macro: Err(
|
||||||
[],
|
"no build data",
|
||||||
),
|
),
|
||||||
origin: CratesIo {
|
origin: CratesIo {
|
||||||
repo: None,
|
repo: None,
|
||||||
|
@ -1231,8 +1231,8 @@ fn cargo_hello_world_project_model() {
|
||||||
prelude: true,
|
prelude: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
proc_macro: Ok(
|
proc_macro: Err(
|
||||||
[],
|
"no build data",
|
||||||
),
|
),
|
||||||
origin: CratesIo {
|
origin: CratesIo {
|
||||||
repo: None,
|
repo: None,
|
||||||
|
@ -1505,8 +1505,8 @@ fn rust_project_hello_world_project_model() {
|
||||||
prelude: false,
|
prelude: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
proc_macro: Ok(
|
proc_macro: Err(
|
||||||
[],
|
"no proc macro dylib present",
|
||||||
),
|
),
|
||||||
origin: CratesIo {
|
origin: CratesIo {
|
||||||
repo: None,
|
repo: None,
|
||||||
|
|
|
@ -459,7 +459,7 @@ fn project_json_to_crate_graph(
|
||||||
krate.display_name.as_ref().map(|it| it.canonical_name()).unwrap_or(""),
|
krate.display_name.as_ref().map(|it| it.canonical_name()).unwrap_or(""),
|
||||||
&it,
|
&it,
|
||||||
),
|
),
|
||||||
None => Ok(Vec::new()),
|
None => Err("no proc macro dylib present".into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let target_cfgs = match krate.target.as_deref() {
|
let target_cfgs = match krate.target.as_deref() {
|
||||||
|
@ -870,9 +870,10 @@ fn add_target_crate_root(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let proc_macro = match build_data.as_ref().and_then(|it| it.proc_macro_dylib_path.as_ref()) {
|
let proc_macro = match build_data.as_ref().map(|it| it.proc_macro_dylib_path.as_ref()) {
|
||||||
Some(it) => load_proc_macro(it),
|
Some(Some(it)) => load_proc_macro(it),
|
||||||
None => Ok(Vec::new()),
|
Some(None) => Err("no proc macro dylib present".into()),
|
||||||
|
None => Err("no build data".into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let display_name = CrateDisplayName::from_canonical_name(cargo_name.to_string());
|
let display_name = CrateDisplayName::from_canonical_name(cargo_name.to_string());
|
||||||
|
|
Loading…
Reference in a new issue