mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-26 20:09:19 +00:00
Make original_range
a method on InFile<&SyntaxNode>
This commit is contained in:
parent
b01981e636
commit
4943ef085d
5 changed files with 88 additions and 89 deletions
|
@ -20,11 +20,11 @@ pub use mbe::{ExpandError, ExpandResult};
|
|||
use std::hash::Hash;
|
||||
use std::sync::Arc;
|
||||
|
||||
use base_db::{impl_intern_key, salsa, CrateId, FileId};
|
||||
use base_db::{impl_intern_key, salsa, CrateId, FileId, FileRange};
|
||||
use syntax::{
|
||||
algo,
|
||||
algo::{self, skip_trivia_token},
|
||||
ast::{self, AstNode},
|
||||
SyntaxNode, SyntaxToken, TextSize,
|
||||
Direction, SyntaxNode, SyntaxToken, TextRange, TextSize,
|
||||
};
|
||||
|
||||
use crate::ast_id_map::FileAstId;
|
||||
|
@ -445,6 +445,72 @@ impl InFile<SyntaxNode> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> InFile<&'a SyntaxNode> {
|
||||
pub fn original_file_range(self, db: &dyn db::AstDatabase) -> FileRange {
|
||||
if let Some(range) = original_range_opt(db, self) {
|
||||
let original_file = range.file_id.original_file(db);
|
||||
if range.file_id == original_file.into() {
|
||||
return FileRange { file_id: original_file, range: range.value };
|
||||
}
|
||||
|
||||
log::error!("Fail to mapping up more for {:?}", range);
|
||||
return FileRange { file_id: range.file_id.original_file(db), range: range.value };
|
||||
}
|
||||
|
||||
// Fall back to whole macro call
|
||||
if let Some(expansion) = self.file_id.expansion_info(db) {
|
||||
if let Some(call_node) = expansion.call_node() {
|
||||
return FileRange {
|
||||
file_id: call_node.file_id.original_file(db),
|
||||
range: call_node.value.text_range(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
FileRange { file_id: self.file_id.original_file(db), range: self.value.text_range() }
|
||||
}
|
||||
}
|
||||
|
||||
fn original_range_opt(
|
||||
db: &dyn db::AstDatabase,
|
||||
node: InFile<&SyntaxNode>,
|
||||
) -> Option<InFile<TextRange>> {
|
||||
let expansion = node.file_id.expansion_info(db)?;
|
||||
|
||||
// the input node has only one token ?
|
||||
let single = skip_trivia_token(node.value.first_token()?, Direction::Next)?
|
||||
== skip_trivia_token(node.value.last_token()?, Direction::Prev)?;
|
||||
|
||||
Some(node.value.descendants().find_map(|it| {
|
||||
let first = skip_trivia_token(it.first_token()?, Direction::Next)?;
|
||||
let first = ascend_call_token(db, &expansion, node.with_value(first))?;
|
||||
|
||||
let last = skip_trivia_token(it.last_token()?, Direction::Prev)?;
|
||||
let last = ascend_call_token(db, &expansion, node.with_value(last))?;
|
||||
|
||||
if (!single && first == last) || (first.file_id != last.file_id) {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(first.with_value(first.value.text_range().cover(last.value.text_range())))
|
||||
})?)
|
||||
}
|
||||
|
||||
fn ascend_call_token(
|
||||
db: &dyn db::AstDatabase,
|
||||
expansion: &ExpansionInfo,
|
||||
token: InFile<SyntaxToken>,
|
||||
) -> Option<InFile<SyntaxToken>> {
|
||||
let (mapped, origin) = expansion.map_token_up(token.as_ref())?;
|
||||
if origin != Origin::Call {
|
||||
return None;
|
||||
}
|
||||
if let Some(info) = mapped.file_id.expansion_info(db) {
|
||||
return ascend_call_token(db, &info, mapped);
|
||||
}
|
||||
Some(mapped)
|
||||
}
|
||||
|
||||
impl InFile<SyntaxToken> {
|
||||
pub fn ancestors_with_macros(
|
||||
self,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue