Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/semantics/source_to_def.rs')
-rw-r--r--crates/hir/src/semantics/source_to_def.rs45
1 files changed, 41 insertions, 4 deletions
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index 09df639d4a..c1e4e1d1e2 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -99,7 +99,8 @@ use hir_def::{
VariantId,
};
use hir_expand::{
- attrs::AttrId, name::AsName, ExpansionInfo, HirFileId, HirFileIdExt, MacroCallId,
+ attrs::AttrId, name::AsName, ExpansionInfo, HirFileId, HirFileIdExt, InMacroFile, MacroCallId,
+ MacroFileIdExt,
};
use rustc_hash::FxHashMap;
use smallvec::SmallVec;
@@ -110,15 +111,32 @@ use syntax::{
AstNode, AstPtr, SyntaxNode,
};
-use crate::{db::HirDatabase, InFile};
+use crate::{db::HirDatabase, InFile, InlineAsmOperand, SemanticsImpl};
#[derive(Default)]
pub(super) struct SourceToDefCache {
pub(super) dynmap_cache: FxHashMap<(ChildContainer, HirFileId), DynMap>,
- pub(super) expansion_info_cache: FxHashMap<MacroFileId, ExpansionInfo>,
+ expansion_info_cache: FxHashMap<MacroFileId, ExpansionInfo>,
pub(super) file_to_def_cache: FxHashMap<FileId, SmallVec<[ModuleId; 1]>>,
}
+impl SourceToDefCache {
+ pub(super) fn get_or_insert_expansion(
+ &mut self,
+ sema: &SemanticsImpl<'_>,
+ macro_file: MacroFileId,
+ ) -> &ExpansionInfo {
+ self.expansion_info_cache.entry(macro_file).or_insert_with(|| {
+ let exp_info = macro_file.expansion_info(sema.db.upcast());
+
+ let InMacroFile { file_id, value } = exp_info.expanded();
+ sema.cache(value, file_id.into());
+
+ exp_info
+ })
+ }
+}
+
pub(super) struct SourceToDefCtx<'db, 'cache> {
pub(super) db: &'db dyn HirDatabase,
pub(super) cache: &'cache mut SourceToDefCache,
@@ -273,6 +291,25 @@ impl SourceToDefCtx<'_, '_> {
ast::Adt::Union(it) => self.union_to_def(InFile::new(file_id, it)).map(AdtId::UnionId),
}
}
+
+ pub(super) fn asm_operand_to_def(
+ &mut self,
+ src: InFile<&ast::AsmOperandNamed>,
+ ) -> Option<InlineAsmOperand> {
+ let asm = src.value.syntax().parent().and_then(ast::AsmExpr::cast)?;
+ let index = asm
+ .asm_pieces()
+ .filter_map(|it| match it {
+ ast::AsmPiece::AsmOperandNamed(it) => Some(it),
+ _ => None,
+ })
+ .position(|it| it == *src.value)?;
+ let container = self.find_pat_or_label_container(src.syntax_ref())?;
+ let (_, source_map) = self.db.body_with_source_map(container);
+ let expr = source_map.node_expr(src.with_value(&ast::Expr::AsmExpr(asm)))?;
+ Some(InlineAsmOperand { owner: container, expr, index })
+ }
+
pub(super) fn bind_pat_to_def(
&mut self,
src: InFile<&ast::IdentPat>,
@@ -281,7 +318,7 @@ impl SourceToDefCtx<'_, '_> {
let (body, source_map) = self.db.body_with_source_map(container);
let src = src.cloned().map(ast::Pat::from);
let pat_id = source_map.node_pat(src.as_ref())?;
- // the pattern could resolve to a constant, verify that that is not the case
+ // the pattern could resolve to a constant, verify that this is not the case
if let crate::Pat::Bind { id, .. } = body[pat_id] {
Some((container, id))
} else {