aboutsummaryrefslogtreecommitdiff
path: root/crates/syntax
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-12-10 17:07:37 +0000
committerAleksey Kladov <[email protected]>2020-12-10 17:07:37 +0000
commit3d5be5ba5b8c5f2d6ca6142dab959e2838589062 (patch)
tree739b7a38dac4c59e2b6ac01f5918e89ca17240ca /crates/syntax
parent78de7f0d4a53e92c343b0c12889b423f1f9bd433 (diff)
Fix accidently quadratic syntax rewriter
Switching from SyntaxNode to GreenNode is a costly operation (b/c dereferencing a synax ptr in `with_green` is linear), so we should avoid that.
Diffstat (limited to 'crates/syntax')
-rw-r--r--crates/syntax/src/algo.rs22
1 files changed, 14 insertions, 8 deletions
diff --git a/crates/syntax/src/algo.rs b/crates/syntax/src/algo.rs
index ee89d9867..5696c014f 100644
--- a/crates/syntax/src/algo.rs
+++ b/crates/syntax/src/algo.rs
@@ -476,7 +476,8 @@ impl<'a> SyntaxRewriter<'a> {
476 if self.f.is_none() && self.replacements.is_empty() && self.insertions.is_empty() { 476 if self.f.is_none() && self.replacements.is_empty() && self.insertions.is_empty() {
477 return node.clone(); 477 return node.clone();
478 } 478 }
479 self.rewrite_children(node) 479 let green = self.rewrite_children(node);
480 with_green(node, green)
480 } 481 }
481 482
482 pub fn rewrite_ast<N: AstNode>(self, node: &N) -> N { 483 pub fn rewrite_ast<N: AstNode>(self, node: &N) -> N {
@@ -523,7 +524,7 @@ impl<'a> SyntaxRewriter<'a> {
523 self.insertions.get(pos).map(|insertions| insertions.iter().cloned()) 524 self.insertions.get(pos).map(|insertions| insertions.iter().cloned())
524 } 525 }
525 526
526 fn rewrite_children(&self, node: &SyntaxNode) -> SyntaxNode { 527 fn rewrite_children(&self, node: &SyntaxNode) -> rowan::GreenNode {
527 let _p = profile::span("rewrite_children"); 528 let _p = profile::span("rewrite_children");
528 529
529 // FIXME: this could be made much faster. 530 // FIXME: this could be made much faster.
@@ -534,7 +535,8 @@ impl<'a> SyntaxRewriter<'a> {
534 for child in node.children_with_tokens() { 535 for child in node.children_with_tokens() {
535 self.rewrite_self(&mut new_children, &child); 536 self.rewrite_self(&mut new_children, &child);
536 } 537 }
537 with_children(node, new_children) 538
539 rowan::GreenNode::new(rowan::SyntaxKind(node.kind() as u16), new_children)
538 } 540 }
539 541
540 fn rewrite_self( 542 fn rewrite_self(
@@ -556,7 +558,7 @@ impl<'a> SyntaxRewriter<'a> {
556 match element { 558 match element {
557 NodeOrToken::Token(it) => acc.push(NodeOrToken::Token(it.green().clone())), 559 NodeOrToken::Token(it) => acc.push(NodeOrToken::Token(it.green().clone())),
558 NodeOrToken::Node(it) => { 560 NodeOrToken::Node(it) => {
559 acc.push(NodeOrToken::Node(self.rewrite_children(it).green().clone())); 561 acc.push(NodeOrToken::Node(self.rewrite_children(it)));
560 } 562 }
561 } 563 }
562 } 564 }
@@ -601,14 +603,18 @@ fn with_children(
601) -> SyntaxNode { 603) -> SyntaxNode {
602 let _p = profile::span("with_children"); 604 let _p = profile::span("with_children");
603 605
604 let len = new_children.iter().map(|it| it.text_len()).sum::<TextSize>(); 606 let new_green = rowan::GreenNode::new(rowan::SyntaxKind(parent.kind() as u16), new_children);
605 let new_node = rowan::GreenNode::new(rowan::SyntaxKind(parent.kind() as u16), new_children); 607 with_green(parent, new_green)
606 let new_root_node = parent.replace_with(new_node); 608}
609
610fn with_green(syntax_node: &SyntaxNode, green: rowan::GreenNode) -> SyntaxNode {
611 let len = green.children().map(|it| it.text_len()).sum::<TextSize>();
612 let new_root_node = syntax_node.replace_with(green);
607 let new_root_node = SyntaxNode::new_root(new_root_node); 613 let new_root_node = SyntaxNode::new_root(new_root_node);
608 614
609 // FIXME: use a more elegant way to re-fetch the node (#1185), make 615 // FIXME: use a more elegant way to re-fetch the node (#1185), make
610 // `range` private afterwards 616 // `range` private afterwards
611 let mut ptr = SyntaxNodePtr::new(parent); 617 let mut ptr = SyntaxNodePtr::new(syntax_node);
612 ptr.range = TextRange::at(ptr.range.start(), len); 618 ptr.range = TextRange::at(ptr.range.start(), len);
613 ptr.to_node(&new_root_node) 619 ptr.to_node(&new_root_node)
614} 620}