aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_fmt
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_fmt')
-rw-r--r--crates/ra_fmt/Cargo.toml11
-rw-r--r--crates/ra_fmt/src/lib.rs76
2 files changed, 87 insertions, 0 deletions
diff --git a/crates/ra_fmt/Cargo.toml b/crates/ra_fmt/Cargo.toml
new file mode 100644
index 000000000..1cf1b520f
--- /dev/null
+++ b/crates/ra_fmt/Cargo.toml
@@ -0,0 +1,11 @@
1[package]
2edition = "2018"
3name = "ra_fmt"
4version = "0.1.0"
5authors = ["Aleksey Kladov <[email protected]>"]
6publish = false
7
8[dependencies]
9itertools = "0.8.0"
10
11ra_syntax = { path = "../ra_syntax" }
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//!
3use itertools::Itertools;
4use ra_syntax::{
5 AstNode,
6 SyntaxNode, SyntaxKind::*,
7 ast::{self, AstToken},
8 algo::generate,
9};
10
11pub 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.
17pub 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
32fn prev_leaves(node: &SyntaxNode) -> impl Iterator<Item = &SyntaxNode> {
33 generate(prev_leaf(node), |&node| prev_leaf(node))
34}
35
36fn prev_leaf(node: &SyntaxNode) -> Option<&SyntaxNode> {
37 generate(node.ancestors().find_map(SyntaxNode::prev_sibling), |it| it.last_child()).last()
38}
39
40pub 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
55pub 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}