diff --git a/crates/ra_editor/src/code_actions.rs b/crates/ra_editor/src/code_actions.rs index 83f7956d293..216d592ff45 100644 --- a/crates/ra_editor/src/code_actions.rs +++ b/crates/ra_editor/src/code_actions.rs @@ -1,15 +1,13 @@ use join_to_string::join; use ra_syntax::{ - File, TextUnit, TextRange, + File, TextUnit, TextRange, Direction, ast::{self, AstNode, AttrsOwner, TypeParamsOwner, NameOwner}, SyntaxKind::{COMMA, WHITESPACE}, SyntaxNodeRef, algo::{ - Direction, siblings, find_leaf_at_offset, find_covering_node, - ancestors, }, }; @@ -25,12 +23,12 @@ pub fn flip_comma<'a>(file: &'a File, offset: TextUnit) -> Option(file: &'a File, offset: TextUnit) -> Option pub fn introduce_variable<'a>(file: &'a File, range: TextRange) -> Option LocalEdit + 'a> { let node = find_covering_node(file.syntax(), range); - let expr = ancestors(node).filter_map(ast::Expr::cast).next()?; - let anchor_stmt = ancestors(expr.syntax()).filter_map(ast::Stmt::cast).next()?; + let expr = node.ancestors().filter_map(ast::Expr::cast).next()?; + let anchor_stmt = expr.syntax().ancestors().filter_map(ast::Stmt::cast).next()?; let indent = anchor_stmt.syntax().prev_sibling()?; if indent.kind() != WHITESPACE { return None; @@ -130,7 +128,7 @@ pub fn introduce_variable<'a>(file: &'a File, range: TextRange) -> Option Option { - siblings(node, direction) + node.siblings(direction) .skip(1) .find(|node| !node.kind().is_trivia()) } diff --git a/crates/ra_editor/src/completion.rs b/crates/ra_editor/src/completion.rs index ff9de20d387..62a63fb0440 100644 --- a/crates/ra_editor/src/completion.rs +++ b/crates/ra_editor/src/completion.rs @@ -4,7 +4,6 @@ File, TextUnit, AstNode, SyntaxNodeRef, SyntaxKind::*, ast::{self, LoopBodyOwner, ModuleItemOwner}, algo::{ - ancestors, visit::{visitor, Visitor, visitor_ctx, VisitorCtx}, }, text_utils::is_subrange, @@ -59,7 +58,7 @@ fn complete_name_ref(file: &File, name_ref: ast::NameRef, acc: &mut Vec(|it| Some(it.items())) .visit::(|it| Some(it.item_list()?.items())) @@ -92,7 +91,7 @@ fn complete_name_ref(file: &File, name_ref: ast::NameRef, acc: &mut Vec) { let mut params = HashMap::new(); - for node in ancestors(ctx) { + for node in ctx.ancestors() { let _ = visitor_ctx(&mut params) .visit::(process) .visit::(process) @@ -123,7 +122,7 @@ fn process<'a, N: ast::FnDefOwner<'a>>(node: N, params: &mut HashMap>(node: SyntaxNodeRef<'a>) -> bool { - match ancestors(node).filter_map(N::cast).next() { + match node.ancestors().filter_map(N::cast).next() { None => false, Some(n) => n.syntax().range() == node.range(), } @@ -152,7 +151,7 @@ fn complete_expr_keywords(file: &File, fn_def: ast::FnDef, name_ref: ast::NameRe } fn is_in_loop_body(name_ref: ast::NameRef) -> bool { - for node in ancestors(name_ref.syntax()) { + for node in name_ref.syntax().ancestors() { if node.kind() == FN_DEF || node.kind() == LAMBDA_EXPR { break; } @@ -171,7 +170,7 @@ fn is_in_loop_body(name_ref: ast::NameRef) -> bool { } fn complete_return(fn_def: ast::FnDef, name_ref: ast::NameRef) -> Option { - // let is_last_in_block = ancestors(name_ref.syntax()).filter_map(ast::Expr::cast) + // let is_last_in_block = name_ref.syntax().ancestors().filter_map(ast::Expr::cast) // .next() // .and_then(|it| it.syntax().parent()) // .and_then(ast::Block::cast) @@ -181,7 +180,7 @@ fn complete_return(fn_def: ast::FnDef, name_ref: ast::NameRef) -> Option false, Some(expr_stmt) => expr_stmt.syntax().range() == name_ref.syntax().range() }; diff --git a/crates/ra_editor/src/extend_selection.rs b/crates/ra_editor/src/extend_selection.rs index dc914a26ada..b00a457b901 100644 --- a/crates/ra_editor/src/extend_selection.rs +++ b/crates/ra_editor/src/extend_selection.rs @@ -1,7 +1,7 @@ use ra_syntax::{ - File, TextRange, SyntaxNodeRef, TextUnit, + File, TextRange, SyntaxNodeRef, TextUnit, Direction, SyntaxKind::*, - algo::{find_leaf_at_offset, LeafAtOffset, find_covering_node, ancestors, Direction, siblings}, + algo::{find_leaf_at_offset, LeafAtOffset, find_covering_node}, }; pub fn extend_selection(file: &File, range: TextRange) -> Option { @@ -30,7 +30,7 @@ pub(crate) fn extend(root: SyntaxNodeRef, range: TextRange) -> Option } } - match ancestors(node).skip_while(|n| n.range() == range).next() { + match node.ancestors().skip_while(|n| n.range() == range).next() { None => None, Some(parent) => Some(parent.range()), } @@ -71,12 +71,12 @@ fn priority(n: SyntaxNodeRef) -> usize { } fn extend_comments(node: SyntaxNodeRef) -> Option { - let left = adj_comments(node, Direction::Backward); - let right = adj_comments(node, Direction::Forward); - if left != right { + let prev = adj_comments(node, Direction::Prev); + let next = adj_comments(node, Direction::Next); + if prev != next { Some(TextRange::from_to( - left.range().start(), - right.range().end(), + prev.range().start(), + next.range().end(), )) } else { None @@ -85,7 +85,7 @@ fn extend_comments(node: SyntaxNodeRef) -> Option { fn adj_comments(node: SyntaxNodeRef, dir: Direction) -> SyntaxNodeRef { let mut res = node; - for node in siblings(node, dir) { + for node in node.siblings(dir) { match node.kind() { COMMENT => res = node, WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (), diff --git a/crates/ra_editor/src/folding_ranges.rs b/crates/ra_editor/src/folding_ranges.rs index 817da28d1a5..733512368ef 100644 --- a/crates/ra_editor/src/folding_ranges.rs +++ b/crates/ra_editor/src/folding_ranges.rs @@ -3,7 +3,7 @@ use ra_syntax::{ File, TextRange, SyntaxNodeRef, SyntaxKind, - algo::{walk, Direction, siblings}, + Direction, }; #[derive(Debug, PartialEq, Eq)] @@ -19,12 +19,10 @@ pub struct Fold { } pub fn folding_ranges(file: &File) -> Vec { - let syntax = file.syntax(); - let mut res = vec![]; let mut visited = HashSet::new(); - for node in walk::preorder(syntax) { + for node in file.syntax().descendants() { if visited.contains(&node) { continue; } @@ -64,7 +62,7 @@ fn contiguous_range_for<'a>( let left = node; let mut right = node; - for node in siblings(node, Direction::Forward) { + for node in node.siblings(Direction::Next) { visited.insert(node); match node.kind() { SyntaxKind::WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (), @@ -139,4 +137,4 @@ fn main() { } -} \ No newline at end of file +} diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs index de929d73a6f..a93924e0051 100644 --- a/crates/ra_editor/src/lib.rs +++ b/crates/ra_editor/src/lib.rs @@ -21,7 +21,7 @@ use ra_syntax::{ File, TextUnit, TextRange, SyntaxNodeRef, ast::{self, AstNode, NameOwner}, - algo::{walk, find_leaf_at_offset, ancestors}, + algo::find_leaf_at_offset, SyntaxKind::{self, *}, }; pub use ra_syntax::AtomEdit; @@ -86,7 +86,7 @@ pub fn matching_brace(file: &File, offset: TextUnit) -> Option { pub fn highlight(file: &File) -> Vec { let mut res = Vec::new(); - for node in walk::preorder(file.syntax()) { + for node in file.syntax().descendants() { let tag = match node.kind() { ERROR => "error", COMMENT | DOC_COMMENT => "comment", @@ -110,7 +110,7 @@ pub fn highlight(file: &File) -> Vec { pub fn diagnostics(file: &File) -> Vec { let mut res = Vec::new(); - for node in walk::preorder(file.syntax()) { + for node in file.syntax().descendants() { if node.kind() == ERROR { res.push(Diagnostic { range: node.range(), @@ -130,7 +130,7 @@ pub fn syntax_tree(file: &File) -> String { } pub fn runnables(file: &File) -> Vec { - walk::preorder(file.syntax()) + file.syntax().descendants() .filter_map(ast::FnDef::cast) .filter_map(|f| { let name = f.name()?.text(); @@ -159,7 +159,7 @@ pub fn find_node_at_offset<'a, N: AstNode<'a>>( let leaf = leaves.clone() .find(|leaf| !leaf.kind().is_trivia()) .or_else(|| leaves.right_biased())?; - ancestors(leaf) + leaf.ancestors() .filter_map(N::cast) .next() } diff --git a/crates/ra_editor/src/scope/fn_scope.rs b/crates/ra_editor/src/scope/fn_scope.rs index 3ae5276a22c..eddd874956f 100644 --- a/crates/ra_editor/src/scope/fn_scope.rs +++ b/crates/ra_editor/src/scope/fn_scope.rs @@ -6,7 +6,7 @@ use ra_syntax::{ SyntaxNodeRef, SyntaxNode, SmolStr, AstNode, ast::{self, NameOwner, LoopBodyOwner, ArgListOwner}, - algo::{ancestors, generate, walk::preorder} + algo::{generate} }; type ScopeId = usize; @@ -51,7 +51,7 @@ fn new_scope(&mut self, parent: ScopeId) -> ScopeId { res } fn add_bindings(&mut self, scope: ScopeId, pat: ast::Pat) { - let entries = preorder(pat.syntax()) + let entries = pat.syntax().descendants() .filter_map(ast::BindPat::cast) .filter_map(ScopeEntry::new); self.scopes[scope].entries.extend(entries); @@ -66,7 +66,7 @@ fn set_scope(&mut self, node: SyntaxNodeRef, scope: ScopeId) { self.scope_for.insert(node.owned(), scope); } fn scope_for(&self, node: SyntaxNodeRef) -> Option { - ancestors(node) + node.ancestors() .filter_map(|it| self.scope_for.get(&it.owned()).map(|&scope| scope)) .next() } diff --git a/crates/ra_editor/src/symbols.rs b/crates/ra_editor/src/symbols.rs index 91798417729..e5cc5ca284f 100644 --- a/crates/ra_editor/src/symbols.rs +++ b/crates/ra_editor/src/symbols.rs @@ -3,7 +3,7 @@ ast::{self, NameOwner}, algo::{ visit::{visitor, Visitor}, - walk::{walk, WalkEvent, preorder}, + walk::{walk, WalkEvent}, }, }; use TextRange; @@ -25,7 +25,7 @@ pub struct FileSymbol { } pub fn file_symbols(file: &File) -> Vec { - preorder(file.syntax()) + file.syntax().descendants() .filter_map(to_symbol) .collect() } diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs index 0f4e7e0d029..5120769418e 100644 --- a/crates/ra_editor/src/typing.rs +++ b/crates/ra_editor/src/typing.rs @@ -4,7 +4,6 @@ TextUnit, TextRange, SyntaxNodeRef, File, AstNode, SyntaxKind, ast, algo::{ - walk::preorder, find_covering_node, }, text_utils::{intersect, contains_offset_nonstrict}, @@ -33,7 +32,7 @@ pub fn join_lines(file: &File, range: TextRange) -> LocalEdit { }; let node = find_covering_node(file.syntax(), range); let mut edit = EditBuilder::new(); - for node in preorder(node) { + for node in node.descendants() { let text = match node.leaf_text() { Some(text) => text, None => continue, diff --git a/crates/ra_syntax/src/algo/mod.rs b/crates/ra_syntax/src/algo/mod.rs index 8de44c58614..a6678093d9e 100644 --- a/crates/ra_syntax/src/algo/mod.rs +++ b/crates/ra_syntax/src/algo/mod.rs @@ -94,29 +94,9 @@ pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRe common_ancestor(left, right) } -pub fn ancestors<'a>(node: SyntaxNodeRef<'a>) -> impl Iterator> { - generate(Some(node), |&node| node.parent()) -} - -#[derive(Debug)] -pub enum Direction { - Forward, - Backward, -} - -pub fn siblings<'a>( - node: SyntaxNodeRef<'a>, - direction: Direction -) -> impl Iterator> { - 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> { - for p in ancestors(n1) { - if ancestors(n2).any(|a| a == p) { + for p in n1.ancestors() { + if n2.ancestors().any(|a| a == p) { return p; } } diff --git a/crates/ra_syntax/src/algo/walk.rs b/crates/ra_syntax/src/algo/walk.rs index 536ee705fbd..8e294d965b0 100644 --- a/crates/ra_syntax/src/algo/walk.rs +++ b/crates/ra_syntax/src/algo/walk.rs @@ -3,12 +3,6 @@ algo::generate, }; -pub fn preorder<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator> { - walk(root).filter_map(|event| match event { - WalkEvent::Enter(node) => Some(node), - WalkEvent::Exit(_) => None, - }) -} #[derive(Debug, Copy, Clone)] pub enum WalkEvent<'a> { diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index c7eda45636e..738664afd0a 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs @@ -51,7 +51,7 @@ ast::AstNode, lexer::{tokenize, Token}, syntax_kinds::SyntaxKind, - yellow::{SyntaxNode, SyntaxNodeRef, OwnedRoot, RefRoot, TreeRoot, SyntaxError}, + yellow::{SyntaxNode, SyntaxNodeRef, OwnedRoot, RefRoot, TreeRoot, SyntaxError, Direction}, reparsing::AtomEdit, }; diff --git a/crates/ra_syntax/src/reparsing.rs b/crates/ra_syntax/src/reparsing.rs index e3c200d1e13..dcafd2c4076 100644 --- a/crates/ra_syntax/src/reparsing.rs +++ b/crates/ra_syntax/src/reparsing.rs @@ -112,7 +112,7 @@ fn find_reparsable_node<'node>( range: TextRange, ) -> Option<(SyntaxNodeRef<'node>, fn(&mut Parser))> { let node = algo::find_covering_node(node, range); - return algo::ancestors(node) + return node.ancestors() .filter_map(|node| reparser(node).map(|r| (node, r))) .next(); diff --git a/crates/ra_syntax/src/utils.rs b/crates/ra_syntax/src/utils.rs index 8bc5f0e24cc..e274f7471f8 100644 --- a/crates/ra_syntax/src/utils.rs +++ b/crates/ra_syntax/src/utils.rs @@ -1,6 +1,6 @@ use std::fmt::Write; use { - algo::walk::{preorder, walk, WalkEvent}, + algo::walk::{walk, WalkEvent}, SyntaxKind, File, SyntaxNodeRef }; @@ -56,7 +56,7 @@ pub fn check_fuzz_invariants(text: &str) { pub(crate) fn validate_block_structure(root: SyntaxNodeRef) { let mut stack = Vec::new(); - for node in preorder(root) { + for node in root.descendants() { match node.kind() { SyntaxKind::L_CURLY => { stack.push(node) diff --git a/crates/ra_syntax/src/yellow/mod.rs b/crates/ra_syntax/src/yellow/mod.rs index c621b1d6a3a..710320f47ca 100644 --- a/crates/ra_syntax/src/yellow/mod.rs +++ b/crates/ra_syntax/src/yellow/mod.rs @@ -53,15 +53,37 @@ fn hash(&self, state: &mut H) { } } -impl SyntaxNode { +impl SyntaxNode { pub(crate) fn new(green: GreenNode, errors: Vec) -> SyntaxNode { SyntaxNode(::rowan::SyntaxNode::new(green, errors)) } } -impl<'a> SyntaxNode> { + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Direction { + Next, + Prev, +} + +impl<'a> SyntaxNodeRef<'a> { pub fn leaf_text(self) -> Option<&'a SmolStr> { self.0.leaf_text() } + pub fn ancestors(self) -> impl Iterator> { + ::algo::generate(Some(self), |&node| node.parent()) + } + pub fn descendants(self) -> impl Iterator> { + ::algo::walk::walk(self).filter_map(|event| match event { + ::algo::walk::WalkEvent::Enter(node) => Some(node), + ::algo::walk::WalkEvent::Exit(_) => None, + }) + } + pub fn siblings(self, direction: Direction) -> impl Iterator> { + ::algo::generate(Some(self), move |&node| match direction { + Direction::Next => node.next_sibling(), + Direction::Prev => node.prev_sibling(), + }) + } } impl> SyntaxNode { diff --git a/crates/ra_syntax/src/yellow/syntax_text.rs b/crates/ra_syntax/src/yellow/syntax_text.rs index affd7f9c7d4..0db1049de9b 100644 --- a/crates/ra_syntax/src/yellow/syntax_text.rs +++ b/crates/ra_syntax/src/yellow/syntax_text.rs @@ -4,7 +4,6 @@ use { SyntaxNodeRef, TextRange, TextUnit, - algo::walk::preorder, text_utils::{intersect, contains_offset_nonstrict}, }; @@ -23,7 +22,8 @@ pub(crate) fn new(node: SyntaxNodeRef<'a>) -> SyntaxText<'a> { } pub fn chunks(&self) -> impl Iterator { let range = self.range; - preorder(self.node) + self.node + .descendants() .filter_map(move |node| { let text = node.leaf_text()?; let range = intersect(range, node.range())?;