Unnamed repository; edit this file 'description' to name the repository.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

<style>
body                { margin: 0; }
pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }

.lifetime           { color: #DFAF8F; font-style: italic; }
.label              { color: #DFAF8F; font-style: italic; }
.comment            { color: #7F9F7F; }
.documentation      { color: #629755; }
.intra_doc_link     { font-style: italic; }
.injected           { opacity: 0.65 ; }
.struct, .enum      { color: #7CB8BB; }
.enum_variant       { color: #BDE0F3; }
.string_literal     { color: #CC9393; }
.field              { color: #94BFF3; }
.function           { color: #93E0E3; }
.parameter          { color: #94BFF3; }
.text               { color: #DCDCCC; }
.type               { color: #7CB8BB; }
.builtin_type       { color: #8CD0D3; }
.type_param         { color: #DFAF8F; }
.attribute          { color: #94BFF3; }
.numeric_literal    { color: #BFEBBF; }
.bool_literal       { color: #BFE6EB; }
.macro              { color: #94BFF3; }
.proc_macro         { color: #94BFF3; text-decoration: underline; }
.derive             { color: #94BFF3; font-style: italic; }
.module             { color: #AFD8AF; }
.value_param        { color: #DCDCCC; }
.variable           { color: #DCDCCC; }
.format_specifier   { color: #CC696B; }
.mutable            { text-decoration: underline; }
.escape_sequence    { color: #94BFF3; }
.keyword            { color: #F0DFAF; font-weight: bold; }
.control            { font-style: italic; }
.reference          { font-style: italic; font-weight: bold; }
.const              { font-weight: bolder; }
.unsafe             { color: #BC8383; }

.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
</style>
<pre><code><span class="keyword">fn</span> <span class="function declaration">fixture</span><span class="parenthesis">(</span><span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="tool_module attribute">rust_analyzer</span><span class="operator attribute">::</span><span class="tool_module attribute">rust_fixture</span><span class="attribute_bracket attribute">]</span> <span class="value_param declaration reference">ra_fixture</span><span class="colon">:</span> <span class="punctuation">&</span><span class="builtin_type">str</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>

<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
    <span class="function">fixture</span><span class="parenthesis">(</span><span class="string_literal">r#"</span><span class="none injected">
</span><span class="keyword injected">trait</span><span class="none injected"> </span><span class="trait declaration injected">Foo</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected">
    </span><span class="keyword injected">fn</span><span class="none injected"> </span><span class="function associated declaration injected static trait">foo</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected">
        </span><span class="unresolved_reference injected">println</span><span class="macro_bang injected">!</span><span class="parenthesis injected">(</span><span class="string_literal injected">"2 + 2 = {}"</span><span class="comma injected">,</span><span class="none injected"> </span><span class="numeric_literal injected">4</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span><span class="none injected">
    </span><span class="brace injected">}</span><span class="none injected">
</span><span class="brace injected">}</span><span class="string_literal">"#</span>
    <span class="parenthesis">)</span><span class="semicolon">;</span>
    <span class="function">fixture</span><span class="parenthesis">(</span><span class="string_literal">r"</span><span class="none injected">
</span><span class="keyword injected">fn</span><span class="none injected"> </span><span class="function declaration injected">foo</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected">
    </span><span class="function injected">foo</span><span class="parenthesis injected">(</span><span class="keyword injected">$0</span><span class="brace injected">{</span><span class="none injected">
        </span><span class="numeric_literal injected">92</span><span class="none injected">
    </span><span class="brace injected">}</span><span class="keyword injected">$0</span><span class="parenthesis injected">)</span><span class="none injected">
</span><span class="brace injected">}</span><span class="string_literal">"</span>
    <span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="brace">}</span></code></pre>
e = node.clone_subtree(); let mut editor = SyntaxEditor::new(node.clone()); let tokens = node .preorder_with_tokens() .filter_map(|event| match event { rowan::WalkEvent::Leave(NodeOrToken::Token(it)) => Some(it), _ => None, }) .filter_map(ast::Whitespace::cast) .filter(|ws| ws.text().contains('\n')); for ws in tokens { let new_ws = make::tokens::whitespace(&format!("{}{self}", ws.syntax())); editor.replace(ws.syntax(), &new_ws); } editor.finish().new_root().clone() } pub(super) fn decrease_indent(self, node: &SyntaxNode) { let tokens = node.preorder_with_tokens().filter_map(|event| match event { rowan::WalkEvent::Leave(NodeOrToken::Token(it)) => Some(it), _ => None, }); for token in tokens { if let Some(ws) = ast::Whitespace::cast(token) && ws.text().contains('\n') { let new_ws = make::tokens::whitespace( &ws.syntax().text().replace(&format!("\n{self}"), "\n"), ); ted::replace(ws.syntax(), &new_ws); } } } pub(super) fn clone_decrease_indent(self, node: &SyntaxNode) -> SyntaxNode { let node = node.clone_subtree(); let mut editor = SyntaxEditor::new(node.clone()); let tokens = node .preorder_with_tokens() .filter_map(|event| match event { rowan::WalkEvent::Leave(NodeOrToken::Token(it)) => Some(it), _ => None, }) .filter_map(ast::Whitespace::cast) .filter(|ws| ws.text().contains('\n')); for ws in tokens { let new_ws = make::tokens::whitespace(&ws.syntax().text().replace(&format!("\n{self}"), "\n")); editor.replace(ws.syntax(), &new_ws); } editor.finish().new_root().clone() } } fn prev_tokens(token: SyntaxToken) -> impl Iterator<Item = SyntaxToken> { iter::successors(Some(token), |token| token.prev_token()) } pub trait AstNodeEdit: AstNode + Clone + Sized { fn indent_level(&self) -> IndentLevel { IndentLevel::from_node(self.syntax()) } #[must_use] fn indent(&self, level: IndentLevel) -> Self { Self::cast(level.clone_increase_indent(self.syntax())).unwrap() } #[must_use] fn indent_with_mapping(&self, level: IndentLevel, make: &SyntaxFactory) -> Self { let new_node = self.indent(level); if let Some(mut mapping) = make.mappings() { let mut builder = SyntaxMappingBuilder::new(new_node.syntax().clone()); for (old, new) in self.syntax().children().zip(new_node.syntax().children()) { builder.map_node(old, new); } builder.finish(&mut mapping); } new_node } #[must_use] fn dedent(&self, level: IndentLevel) -> Self { Self::cast(level.clone_decrease_indent(self.syntax())).unwrap() } #[must_use] fn reset_indent(&self) -> Self { let level = IndentLevel::from_node(self.syntax()); self.dedent(level) } } impl<N: AstNode + Clone> AstNodeEdit for N {} #[test] fn test_increase_indent() { let arm_list = { let arm = make::match_arm(make::wildcard_pat().into(), None, make::ext::expr_unit()); make::match_arm_list([arm.clone(), arm]) }; assert_eq!( arm_list.syntax().to_string(), "{ _ => (), _ => (), }" ); let indented = arm_list.indent(IndentLevel(2)); assert_eq!( indented.syntax().to_string(), "{ _ => (), _ => (), }" ); }