mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 21:43:37 +00:00
Add hygiene information to SourceAnalyzer
This commit is contained in:
parent
58a3b3b502
commit
245a9b165a
5 changed files with 36 additions and 13 deletions
|
@ -14,7 +14,8 @@ use hir_def::{
|
||||||
DefWithBodyId,
|
DefWithBodyId,
|
||||||
};
|
};
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
name::AsName, AstId, HirFileId, MacroCallId, MacroCallLoc, MacroFileKind, Source,
|
hygiene::Hygiene, name::AsName, AstId, HirFileId, MacroCallId, MacroCallLoc, MacroFileKind,
|
||||||
|
Source,
|
||||||
};
|
};
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, AstNode},
|
ast::{self, AstNode},
|
||||||
|
@ -236,10 +237,10 @@ impl SourceAnalyzer {
|
||||||
pub fn resolve_macro_call(
|
pub fn resolve_macro_call(
|
||||||
&self,
|
&self,
|
||||||
db: &impl HirDatabase,
|
db: &impl HirDatabase,
|
||||||
macro_call: &ast::MacroCall,
|
macro_call: Source<&ast::MacroCall>,
|
||||||
) -> Option<MacroDef> {
|
) -> Option<MacroDef> {
|
||||||
// This must be a normal source file rather than macro file.
|
let hygiene = Hygiene::new(db, macro_call.file_id);
|
||||||
let path = macro_call.path().and_then(Path::from_ast)?;
|
let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &hygiene))?;
|
||||||
self.resolver.resolve_path_as_macro(db, &path).map(|it| it.into())
|
self.resolver.resolve_path_as_macro(db, &path).map(|it| it.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,12 +442,14 @@ impl SourceAnalyzer {
|
||||||
db: &impl HirDatabase,
|
db: &impl HirDatabase,
|
||||||
macro_call: Source<&ast::MacroCall>,
|
macro_call: Source<&ast::MacroCall>,
|
||||||
) -> Option<Expansion> {
|
) -> Option<Expansion> {
|
||||||
let def = self.resolve_macro_call(db, macro_call.value)?.id;
|
let def = self.resolve_macro_call(db, macro_call)?.id;
|
||||||
let ast_id = AstId::new(
|
let ast_id = AstId::new(
|
||||||
macro_call.file_id,
|
macro_call.file_id,
|
||||||
db.ast_id_map(macro_call.file_id).ast_id(macro_call.value),
|
db.ast_id_map(macro_call.file_id).ast_id(macro_call.value),
|
||||||
);
|
);
|
||||||
let macro_call_loc = MacroCallLoc { def, ast_id };
|
let macro_call_loc = MacroCallLoc { def, ast_id };
|
||||||
|
let kind = to_macro_file_kind(macro_call.value);
|
||||||
|
dbg!(kind);
|
||||||
Some(Expansion {
|
Some(Expansion {
|
||||||
macro_call_id: db.intern_macro(macro_call_loc),
|
macro_call_id: db.intern_macro(macro_call_loc),
|
||||||
macro_file_kind: to_macro_file_kind(macro_call.value),
|
macro_file_kind: to_macro_file_kind(macro_call.value),
|
||||||
|
|
|
@ -97,7 +97,7 @@ impl Path {
|
||||||
|
|
||||||
/// Converts an `ast::Path` to `Path`. Works with use trees.
|
/// Converts an `ast::Path` to `Path`. Works with use trees.
|
||||||
/// It correctly handles `$crate` based path from macro call.
|
/// It correctly handles `$crate` based path from macro call.
|
||||||
pub(crate) fn from_src(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
|
pub fn from_src(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
|
||||||
let mut kind = PathKind::Plain;
|
let mut kind = PathKind::Plain;
|
||||||
let mut segments = Vec::new();
|
let mut segments = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -18,12 +18,9 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
|
||||||
// Find the calling expression and it's NameRef
|
// Find the calling expression and it's NameRef
|
||||||
let calling_node = FnCallNode::with_node(&syntax, position.offset)?;
|
let calling_node = FnCallNode::with_node(&syntax, position.offset)?;
|
||||||
let name_ref = calling_node.name_ref()?;
|
let name_ref = calling_node.name_ref()?;
|
||||||
|
let name_ref = hir::Source::new(position.file_id.into(), name_ref.syntax());
|
||||||
|
|
||||||
let analyzer = hir::SourceAnalyzer::new(
|
let analyzer = hir::SourceAnalyzer::new(db, name_ref, None);
|
||||||
db,
|
|
||||||
hir::Source::new(position.file_id.into(), name_ref.syntax()),
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
let (mut call_info, has_self) = match &calling_node {
|
let (mut call_info, has_self) = match &calling_node {
|
||||||
FnCallNode::CallExpr(expr) => {
|
FnCallNode::CallExpr(expr) => {
|
||||||
//FIXME: don't poke into Ty
|
//FIXME: don't poke into Ty
|
||||||
|
@ -44,7 +41,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
|
||||||
(CallInfo::with_fn(db, function), function.has_self_param(db))
|
(CallInfo::with_fn(db, function), function.has_self_param(db))
|
||||||
}
|
}
|
||||||
FnCallNode::MacroCallExpr(expr) => {
|
FnCallNode::MacroCallExpr(expr) => {
|
||||||
let macro_def = analyzer.resolve_macro_call(db, &expr)?;
|
let macro_def = analyzer.resolve_macro_call(db, name_ref.with_value(&expr))?;
|
||||||
(CallInfo::with_macro(db, macro_def)?, false)
|
(CallInfo::with_macro(db, macro_def)?, false)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -269,4 +269,27 @@ fn some_thing() -> u32 {
|
||||||
assert_eq!(res.name, "foo");
|
assert_eq!(res.name, "foo");
|
||||||
assert_snapshot!(res.expansion, @r###"bar!()"###);
|
assert_snapshot!(res.expansion, @r###"bar!()"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn macro_expand_with_dollar_crate() {
|
||||||
|
let res = check_expand_macro(
|
||||||
|
r#"
|
||||||
|
//- /lib.rs
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! bar {
|
||||||
|
() => {0};
|
||||||
|
}
|
||||||
|
macro_rules! foo {
|
||||||
|
() => {$crate::bar!()};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let res = fo<|>o!();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(res.name, "foo");
|
||||||
|
assert_snapshot!(res.expansion, @r###"0"###);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,7 +152,7 @@ pub(crate) fn classify_name_ref(
|
||||||
|
|
||||||
if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
|
if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
|
||||||
tested_by!(goto_definition_works_for_macros);
|
tested_by!(goto_definition_works_for_macros);
|
||||||
if let Some(macro_def) = analyzer.resolve_macro_call(db, ¯o_call) {
|
if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(¯o_call)) {
|
||||||
let kind = NameKind::Macro(macro_def);
|
let kind = NameKind::Macro(macro_def);
|
||||||
return Some(NameDefinition { kind, container, visibility });
|
return Some(NameDefinition { kind, container, visibility });
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue