Make siblings an inherent method

This commit is contained in:
Aleksey Kladov 2018-10-02 18:14:33 +03:00
parent d323c81d5c
commit 1a2a8dec14
6 changed files with 30 additions and 34 deletions

View file

@ -1,12 +1,11 @@
use join_to_string::join; use join_to_string::join;
use ra_syntax::{ use ra_syntax::{
File, TextUnit, TextRange, File, TextUnit, TextRange, Direction,
ast::{self, AstNode, AttrsOwner, TypeParamsOwner, NameOwner}, ast::{self, AstNode, AttrsOwner, TypeParamsOwner, NameOwner},
SyntaxKind::{COMMA, WHITESPACE}, SyntaxKind::{COMMA, WHITESPACE},
SyntaxNodeRef, SyntaxNodeRef,
algo::{ algo::{
Direction, siblings,
find_leaf_at_offset, find_leaf_at_offset,
find_covering_node, find_covering_node,
}, },
@ -24,12 +23,12 @@ pub fn flip_comma<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce()
let syntax = file.syntax(); let syntax = file.syntax();
let comma = find_leaf_at_offset(syntax, offset).find(|leaf| leaf.kind() == COMMA)?; let comma = find_leaf_at_offset(syntax, offset).find(|leaf| leaf.kind() == COMMA)?;
let left = non_trivia_sibling(comma, Direction::Backward)?; let prev = non_trivia_sibling(comma, Direction::Prev)?;
let right = non_trivia_sibling(comma, Direction::Forward)?; let next = non_trivia_sibling(comma, Direction::Next)?;
Some(move || { Some(move || {
let mut edit = EditBuilder::new(); let mut edit = EditBuilder::new();
edit.replace(left.range(), right.text().to_string()); edit.replace(prev.range(), next.text().to_string());
edit.replace(right.range(), left.text().to_string()); edit.replace(next.range(), prev.text().to_string());
LocalEdit { LocalEdit {
edit: edit.finish(), edit: edit.finish(),
cursor_position: None, cursor_position: None,
@ -129,7 +128,7 @@ pub fn introduce_variable<'a>(file: &'a File, range: TextRange) -> Option<impl F
} }
fn non_trivia_sibling(node: SyntaxNodeRef, direction: Direction) -> Option<SyntaxNodeRef> { fn non_trivia_sibling(node: SyntaxNodeRef, direction: Direction) -> Option<SyntaxNodeRef> {
siblings(node, direction) node.siblings(direction)
.skip(1) .skip(1)
.find(|node| !node.kind().is_trivia()) .find(|node| !node.kind().is_trivia())
} }

View file

@ -1,7 +1,7 @@
use ra_syntax::{ use ra_syntax::{
File, TextRange, SyntaxNodeRef, TextUnit, File, TextRange, SyntaxNodeRef, TextUnit, Direction,
SyntaxKind::*, SyntaxKind::*,
algo::{find_leaf_at_offset, LeafAtOffset, find_covering_node, Direction, siblings}, algo::{find_leaf_at_offset, LeafAtOffset, find_covering_node},
}; };
pub fn extend_selection(file: &File, range: TextRange) -> Option<TextRange> { pub fn extend_selection(file: &File, range: TextRange) -> Option<TextRange> {
@ -71,12 +71,12 @@ fn pick_best<'a>(l: SyntaxNodeRef<'a>, r: SyntaxNodeRef<'a>) -> SyntaxNodeRef<'a
} }
fn extend_comments(node: SyntaxNodeRef) -> Option<TextRange> { fn extend_comments(node: SyntaxNodeRef) -> Option<TextRange> {
let left = adj_comments(node, Direction::Backward); let prev = adj_comments(node, Direction::Prev);
let right = adj_comments(node, Direction::Forward); let next = adj_comments(node, Direction::Next);
if left != right { if prev != next {
Some(TextRange::from_to( Some(TextRange::from_to(
left.range().start(), prev.range().start(),
right.range().end(), next.range().end(),
)) ))
} else { } else {
None None
@ -85,7 +85,7 @@ fn extend_comments(node: SyntaxNodeRef) -> Option<TextRange> {
fn adj_comments(node: SyntaxNodeRef, dir: Direction) -> SyntaxNodeRef { fn adj_comments(node: SyntaxNodeRef, dir: Direction) -> SyntaxNodeRef {
let mut res = node; let mut res = node;
for node in siblings(node, dir) { for node in node.siblings(dir) {
match node.kind() { match node.kind() {
COMMENT => res = node, COMMENT => res = node,
WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (), WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (),

View file

@ -3,7 +3,7 @@ use std::collections::HashSet;
use ra_syntax::{ use ra_syntax::{
File, TextRange, SyntaxNodeRef, File, TextRange, SyntaxNodeRef,
SyntaxKind, SyntaxKind,
algo::{Direction, siblings}, Direction,
}; };
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
@ -62,7 +62,7 @@ fn contiguous_range_for<'a>(
let left = node; let left = node;
let mut right = node; let mut right = node;
for node in siblings(node, Direction::Forward) { for node in node.siblings(Direction::Next) {
visited.insert(node); visited.insert(node);
match node.kind() { match node.kind() {
SyntaxKind::WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (), SyntaxKind::WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (),

View file

@ -94,22 +94,6 @@ pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRe
common_ancestor(left, right) common_ancestor(left, right)
} }
#[derive(Debug)]
pub enum Direction {
Forward,
Backward,
}
pub fn siblings<'a>(
node: SyntaxNodeRef<'a>,
direction: Direction
) -> impl Iterator<Item=SyntaxNodeRef<'a>> {
generate(Some(node), move |&node| match direction {
Direction::Forward => node.next_sibling(),
Direction::Backward => node.prev_sibling(),
})
}
fn common_ancestor<'a>(n1: SyntaxNodeRef<'a>, n2: SyntaxNodeRef<'a>) -> SyntaxNodeRef<'a> { fn common_ancestor<'a>(n1: SyntaxNodeRef<'a>, n2: SyntaxNodeRef<'a>) -> SyntaxNodeRef<'a> {
for p in n1.ancestors() { for p in n1.ancestors() {
if n2.ancestors().any(|a| a == p) { if n2.ancestors().any(|a| a == p) {

View file

@ -51,7 +51,7 @@ pub use {
ast::AstNode, ast::AstNode,
lexer::{tokenize, Token}, lexer::{tokenize, Token},
syntax_kinds::SyntaxKind, syntax_kinds::SyntaxKind,
yellow::{SyntaxNode, SyntaxNodeRef, OwnedRoot, RefRoot, TreeRoot, SyntaxError}, yellow::{SyntaxNode, SyntaxNodeRef, OwnedRoot, RefRoot, TreeRoot, SyntaxError, Direction},
reparsing::AtomEdit, reparsing::AtomEdit,
}; };

View file

@ -58,6 +58,13 @@ impl SyntaxNode {
SyntaxNode(::rowan::SyntaxNode::new(green, errors)) SyntaxNode(::rowan::SyntaxNode::new(green, errors))
} }
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Direction {
Next,
Prev,
}
impl<'a> SyntaxNodeRef<'a> { impl<'a> SyntaxNodeRef<'a> {
pub fn leaf_text(self) -> Option<&'a SmolStr> { pub fn leaf_text(self) -> Option<&'a SmolStr> {
self.0.leaf_text() self.0.leaf_text()
@ -71,6 +78,12 @@ impl<'a> SyntaxNodeRef<'a> {
::algo::walk::WalkEvent::Exit(_) => None, ::algo::walk::WalkEvent::Exit(_) => None,
}) })
} }
pub fn siblings(self, direction: Direction) -> impl Iterator<Item=SyntaxNodeRef<'a>> {
::algo::generate(Some(self), move |&node| match direction {
Direction::Next => node.next_sibling(),
Direction::Prev => node.prev_sibling(),
})
}
} }
impl<R: TreeRoot<RaTypes>> SyntaxNode<R> { impl<R: TreeRoot<RaTypes>> SyntaxNode<R> {