mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-31 20:09:01 +00:00
Add some more hir_expand::files conversions
This commit is contained in:
parent
e65dddaf59
commit
f0e39c77cc
6 changed files with 137 additions and 64 deletions
|
|
@ -42,6 +42,49 @@ impl FilePosition {
|
|||
FilePositionWrapper { file_id: self.file_id.file_id(db), offset: self.offset }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FileRange> for HirFileRange {
|
||||
fn from(value: FileRange) -> Self {
|
||||
HirFileRange { file_id: value.file_id.into(), range: value.range }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FilePosition> for HirFilePosition {
|
||||
fn from(value: FilePosition) -> Self {
|
||||
HirFilePosition { file_id: value.file_id.into(), offset: value.offset }
|
||||
}
|
||||
}
|
||||
|
||||
impl FilePositionWrapper<span::FileId> {
|
||||
pub fn with_edition(self, db: &dyn ExpandDatabase, edition: span::Edition) -> FilePosition {
|
||||
FilePositionWrapper {
|
||||
file_id: EditionedFileId::new(db, self.file_id, edition),
|
||||
offset: self.offset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FileRangeWrapper<span::FileId> {
|
||||
pub fn with_edition(self, db: &dyn ExpandDatabase, edition: span::Edition) -> FileRange {
|
||||
FileRangeWrapper {
|
||||
file_id: EditionedFileId::new(db, self.file_id, edition),
|
||||
range: self.range,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> InFileWrapper<span::FileId, T> {
|
||||
pub fn with_edition(self, db: &dyn ExpandDatabase, edition: span::Edition) -> InRealFile<T> {
|
||||
InRealFile { file_id: EditionedFileId::new(db, self.file_id, edition), value: self.value }
|
||||
}
|
||||
}
|
||||
|
||||
impl HirFileRange {
|
||||
pub fn file_range(self) -> Option<FileRange> {
|
||||
Some(FileRange { file_id: self.file_id.file_id()?, range: self.range })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||
pub struct FileRangeWrapper<FileKind> {
|
||||
pub file_id: FileKind,
|
||||
|
|
@ -194,6 +237,9 @@ impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, N> {
|
|||
pub fn syntax(&self) -> InFileWrapper<FileId, &SyntaxNode> {
|
||||
self.with_value(self.value.syntax())
|
||||
}
|
||||
pub fn node_file_range(&self) -> FileRangeWrapper<FileId> {
|
||||
FileRangeWrapper { file_id: self.file_id, range: self.value.syntax().text_range() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, &N> {
|
||||
|
|
@ -204,9 +250,9 @@ impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, &N> {
|
|||
}
|
||||
|
||||
// region:specific impls
|
||||
impl<SN: Borrow<SyntaxNode>> InRealFile<SN> {
|
||||
pub fn file_range(&self) -> FileRange {
|
||||
FileRange { file_id: self.file_id, range: self.value.borrow().text_range() }
|
||||
impl<FileId: Copy, SN: Borrow<SyntaxNode>> InFileWrapper<FileId, SN> {
|
||||
pub fn file_range(&self) -> FileRangeWrapper<FileId> {
|
||||
FileRangeWrapper { file_id: self.file_id, range: self.value.borrow().text_range() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -392,6 +392,10 @@ impl HirFileId {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn call_node(self, db: &dyn ExpandDatabase) -> Option<InFile<SyntaxNode>> {
|
||||
Some(db.lookup_intern_macro_call(self.macro_file()?).to_node(db))
|
||||
}
|
||||
|
||||
pub fn as_builtin_derive_attr_node(
|
||||
&self,
|
||||
db: &dyn ExpandDatabase,
|
||||
|
|
@ -848,7 +852,10 @@ impl ExpansionInfo {
|
|||
map_node_range_up(db, &self.exp_map, range)
|
||||
}
|
||||
|
||||
/// Maps up the text range out of the expansion into is macro call.
|
||||
/// Maps up the text range out of the expansion into its macro call.
|
||||
///
|
||||
/// Note that this may return multiple ranges as we lose the precise association between input to output
|
||||
/// and as such we may consider inputs that are unrelated.
|
||||
pub fn map_range_up_once(
|
||||
&self,
|
||||
db: &dyn ExpandDatabase,
|
||||
|
|
@ -864,11 +871,10 @@ impl ExpansionInfo {
|
|||
InFile { file_id, value: smallvec::smallvec![span.range + anchor_offset] }
|
||||
}
|
||||
SpanMap::ExpansionSpanMap(arg_map) => {
|
||||
let arg_range = self
|
||||
.arg
|
||||
.value
|
||||
.as_ref()
|
||||
.map_or_else(|| TextRange::empty(TextSize::from(0)), |it| it.text_range());
|
||||
let Some(arg_node) = &self.arg.value else {
|
||||
return InFile::new(self.arg.file_id, smallvec::smallvec![]);
|
||||
};
|
||||
let arg_range = arg_node.text_range();
|
||||
InFile::new(
|
||||
self.arg.file_id,
|
||||
arg_map
|
||||
|
|
|
|||
|
|
@ -20,12 +20,15 @@ pub fn prettify_macro_expansion(
|
|||
let span_offset = syn.text_range().start();
|
||||
let target_crate = target_crate_id.data(db);
|
||||
let mut syntax_ctx_id_to_dollar_crate_replacement = FxHashMap::default();
|
||||
syntax_bridge::prettify_macro_expansion::prettify_macro_expansion(syn, &mut |dollar_crate| {
|
||||
syntax_bridge::prettify_macro_expansion::prettify_macro_expansion(
|
||||
syn,
|
||||
&mut |dollar_crate| {
|
||||
let ctx = span_map.span_at(dollar_crate.text_range().start() + span_offset).ctx;
|
||||
let replacement =
|
||||
syntax_ctx_id_to_dollar_crate_replacement.entry(ctx).or_insert_with(|| {
|
||||
let macro_call_id =
|
||||
ctx.outer_expn(db).expect("`$crate` cannot come from `SyntaxContextId::ROOT`");
|
||||
let macro_call_id = ctx
|
||||
.outer_expn(db)
|
||||
.expect("`$crate` cannot come from `SyntaxContextId::ROOT`");
|
||||
let macro_call = db.lookup_intern_macro_call(macro_call_id.into());
|
||||
let macro_def_crate = macro_call.def.krate;
|
||||
// First, if this is the same crate as the macro, nothing will work but `crate`.
|
||||
|
|
@ -48,7 +51,7 @@ pub fn prettify_macro_expansion(
|
|||
});
|
||||
if replacement.text() == "$crate" {
|
||||
// The parent may have many children, and looking for the token may yield incorrect results.
|
||||
return dollar_crate.clone();
|
||||
return None;
|
||||
}
|
||||
// We need to `clone_subtree()` but rowan doesn't provide such operation for tokens.
|
||||
let parent = replacement.parent().unwrap().clone_subtree().clone_for_update();
|
||||
|
|
@ -56,6 +59,7 @@ pub fn prettify_macro_expansion(
|
|||
.children_with_tokens()
|
||||
.filter_map(NodeOrToken::into_token)
|
||||
.find(|it| it.kind() == replacement.kind())
|
||||
.unwrap()
|
||||
})
|
||||
},
|
||||
|_| (),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,8 @@ fn check_(
|
|||
"{}",
|
||||
syntax_bridge::prettify_macro_expansion::prettify_macro_expansion(
|
||||
node.syntax_node(),
|
||||
&mut |it| it.clone()
|
||||
&mut |_| None,
|
||||
|_| ()
|
||||
)
|
||||
);
|
||||
expect.assert_eq(&expect_res);
|
||||
|
|
|
|||
|
|
@ -112,7 +112,10 @@ pub struct EditionedFileId(u32);
|
|||
|
||||
impl fmt::Debug for EditionedFileId {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("EditionedFileId").field(&self.file_id()).field(&self.edition()).finish()
|
||||
f.debug_tuple("EditionedFileId")
|
||||
.field(&self.file_id().index())
|
||||
.field(&self.edition())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,13 @@ use syntax::{
|
|||
ted::{self, Position},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum PrettifyWsKind {
|
||||
Space,
|
||||
Indent(usize),
|
||||
Newline,
|
||||
}
|
||||
|
||||
/// Renders a [`SyntaxNode`] with whitespace inserted between tokens that require them.
|
||||
///
|
||||
/// This is an internal API that is only exported because `mbe` needs it for tests and cannot depend
|
||||
|
|
@ -15,7 +22,8 @@ use syntax::{
|
|||
#[deprecated = "use `hir_expand::prettify_macro_expansion()` instead"]
|
||||
pub fn prettify_macro_expansion(
|
||||
syn: SyntaxNode,
|
||||
dollar_crate_replacement: &mut dyn FnMut(&SyntaxToken) -> SyntaxToken,
|
||||
dollar_crate_replacement: &mut dyn FnMut(&SyntaxToken) -> Option<SyntaxToken>,
|
||||
inspect_mods: impl FnOnce(&[(Position, PrettifyWsKind)]),
|
||||
) -> SyntaxNode {
|
||||
let mut indent = 0;
|
||||
let mut last: Option<SyntaxKind> = None;
|
||||
|
|
@ -27,14 +35,12 @@ pub fn prettify_macro_expansion(
|
|||
let after = Position::after;
|
||||
|
||||
let do_indent = |pos: fn(_) -> Position, token: &SyntaxToken, indent| {
|
||||
(pos(token.clone()), make::tokens::whitespace(&" ".repeat(4 * indent)))
|
||||
};
|
||||
let do_ws = |pos: fn(_) -> Position, token: &SyntaxToken| {
|
||||
(pos(token.clone()), make::tokens::single_space())
|
||||
};
|
||||
let do_nl = |pos: fn(_) -> Position, token: &SyntaxToken| {
|
||||
(pos(token.clone()), make::tokens::single_newline())
|
||||
(pos(token.clone()), PrettifyWsKind::Indent(indent))
|
||||
};
|
||||
let do_ws =
|
||||
|pos: fn(_) -> Position, token: &SyntaxToken| (pos(token.clone()), PrettifyWsKind::Space);
|
||||
let do_nl =
|
||||
|pos: fn(_) -> Position, token: &SyntaxToken| (pos(token.clone()), PrettifyWsKind::Newline);
|
||||
|
||||
for event in syn.preorder_with_tokens() {
|
||||
let token = match event {
|
||||
|
|
@ -46,20 +52,19 @@ pub fn prettify_macro_expansion(
|
|||
) =>
|
||||
{
|
||||
if indent > 0 {
|
||||
mods.push((
|
||||
Position::after(node.clone()),
|
||||
make::tokens::whitespace(&" ".repeat(4 * indent)),
|
||||
));
|
||||
mods.push((Position::after(node.clone()), PrettifyWsKind::Indent(indent)));
|
||||
}
|
||||
if node.parent().is_some() {
|
||||
mods.push((Position::after(node), make::tokens::single_newline()));
|
||||
mods.push((Position::after(node), PrettifyWsKind::Newline));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
if token.kind() == SyntaxKind::IDENT && token.text() == "$crate" {
|
||||
dollar_crate_replacements.push((token.clone(), dollar_crate_replacement(&token)));
|
||||
if let Some(replacement) = dollar_crate_replacement(&token) {
|
||||
dollar_crate_replacements.push((token.clone(), replacement));
|
||||
}
|
||||
}
|
||||
let tok = &token;
|
||||
|
||||
|
|
@ -129,8 +134,16 @@ pub fn prettify_macro_expansion(
|
|||
last = Some(tok.kind());
|
||||
}
|
||||
|
||||
inspect_mods(&mods);
|
||||
for (pos, insert) in mods {
|
||||
ted::insert(pos, insert);
|
||||
ted::insert_raw(
|
||||
pos,
|
||||
match insert {
|
||||
PrettifyWsKind::Space => make::tokens::single_space(),
|
||||
PrettifyWsKind::Indent(indent) => make::tokens::whitespace(&" ".repeat(4 * indent)),
|
||||
PrettifyWsKind::Newline => make::tokens::single_newline(),
|
||||
},
|
||||
);
|
||||
}
|
||||
for (old, new) in dollar_crate_replacements {
|
||||
ted::replace(old, new);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue