diff options
author | Aleksey Kladov <[email protected]> | 2020-12-10 17:07:37 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-12-10 17:07:37 +0000 |
commit | 3d5be5ba5b8c5f2d6ca6142dab959e2838589062 (patch) | |
tree | 739b7a38dac4c59e2b6ac01f5918e89ca17240ca /crates | |
parent | 78de7f0d4a53e92c343b0c12889b423f1f9bd433 (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')
-rw-r--r-- | crates/syntax/src/algo.rs | 22 |
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 | |||
610 | fn 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 | } |