Improve insert_whitespaces
This commit is contained in:
parent
4012da07fd
commit
80fe467ce8
@ -8,7 +8,7 @@
|
|||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
algo::{find_node_at_offset, replace_descendants},
|
algo::{find_node_at_offset, replace_descendants},
|
||||||
ast::{self},
|
ast::{self},
|
||||||
AstNode, NodeOrToken, SyntaxKind, SyntaxNode, WalkEvent,
|
AstNode, NodeOrToken, SyntaxKind, SyntaxNode, WalkEvent, T,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct ExpandedMacro {
|
pub struct ExpandedMacro {
|
||||||
@ -55,9 +55,12 @@ fn expand_macro_recur(
|
|||||||
Some(replace_descendants(&expanded, &replaces))
|
Some(replace_descendants(&expanded, &replaces))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: It would also be cool to share logic here and in the mbe tests,
|
||||||
|
// which are pretty unreadable at the moment.
|
||||||
fn insert_whitespaces(syn: SyntaxNode) -> String {
|
fn insert_whitespaces(syn: SyntaxNode) -> String {
|
||||||
let mut res = String::new();
|
use SyntaxKind::*;
|
||||||
|
|
||||||
|
let mut res = String::new();
|
||||||
let mut token_iter = syn
|
let mut token_iter = syn
|
||||||
.preorder_with_tokens()
|
.preorder_with_tokens()
|
||||||
.filter_map(|event| {
|
.filter_map(|event| {
|
||||||
@ -69,16 +72,44 @@ fn insert_whitespaces(syn: SyntaxNode) -> String {
|
|||||||
})
|
})
|
||||||
.peekable();
|
.peekable();
|
||||||
|
|
||||||
|
let mut indent = 0;
|
||||||
|
let mut last: Option<SyntaxKind> = None;
|
||||||
|
|
||||||
while let Some(token) = token_iter.next() {
|
while let Some(token) = token_iter.next() {
|
||||||
res += &token.text().to_string();
|
let mut is_next = |f: fn(SyntaxKind) -> bool, default| -> bool {
|
||||||
if token.kind().is_keyword()
|
token_iter.peek().map(|it| f(it.kind())).unwrap_or(default)
|
||||||
|| token.kind().is_literal()
|
};
|
||||||
|| token.kind() == SyntaxKind::IDENT
|
let is_last = |f: fn(SyntaxKind) -> bool, default| -> bool {
|
||||||
|
last.map(|it| f(it)).unwrap_or(default)
|
||||||
|
};
|
||||||
|
|
||||||
|
res += &match token.kind() {
|
||||||
|
k @ _
|
||||||
|
if (k.is_keyword() || k.is_literal() || k == IDENT)
|
||||||
|
&& is_next(|it| !it.is_punct(), true) =>
|
||||||
{
|
{
|
||||||
if !token_iter.peek().map(|it| it.kind().is_punct()).unwrap_or(false) {
|
token.text().to_string() + " "
|
||||||
res += " ";
|
|
||||||
}
|
}
|
||||||
|
L_CURLY if is_next(|it| it != R_CURLY, true) => {
|
||||||
|
indent += 1;
|
||||||
|
format!(" {{\n{}", " ".repeat(indent))
|
||||||
}
|
}
|
||||||
|
R_CURLY if is_last(|it| it != L_CURLY, true) => {
|
||||||
|
indent = indent.checked_sub(1).unwrap_or(0);
|
||||||
|
format!("\n}}{}", " ".repeat(indent))
|
||||||
|
}
|
||||||
|
R_CURLY => {
|
||||||
|
indent = indent.checked_sub(1).unwrap_or(0);
|
||||||
|
format!("}}\n{}", " ".repeat(indent))
|
||||||
|
}
|
||||||
|
T![;] => format!(";\n{}", " ".repeat(indent)),
|
||||||
|
T![->] => " -> ".to_string(),
|
||||||
|
T![=] => " = ".to_string(),
|
||||||
|
T![=>] => " => ".to_string(),
|
||||||
|
_ => token.text().to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
last = Some(token.kind());
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
@ -86,19 +117,18 @@ fn insert_whitespaces(syn: SyntaxNode) -> String {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use super::*;
|
||||||
use crate::mock_analysis::analysis_and_position;
|
use crate::mock_analysis::analysis_and_position;
|
||||||
|
use insta::assert_snapshot;
|
||||||
|
|
||||||
fn check_expand_macro(fixture: &str, expected: (&str, &str)) {
|
fn check_expand_macro(fixture: &str) -> ExpandedMacro {
|
||||||
let (analysis, pos) = analysis_and_position(fixture);
|
let (analysis, pos) = analysis_and_position(fixture);
|
||||||
|
analysis.expand_macro(pos).unwrap().unwrap()
|
||||||
let result = analysis.expand_macro(pos).unwrap().unwrap();
|
|
||||||
assert_eq!(result.name, expected.0.to_string());
|
|
||||||
assert_eq!(result.expansion, expected.1.to_string());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn macro_expand_recursive_expansion() {
|
fn macro_expand_recursive_expansion() {
|
||||||
check_expand_macro(
|
let res = check_expand_macro(
|
||||||
r#"
|
r#"
|
||||||
//- /lib.rs
|
//- /lib.rs
|
||||||
macro_rules! bar {
|
macro_rules! bar {
|
||||||
@ -112,7 +142,37 @@ macro_rules! baz {
|
|||||||
}
|
}
|
||||||
f<|>oo!();
|
f<|>oo!();
|
||||||
"#,
|
"#,
|
||||||
("foo", "fn b(){}"),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert_eq!(res.name, "foo");
|
||||||
|
assert_snapshot!(res.expansion, @r###"
|
||||||
|
fn b(){}
|
||||||
|
"###);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn macro_expand_multiple_lines() {
|
||||||
|
let res = check_expand_macro(
|
||||||
|
r#"
|
||||||
|
//- /lib.rs
|
||||||
|
macro_rules! foo {
|
||||||
|
() => {
|
||||||
|
fn some_thing() -> u32 {
|
||||||
|
let a = 0;
|
||||||
|
a + 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f<|>oo!();
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(res.name, "foo");
|
||||||
|
assert_snapshot!(res.expansion, @r###"
|
||||||
|
fn some_thing() -> u32 {
|
||||||
|
let a = 0;
|
||||||
|
a+10
|
||||||
|
}
|
||||||
|
"###);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user