diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-09 09:56:54 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-09 09:56:54 +0000 |
commit | 34398a8756b56c323d3b4b2ef32fbca32d88a105 (patch) | |
tree | 92ebf0ec790945116e152fce7a9e3cc749c6b8e0 /crates/ra_fmt/src | |
parent | 3e8351fb0607f8711749b00d80f68bf25de01a76 (diff) | |
parent | 02dd0cfd8c7bf50cfb26c3c5178be5af4f3fdd25 (diff) |
Merge #766
766: Formatting code into ra_fmt r=matklad a=eulerdisk
As discussed https://github.com/rust-analyzer/rust-analyzer/pull/762#discussion_r254905885
I did only move the code without other improvements.
Co-authored-by: Andrea Pretto <[email protected]>
Diffstat (limited to 'crates/ra_fmt/src')
-rw-r--r-- | crates/ra_fmt/src/lib.rs | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/crates/ra_fmt/src/lib.rs b/crates/ra_fmt/src/lib.rs new file mode 100644 index 000000000..62e6fb9c1 --- /dev/null +++ b/crates/ra_fmt/src/lib.rs | |||
@@ -0,0 +1,76 @@ | |||
1 | //! This crate provides some utilities for indenting rust code. | ||
2 | //! | ||
3 | use itertools::Itertools; | ||
4 | use ra_syntax::{ | ||
5 | AstNode, | ||
6 | SyntaxNode, SyntaxKind::*, | ||
7 | ast::{self, AstToken}, | ||
8 | algo::generate, | ||
9 | }; | ||
10 | |||
11 | pub fn reindent(text: &str, indent: &str) -> String { | ||
12 | let indent = format!("\n{}", indent); | ||
13 | text.lines().intersperse(&indent).collect() | ||
14 | } | ||
15 | |||
16 | /// If the node is on the beginning of the line, calculate indent. | ||
17 | pub fn leading_indent(node: &SyntaxNode) -> Option<&str> { | ||
18 | for leaf in prev_leaves(node) { | ||
19 | if let Some(ws) = ast::Whitespace::cast(leaf) { | ||
20 | let ws_text = ws.text(); | ||
21 | if let Some(pos) = ws_text.rfind('\n') { | ||
22 | return Some(&ws_text[pos + 1..]); | ||
23 | } | ||
24 | } | ||
25 | if leaf.leaf_text().unwrap().contains('\n') { | ||
26 | break; | ||
27 | } | ||
28 | } | ||
29 | None | ||
30 | } | ||
31 | |||
32 | fn prev_leaves(node: &SyntaxNode) -> impl Iterator<Item = &SyntaxNode> { | ||
33 | generate(prev_leaf(node), |&node| prev_leaf(node)) | ||
34 | } | ||
35 | |||
36 | fn prev_leaf(node: &SyntaxNode) -> Option<&SyntaxNode> { | ||
37 | generate(node.ancestors().find_map(SyntaxNode::prev_sibling), |it| it.last_child()).last() | ||
38 | } | ||
39 | |||
40 | pub fn extract_trivial_expression(block: &ast::Block) -> Option<&ast::Expr> { | ||
41 | let expr = block.expr()?; | ||
42 | if expr.syntax().text().contains('\n') { | ||
43 | return None; | ||
44 | } | ||
45 | let non_trivial_children = block.syntax().children().filter(|it| match it.kind() { | ||
46 | WHITESPACE | L_CURLY | R_CURLY => false, | ||
47 | _ => it != &expr.syntax(), | ||
48 | }); | ||
49 | if non_trivial_children.count() > 0 { | ||
50 | return None; | ||
51 | } | ||
52 | Some(expr) | ||
53 | } | ||
54 | |||
55 | pub fn compute_ws(left: &SyntaxNode, right: &SyntaxNode) -> &'static str { | ||
56 | match left.kind() { | ||
57 | L_PAREN | L_BRACK => return "", | ||
58 | L_CURLY => { | ||
59 | if let USE_TREE = right.kind() { | ||
60 | return ""; | ||
61 | } | ||
62 | } | ||
63 | _ => (), | ||
64 | } | ||
65 | match right.kind() { | ||
66 | R_PAREN | R_BRACK => return "", | ||
67 | R_CURLY => { | ||
68 | if let USE_TREE = left.kind() { | ||
69 | return ""; | ||
70 | } | ||
71 | } | ||
72 | DOT => return "", | ||
73 | _ => (), | ||
74 | } | ||
75 | " " | ||
76 | } | ||