mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +00:00
Always expand macros during analysis
This commit is contained in:
parent
e2dd17f75b
commit
2ccfb49bab
3 changed files with 51 additions and 23 deletions
|
@ -173,11 +173,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
|||
}
|
||||
|
||||
pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
|
||||
self.analyze(call.syntax()).resolve_method_call(call)
|
||||
self.analyze(call.syntax()).resolve_method_call(self.db, call)
|
||||
}
|
||||
|
||||
pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<StructField> {
|
||||
self.analyze(field.syntax()).resolve_field(field)
|
||||
self.analyze(field.syntax()).resolve_field(self.db, field)
|
||||
}
|
||||
|
||||
pub fn resolve_record_field(
|
||||
|
@ -188,7 +188,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
|||
}
|
||||
|
||||
pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<VariantDef> {
|
||||
self.analyze(record_lit.syntax()).resolve_record_literal(record_lit)
|
||||
self.analyze(record_lit.syntax()).resolve_record_literal(self.db, record_lit)
|
||||
}
|
||||
|
||||
pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<VariantDef> {
|
||||
|
|
|
@ -78,9 +78,15 @@ impl SourceAnalyzer {
|
|||
}
|
||||
}
|
||||
|
||||
fn expr_id(&self, expr: &ast::Expr) -> Option<ExprId> {
|
||||
let src = InFile { file_id: self.file_id, value: expr };
|
||||
self.body_source_map.as_ref()?.node_expr(src)
|
||||
fn expr_id(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<ExprId> {
|
||||
let src = match expr {
|
||||
ast::Expr::MacroCall(call) => {
|
||||
self.expand_expr(db, InFile::new(self.file_id, call.clone()))?
|
||||
}
|
||||
_ => InFile::new(self.file_id, expr.clone()),
|
||||
};
|
||||
let sm = self.body_source_map.as_ref()?;
|
||||
sm.node_expr(src.as_ref())
|
||||
}
|
||||
|
||||
fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> {
|
||||
|
@ -104,14 +110,7 @@ impl SourceAnalyzer {
|
|||
}
|
||||
|
||||
pub(crate) fn type_of(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<Type> {
|
||||
let expr_id = match expr {
|
||||
ast::Expr::MacroCall(call) => {
|
||||
let expr = self.expand_expr(db, InFile::new(self.file_id, call.clone()))?;
|
||||
self.body_source_map.as_ref()?.node_expr(expr.as_ref())
|
||||
}
|
||||
_ => self.expr_id(expr),
|
||||
}?;
|
||||
|
||||
let expr_id = self.expr_id(db, expr)?;
|
||||
let ty = self.infer.as_ref()?[expr_id].clone();
|
||||
Type::new_with_resolver(db, &self.resolver, ty)
|
||||
}
|
||||
|
@ -122,13 +121,21 @@ impl SourceAnalyzer {
|
|||
Type::new_with_resolver(db, &self.resolver, ty)
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
|
||||
let expr_id = self.expr_id(&call.clone().into())?;
|
||||
pub(crate) fn resolve_method_call(
|
||||
&self,
|
||||
db: &dyn HirDatabase,
|
||||
call: &ast::MethodCallExpr,
|
||||
) -> Option<Function> {
|
||||
let expr_id = self.expr_id(db, &call.clone().into())?;
|
||||
self.infer.as_ref()?.method_resolution(expr_id).map(Function::from)
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_field(&self, field: &ast::FieldExpr) -> Option<crate::StructField> {
|
||||
let expr_id = self.expr_id(&field.clone().into())?;
|
||||
pub(crate) fn resolve_field(
|
||||
&self,
|
||||
db: &dyn HirDatabase,
|
||||
field: &ast::FieldExpr,
|
||||
) -> Option<crate::StructField> {
|
||||
let expr_id = self.expr_id(db, &field.clone().into())?;
|
||||
self.infer.as_ref()?.field_resolution(expr_id).map(|it| it.into())
|
||||
}
|
||||
|
||||
|
@ -138,7 +145,7 @@ impl SourceAnalyzer {
|
|||
field: &ast::RecordField,
|
||||
) -> Option<(crate::StructField, Option<Local>)> {
|
||||
let (expr_id, local) = match field.expr() {
|
||||
Some(it) => (self.expr_id(&it)?, None),
|
||||
Some(it) => (self.expr_id(db, &it)?, None),
|
||||
None => {
|
||||
let src = InFile { file_id: self.file_id, value: field };
|
||||
let expr_id = self.body_source_map.as_ref()?.field_init_shorthand_expr(src)?;
|
||||
|
@ -159,9 +166,10 @@ impl SourceAnalyzer {
|
|||
|
||||
pub(crate) fn resolve_record_literal(
|
||||
&self,
|
||||
db: &dyn HirDatabase,
|
||||
record_lit: &ast::RecordLit,
|
||||
) -> Option<crate::VariantDef> {
|
||||
let expr_id = self.expr_id(&record_lit.clone().into())?;
|
||||
let expr_id = self.expr_id(db, &record_lit.clone().into())?;
|
||||
self.infer.as_ref()?.variant_resolution_for_expr(expr_id).map(|it| it.into())
|
||||
}
|
||||
|
||||
|
@ -207,7 +215,7 @@ impl SourceAnalyzer {
|
|||
path: &ast::Path,
|
||||
) -> Option<PathResolution> {
|
||||
if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) {
|
||||
let expr_id = self.expr_id(&path_expr.into())?;
|
||||
let expr_id = self.expr_id(db, &path_expr.into())?;
|
||||
if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) {
|
||||
return Some(PathResolution::AssocItem(assoc.into()));
|
||||
}
|
||||
|
|
|
@ -104,6 +104,9 @@ mod tests {
|
|||
let (analysis, pos) = analysis_and_position(ra_fixture);
|
||||
|
||||
let mut navs = analysis.goto_definition(pos).unwrap().unwrap().info;
|
||||
if navs.len() == 0 {
|
||||
panic!("unresolved reference")
|
||||
}
|
||||
assert_eq!(navs.len(), 1);
|
||||
|
||||
let nav = navs.pop().unwrap();
|
||||
|
@ -359,7 +362,7 @@ mod tests {
|
|||
fn goto_def_for_fields() {
|
||||
covers!(ra_ide_db::goto_def_for_fields);
|
||||
check_goto(
|
||||
"
|
||||
r"
|
||||
//- /lib.rs
|
||||
struct Foo {
|
||||
spam: u32,
|
||||
|
@ -378,7 +381,7 @@ mod tests {
|
|||
fn goto_def_for_record_fields() {
|
||||
covers!(ra_ide_db::goto_def_for_record_fields);
|
||||
check_goto(
|
||||
"
|
||||
r"
|
||||
//- /lib.rs
|
||||
struct Foo {
|
||||
spam: u32,
|
||||
|
@ -395,6 +398,23 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_def_for_record_fields_macros() {
|
||||
check_goto(
|
||||
r"
|
||||
//- /lib.rs
|
||||
macro_rules! m { () => { 92 };}
|
||||
struct Foo { spam: u32 }
|
||||
|
||||
fn bar() -> Foo {
|
||||
Foo { spam<|>: m!() }
|
||||
}
|
||||
",
|
||||
"spam RECORD_FIELD_DEF FileId(1) [45; 54) [45; 49)",
|
||||
"spam: u32|spam",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_for_tuple_fields() {
|
||||
check_goto(
|
||||
|
|
Loading…
Reference in a new issue