3913: Remove allocations from LCA r=matklad a=matklad

I haven't actually profiled this, but not allocating a hash map (or
anything, really) seems like a good idea



bors r+
🤖

Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2020-04-09 11:58:15 +00:00 committed by GitHub
commit d416d892fc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -7,7 +7,7 @@ use std::{
use itertools::Itertools; use itertools::Itertools;
use ra_text_edit::TextEditBuilder; use ra_text_edit::TextEditBuilder;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::FxHashMap;
use crate::{ use crate::{
AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxNodePtr, SyntaxToken, AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxNodePtr, SyntaxToken,
@ -72,8 +72,18 @@ pub fn find_covering_element(root: &SyntaxNode, range: TextRange) -> SyntaxEleme
} }
pub fn least_common_ancestor(u: &SyntaxNode, v: &SyntaxNode) -> Option<SyntaxNode> { pub fn least_common_ancestor(u: &SyntaxNode, v: &SyntaxNode) -> Option<SyntaxNode> {
let u_ancestors = u.ancestors().collect::<FxHashSet<SyntaxNode>>(); if u == v {
v.ancestors().find(|it| u_ancestors.contains(it)) return Some(u.clone());
}
let u_depth = u.ancestors().count();
let v_depth = v.ancestors().count();
let keep = u_depth.min(v_depth);
let u_candidates = u.ancestors().skip(u_depth - keep);
let v_canidates = v.ancestors().skip(v_depth - keep);
let (res, _) = u_candidates.zip(v_canidates).find(|(x, y)| x == y)?;
Some(res)
} }
pub fn neighbor<T: AstNode>(me: &T, direction: Direction) -> Option<T> { pub fn neighbor<T: AstNode>(me: &T, direction: Direction) -> Option<T> {