spans always come from real file

This commit is contained in:
Lukas Wirth 2023-11-24 16:38:48 +01:00
parent 394d11b0fa
commit 30093a6d81
57 changed files with 1369 additions and 1224 deletions

View file

@ -1,5 +1,6 @@
//! Attributes & documentation for hir types.
use base_db::FileId;
use hir_def::{
attr::AttrsWithOwner,
item_scope::ItemInNs,
@ -8,7 +9,10 @@ use hir_def::{
resolver::{HasResolver, Resolver, TypeNs},
AssocItemId, AttrDefId, ModuleDefId,
};
use hir_expand::name::Name;
use hir_expand::{
name::Name,
span::{RealSpanMap, SpanMapRef},
};
use hir_ty::db::HirDatabase;
use syntax::{ast, AstNode};
@ -234,7 +238,11 @@ fn modpath_from_str(db: &dyn HirDatabase, link: &str) -> Option<ModPath> {
if ast_path.syntax().text() != link {
return None;
}
ModPath::from_src(db.upcast(), ast_path, &Default::default())
ModPath::from_src(
db.upcast(),
ast_path,
SpanMapRef::RealSpanMap(&RealSpanMap::empty(FileId(0))),
)
};
let full = try_get_modpath(link);

View file

@ -59,7 +59,7 @@ use hir_def::{
Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId,
TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
};
use hir_expand::{name::name, MacroCallKind};
use hir_expand::{name::name, InMacroFile, MacroCallKind};
use hir_ty::{
all_super_traits, autoderef, check_orphan_rules,
consteval::{try_const_usize, unknown_const_as_generic, ConstEvalError, ConstExt},
@ -3483,11 +3483,41 @@ impl Impl {
self.id.lookup(db.upcast()).container.into()
}
pub fn as_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> {
pub fn as_builtin_derive_attr(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> {
let src = self.source(db)?;
src.file_id.as_builtin_derive_attr_node(db.upcast())
}
pub fn as_builtin_derive_path(self, db: &dyn HirDatabase) -> Option<InMacroFile<ast::Path>> {
let src = self.source(db)?;
let macro_file = src.file_id.macro_file()?;
let loc = db.lookup_intern_macro_call(macro_file.macro_call_id);
let (derive_attr, derive_index) = match loc.kind {
MacroCallKind::Derive { ast_id, derive_attr_index, derive_index } => {
let module_id = self.id.lookup(db.upcast()).container;
(
db.crate_def_map(module_id.krate())[module_id.local_id]
.scope
.derive_macro_invoc(ast_id, derive_attr_index)?,
derive_index,
)
}
_ => return None,
};
let file_id = MacroFile { macro_call_id: derive_attr };
let path = db
.parse_macro_expansion(file_id)
.value
.0
.syntax_node()
.children()
.nth(derive_index as usize)
.and_then(<ast::Attr as AstNode>::cast)
.and_then(|it| it.path())?;
Some(InMacroFile { file_id, value: path })
}
pub fn check_orphan_rules(self, db: &dyn HirDatabase) -> bool {
check_orphan_rules(db, self.id)
}

View file

@ -19,6 +19,7 @@ use hir_expand::{db::ExpandDatabase, name::AsName, ExpansionInfo, HirFileIdExt,
use itertools::Itertools;
use rustc_hash::{FxHashMap, FxHashSet};
use smallvec::{smallvec, SmallVec};
use stdx::TupleExt;
use syntax::{
algo::skip_trivia_token,
ast::{self, HasAttrs as _, HasGenericParams, HasLoopBody},
@ -529,11 +530,11 @@ impl<'db> SemanticsImpl<'db> {
token: SyntaxToken,
// FIXME: We might want this to be Option<TextSize> to be able to opt out of subrange
// mapping, specifically for node downmapping
offset: TextSize,
_offset: TextSize,
f: &mut dyn FnMut(InFile<SyntaxToken>) -> bool,
) {
// FIXME: Clean this up
let _p = profile::span("descend_into_macros");
let relative_token_offset = token.text_range().start().checked_sub(offset);
let parent = match token.parent() {
Some(it) => it,
None => return,
@ -543,13 +544,35 @@ impl<'db> SemanticsImpl<'db> {
None => return,
};
let def_map = sa.resolver.def_map();
let absolute_range = match sa.file_id.repr() {
base_db::span::HirFileIdRepr::FileId(file_id) => {
FileRange { file_id, range: token.text_range() }
}
base_db::span::HirFileIdRepr::MacroFile(m) => {
let span =
self.db.parse_macro_expansion(m).value.1.span_for_range(token.text_range());
let range = span.range
+ self
.db
.ast_id_map(span.anchor.file_id.into())
.get_erased(span.anchor.ast_id)
.text_range()
.start();
FileRange { file_id: span.anchor.file_id, range }
}
};
// fetch span information of token in real file, then use that look through expansions of
// calls the token is in and afterwards recursively with the same span.
// what about things where spans change? Due to being joined etc, that is we don't find the
// exact span anymore?
let mut stack: SmallVec<[_; 4]> = smallvec![InFile::new(sa.file_id, token)];
let mut cache = self.expansion_info_cache.borrow_mut();
let mut mcache = self.macro_call_cache.borrow_mut();
let mut process_expansion_for_token =
|stack: &mut SmallVec<_>, macro_file, token: InFile<&_>| {
|stack: &mut SmallVec<_>, macro_file, _token: InFile<&_>| {
let expansion_info = cache
.entry(macro_file)
.or_insert_with(|| macro_file.expansion_info(self.db.upcast()))
@ -560,11 +583,8 @@ impl<'db> SemanticsImpl<'db> {
self.cache(value, file_id);
}
let mapped_tokens = expansion_info.map_token_down(
self.db.upcast(),
token,
relative_token_offset,
)?;
let mapped_tokens =
expansion_info.map_range_down(self.db.upcast(), absolute_range, None)?;
let len = stack.len();
// requeue the tokens we got from mapping our current token down
@ -728,6 +748,8 @@ impl<'db> SemanticsImpl<'db> {
pub fn original_range_opt(&self, node: &SyntaxNode) -> Option<FileRange> {
let node = self.find_file(node);
node.original_file_range_opt(self.db.upcast())
.filter(|(_, ctx)| ctx.is_root())
.map(TupleExt::head)
}
/// Attempts to map the node out of macro expanded files.

View file

@ -7,7 +7,7 @@ use hir_def::{
AdtId, AssocItemId, DefWithBodyId, HasModule, ImplId, Lookup, MacroId, ModuleDefId, ModuleId,
TraitId,
};
use hir_expand::{HirFileId, InFile};
use hir_expand::{files::ascend_range_up_macros, HirFileId, InFile};
use hir_ty::db::HirDatabase;
use syntax::{ast::HasName, AstNode, SmolStr, SyntaxNode, SyntaxNodePtr};
@ -50,13 +50,9 @@ impl DeclarationLocation {
node.as_ref().original_file_range(db.upcast())
}
pub fn original_name_range(&self, db: &dyn HirDatabase) -> Option<FileRange> {
if let Some(file_id) = self.hir_file_id.file_id() {
// fast path to prevent parsing
return Some(FileRange { file_id, range: self.name_ptr.text_range() });
}
let node = resolve_node(db, self.hir_file_id, &self.name_ptr);
node.as_ref().original_file_range_opt(db.upcast())
pub fn original_name_range(&self, db: &dyn HirDatabase) -> FileRange {
let mapping = InFile::new(self.hir_file_id, self.name_ptr.text_range());
ascend_range_up_macros(db.upcast(), mapping).0
}
}