From 0be055072d511f4634855377ab26a3c227e2ab31 Mon Sep 17 00:00:00 2001 From: Simon Vandel Sillesen Date: Sun, 6 Jan 2019 21:59:14 +0100 Subject: fix tests --- crates/ra_editor/src/typing.rs | 82 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 72 insertions(+), 10 deletions(-) (limited to 'crates/ra_editor/src') 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::{ algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset}, ast, text_utils::intersect, - AstNode, SourceFileNode, SyntaxKind, + AstNode, Direction, SourceFileNode, SyntaxKind, SyntaxKind::*, SyntaxNodeRef, TextRange, TextUnit, }; @@ -139,15 +139,41 @@ pub fn on_eq_typed(file: &SourceFileNode, offset: TextUnit) -> Option pub fn on_dot_typed(file: &SourceFileNode, offset: TextUnit) -> Option { let before_dot_offset = offset - TextUnit::of_char('.'); - let _whitespace = find_leaf_at_offset(file.syntax(), before_dot_offset) - .left_biased() - .and_then(ast::Whitespace::cast)?; + let _whitespace = find_leaf_at_offset(file.syntax(), before_dot_offset).left_biased()?; + + // find whitespace just left of the dot + ast::Whitespace::cast(_whitespace)?; + + // make sure there is a method call + let _method_call = _whitespace + .siblings(Direction::Prev) + // first is whitespace + .skip(1) + .next()?; + + ast::MethodCallExprNode::cast(_method_call)?; + + // find how much the _method call is indented + let method_chain_indent = _method_call + .ancestors() + .skip(1) + .next()? + .siblings(Direction::Prev) + .skip(1) + .next()? + .leaf_text() + .map(|x| last_line_indent_in_whitespace(x))?; - // whitespace found just left of the dot + let current_indent = TextUnit::of_str(last_line_indent_in_whitespace(_whitespace.leaf_text()?)); // TODO: indent is always 4 spaces now. A better heuristic could look on the previous line(s) - let indent = " ".to_string(); - let cursor_position = offset + TextUnit::of_str(&indent);; + let target_indent = TextUnit::of_str(method_chain_indent) + TextUnit::from_usize(4); + + let diff = target_indent - current_indent; + + let indent = "".repeat(diff.to_usize()); + + let cursor_position = offset + diff; let mut edit = TextEditBuilder::default(); edit.insert(before_dot_offset, indent); Some(LocalEdit { @@ -157,6 +183,11 @@ pub fn on_dot_typed(file: &SourceFileNode, offset: TextUnit) -> Option &str { + ws.split('\n').last().unwrap_or("") +} + fn remove_newline( edit: &mut TextEditBuilder, node: SyntaxNodeRef, @@ -642,9 +673,10 @@ fn foo() { fn do_check(before: &str, after: &str) { let (offset, before) = extract_offset(before); let file = SourceFileNode::parse(&before); - let result = on_dot_typed(&file, offset).unwrap(); - let actual = result.edit.apply(&before); - assert_eq_text!(after, &actual); + if let Some(result) = on_eq_typed(&file, offset) { + let actual = result.edit.apply(&before); + assert_eq_text!(after, &actual); + }; } // indent if continuing chain call do_check( @@ -711,6 +743,36 @@ fn foo() { .first() . } +", + ); + + // don't indent if there is no method call on previous line + do_check( + r" + pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable> { + .<|> + } +", + r" + pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable> { + . + } +", + ); + + // indent to match previous expr + do_check( + r" + pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable> { + self.child_impl(db, name) +.<|> + } +", + r" + pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable> { + self.child_impl(db, name) + . + } ", ); } -- cgit v1.2.3