aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_editor/src/typing.rs82
1 files changed, 72 insertions, 10 deletions
diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs
index 528c7b200..c9bc55ccc 100644
--- a/crates/ra_editor/src/typing.rs
+++ b/crates/ra_editor/src/typing.rs
@@ -5,7 +5,7 @@ use ra_syntax::{
5 algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset}, 5 algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset},
6 ast, 6 ast,
7 text_utils::intersect, 7 text_utils::intersect,
8 AstNode, SourceFileNode, SyntaxKind, 8 AstNode, Direction, SourceFileNode, SyntaxKind,
9 SyntaxKind::*, 9 SyntaxKind::*,
10 SyntaxNodeRef, TextRange, TextUnit, 10 SyntaxNodeRef, TextRange, TextUnit,
11}; 11};
@@ -139,15 +139,41 @@ pub fn on_eq_typed(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit>
139pub fn on_dot_typed(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit> { 139pub fn on_dot_typed(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit> {
140 let before_dot_offset = offset - TextUnit::of_char('.'); 140 let before_dot_offset = offset - TextUnit::of_char('.');
141 141
142 let _whitespace = find_leaf_at_offset(file.syntax(), before_dot_offset) 142 let _whitespace = find_leaf_at_offset(file.syntax(), before_dot_offset).left_biased()?;
143 .left_biased() 143
144 .and_then(ast::Whitespace::cast)?; 144 // find whitespace just left of the dot
145 ast::Whitespace::cast(_whitespace)?;
146
147 // make sure there is a method call
148 let _method_call = _whitespace
149 .siblings(Direction::Prev)
150 // first is whitespace
151 .skip(1)
152 .next()?;
153
154 ast::MethodCallExprNode::cast(_method_call)?;
155
156 // find how much the _method call is indented
157 let method_chain_indent = _method_call
158 .ancestors()
159 .skip(1)
160 .next()?
161 .siblings(Direction::Prev)
162 .skip(1)
163 .next()?
164 .leaf_text()
165 .map(|x| last_line_indent_in_whitespace(x))?;
145 166
146 // whitespace found just left of the dot 167 let current_indent = TextUnit::of_str(last_line_indent_in_whitespace(_whitespace.leaf_text()?));
147 // TODO: indent is always 4 spaces now. A better heuristic could look on the previous line(s) 168 // TODO: indent is always 4 spaces now. A better heuristic could look on the previous line(s)
148 let indent = " ".to_string();
149 169
150 let cursor_position = offset + TextUnit::of_str(&indent);; 170 let target_indent = TextUnit::of_str(method_chain_indent) + TextUnit::from_usize(4);
171
172 let diff = target_indent - current_indent;
173
174 let indent = "".repeat(diff.to_usize());
175
176 let cursor_position = offset + diff;
151 let mut edit = TextEditBuilder::default(); 177 let mut edit = TextEditBuilder::default();
152 edit.insert(before_dot_offset, indent); 178 edit.insert(before_dot_offset, indent);
153 Some(LocalEdit { 179 Some(LocalEdit {
@@ -157,6 +183,11 @@ pub fn on_dot_typed(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit
157 }) 183 })
158} 184}
159 185
186/// Finds the last line in the whitespace
187fn last_line_indent_in_whitespace(ws: &str) -> &str {
188 ws.split('\n').last().unwrap_or("")
189}
190
160fn remove_newline( 191fn remove_newline(
161 edit: &mut TextEditBuilder, 192 edit: &mut TextEditBuilder,
162 node: SyntaxNodeRef, 193 node: SyntaxNodeRef,
@@ -642,9 +673,10 @@ fn foo() {
642 fn do_check(before: &str, after: &str) { 673 fn do_check(before: &str, after: &str) {
643 let (offset, before) = extract_offset(before); 674 let (offset, before) = extract_offset(before);
644 let file = SourceFileNode::parse(&before); 675 let file = SourceFileNode::parse(&before);
645 let result = on_dot_typed(&file, offset).unwrap(); 676 if let Some(result) = on_eq_typed(&file, offset) {
646 let actual = result.edit.apply(&before); 677 let actual = result.edit.apply(&before);
647 assert_eq_text!(after, &actual); 678 assert_eq_text!(after, &actual);
679 };
648 } 680 }
649 // indent if continuing chain call 681 // indent if continuing chain call
650 do_check( 682 do_check(
@@ -713,6 +745,36 @@ fn foo() {
713 } 745 }
714", 746",
715 ); 747 );
748
749 // don't indent if there is no method call on previous line
750 do_check(
751 r"
752 pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> {
753 .<|>
754 }
755",
756 r"
757 pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> {
758 .
759 }
760",
761 );
762
763 // indent to match previous expr
764 do_check(
765 r"
766 pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> {
767 self.child_impl(db, name)
768.<|>
769 }
770",
771 r"
772 pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> {
773 self.child_impl(db, name)
774 .
775 }
776",
777 );
716 } 778 }
717 779
718 #[test] 780 #[test]