Skip to content

Commit 067a08b

Browse files
committed
Insert ws out of node for prettify_macro_expansion
**Before** ```text VISIBILITY@0..4 PUB_KW@0..3 "pub" WHITESPACE@3..4 " " FN_KW@4..6 "fn" WHITESPACE@6..7 " " ... ``` **After** ```rust VISIBILITY@0..3 PUB_KW@0..3 "pub" WHITESPACE@3..4 " " FN_KW@4..6 "fn" ... ```
1 parent 7e4c4d8 commit 067a08b

1 file changed

Lines changed: 77 additions & 12 deletions

File tree

crates/syntax-bridge/src/prettify_macro_expansion.rs

Lines changed: 77 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use syntax::{
44
SyntaxKind::{self, *},
55
SyntaxNode, SyntaxToken, T, WalkEvent,
66
ast::syntax_factory::SyntaxFactory,
7-
syntax_editor::{Position, SyntaxEditor},
7+
syntax_editor::{Element, Position, SyntaxEditor},
88
};
99

1010
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -31,8 +31,8 @@ pub fn prettify_macro_expansion(
3131
let mut dollar_crate_replacements = Vec::new();
3232
let (editor, syn) = SyntaxEditor::new(syn);
3333

34-
let before = Position::before;
35-
let after = Position::after;
34+
let before = before_non_wrap;
35+
let after = after_non_wrap;
3636

3737
let do_indent = |pos: fn(_) -> Position, token: &SyntaxToken, indent| {
3838
(pos(token.clone()), PrettifyWsKind::Indent(indent))
@@ -56,9 +56,9 @@ pub fn prettify_macro_expansion(
5656
_ => false,
5757
};
5858
if (!is_last_child && is_non_last_newline) || is_always_newline {
59-
mods.push((Position::after(node.clone()), PrettifyWsKind::Indent(indent)));
59+
mods.push((after_non_wrap(node.clone()), PrettifyWsKind::Indent(indent)));
6060
if node.parent().is_some() {
61-
mods.push((Position::after(node), PrettifyWsKind::Newline));
61+
mods.push((after_non_wrap(node), PrettifyWsKind::Newline));
6262
}
6363
}
6464
continue;
@@ -176,6 +176,25 @@ pub fn prettify_macro_expansion(
176176
editor.finish().new_root().clone()
177177
}
178178

179+
fn before_non_wrap(elem: impl Element) -> Position {
180+
let mut elem = elem.syntax_element();
181+
while elem.prev_sibling_or_token().is_none()
182+
&& let Some(parent) = elem.parent()
183+
{
184+
elem = parent.into();
185+
}
186+
Position::before(elem)
187+
}
188+
fn after_non_wrap(elem: impl Element) -> Position {
189+
let mut elem = elem.syntax_element();
190+
while elem.next_sibling_or_token().is_none()
191+
&& let Some(parent) = elem.parent()
192+
{
193+
elem = parent.into();
194+
}
195+
Position::after(elem)
196+
}
197+
179198
fn is_text(k: SyntaxKind) -> bool {
180199
// Consider all keywords in all editions.
181200
k.is_any_identifier() || k.is_literal() || k == UNDERSCORE
@@ -187,17 +206,12 @@ mod tests {
187206
use expect_test::{Expect, expect};
188207

189208
#[expect(deprecated)]
190-
fn check_pretty(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
209+
fn pretty_input(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> SyntaxNode {
191210
let ra_fixture = stdx::trim_indent(ra_fixture);
192211
let source_file = syntax::ast::SourceFile::parse(&ra_fixture, span::Edition::CURRENT);
193212
let syn = remove_whitespaces(&source_file.syntax_node());
194213

195-
let pretty = prettify_macro_expansion(syn, &mut |_, _| None, |_| ());
196-
let mut pretty = pretty.to_string();
197-
if pretty.contains('\n') {
198-
pretty.push('\n');
199-
}
200-
expect.assert_eq(&pretty);
214+
return prettify_macro_expansion(syn, &mut |_, _| None, |_| ());
201215

202216
fn remove_whitespaces(node: &SyntaxNode) -> SyntaxNode {
203217
let (editor, node) = SyntaxEditor::new(node.clone());
@@ -211,6 +225,20 @@ mod tests {
211225
}
212226
}
213227

228+
fn check_pretty(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
229+
let pretty = pretty_input(ra_fixture);
230+
let mut pretty = pretty.to_string();
231+
if pretty.contains('\n') {
232+
pretty.push('\n');
233+
}
234+
expect.assert_eq(&pretty);
235+
}
236+
237+
fn check_pretty_ast(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
238+
let pretty = pretty_input(ra_fixture);
239+
expect.assert_eq(&format!("{pretty:#?}"));
240+
}
241+
214242
#[test]
215243
fn test_in_macro() {
216244
check_pretty(
@@ -470,4 +498,41 @@ mod tests {
470498
"#]],
471499
);
472500
}
501+
502+
#[test]
503+
fn test_insert_outside_node() {
504+
check_pretty_ast(
505+
r#"
506+
pub fn foo() -> i32 {}
507+
"#,
508+
expect![[r#"
509+
SOURCE_FILE@0..22
510+
FN@0..22
511+
VISIBILITY@0..3
512+
PUB_KW@0..3 "pub"
513+
WHITESPACE@3..4 " "
514+
FN_KW@4..6 "fn"
515+
WHITESPACE@6..7 " "
516+
NAME@7..10
517+
IDENT@7..10 "foo"
518+
PARAM_LIST@10..12
519+
L_PAREN@10..11 "("
520+
R_PAREN@11..12 ")"
521+
WHITESPACE@12..13 " "
522+
RET_TYPE@13..19
523+
THIN_ARROW@13..15 "->"
524+
WHITESPACE@15..16 " "
525+
PATH_TYPE@16..19
526+
PATH@16..19
527+
PATH_SEGMENT@16..19
528+
NAME_REF@16..19
529+
IDENT@16..19 "i32"
530+
WHITESPACE@19..20 " "
531+
BLOCK_EXPR@20..22
532+
STMT_LIST@20..22
533+
L_CURLY@20..21 "{"
534+
R_CURLY@21..22 "}"
535+
"#]],
536+
);
537+
}
473538
}

0 commit comments

Comments
 (0)