diff options
Diffstat (limited to 'crates/syntax/src')
-rw-r--r-- | crates/syntax/src/algo.rs | 13 | ||||
-rw-r--r-- | crates/syntax/src/ast/token_ext.rs | 27 |
2 files changed, 31 insertions, 9 deletions
diff --git a/crates/syntax/src/algo.rs b/crates/syntax/src/algo.rs index 320c430c9..ee89d9867 100644 --- a/crates/syntax/src/algo.rs +++ b/crates/syntax/src/algo.rs | |||
@@ -127,6 +127,8 @@ pub struct TreeDiff { | |||
127 | 127 | ||
128 | impl TreeDiff { | 128 | impl TreeDiff { |
129 | pub fn into_text_edit(&self, builder: &mut TextEditBuilder) { | 129 | pub fn into_text_edit(&self, builder: &mut TextEditBuilder) { |
130 | let _p = profile::span("into_text_edit"); | ||
131 | |||
130 | for (anchor, to) in self.insertions.iter() { | 132 | for (anchor, to) in self.insertions.iter() { |
131 | let offset = match anchor { | 133 | let offset = match anchor { |
132 | TreeDiffInsertPos::After(it) => it.text_range().end(), | 134 | TreeDiffInsertPos::After(it) => it.text_range().end(), |
@@ -154,6 +156,8 @@ impl TreeDiff { | |||
154 | /// | 156 | /// |
155 | /// This function tries to find a fine-grained diff. | 157 | /// This function tries to find a fine-grained diff. |
156 | pub fn diff(from: &SyntaxNode, to: &SyntaxNode) -> TreeDiff { | 158 | pub fn diff(from: &SyntaxNode, to: &SyntaxNode) -> TreeDiff { |
159 | let _p = profile::span("diff"); | ||
160 | |||
157 | let mut diff = TreeDiff { | 161 | let mut diff = TreeDiff { |
158 | replacements: FxHashMap::default(), | 162 | replacements: FxHashMap::default(), |
159 | insertions: FxIndexMap::default(), | 163 | insertions: FxIndexMap::default(), |
@@ -467,6 +471,8 @@ impl<'a> SyntaxRewriter<'a> { | |||
467 | } | 471 | } |
468 | 472 | ||
469 | pub fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode { | 473 | pub fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode { |
474 | let _p = profile::span("rewrite"); | ||
475 | |||
470 | 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() { |
471 | return node.clone(); | 477 | return node.clone(); |
472 | } | 478 | } |
@@ -483,6 +489,7 @@ impl<'a> SyntaxRewriter<'a> { | |||
483 | /// | 489 | /// |
484 | /// Returns `None` when there are no replacements. | 490 | /// Returns `None` when there are no replacements. |
485 | pub fn rewrite_root(&self) -> Option<SyntaxNode> { | 491 | pub fn rewrite_root(&self) -> Option<SyntaxNode> { |
492 | let _p = profile::span("rewrite_root"); | ||
486 | fn element_to_node_or_parent(element: &SyntaxElement) -> SyntaxNode { | 493 | fn element_to_node_or_parent(element: &SyntaxElement) -> SyntaxNode { |
487 | match element { | 494 | match element { |
488 | SyntaxElement::Node(it) => it.clone(), | 495 | SyntaxElement::Node(it) => it.clone(), |
@@ -517,6 +524,8 @@ impl<'a> SyntaxRewriter<'a> { | |||
517 | } | 524 | } |
518 | 525 | ||
519 | fn rewrite_children(&self, node: &SyntaxNode) -> SyntaxNode { | 526 | fn rewrite_children(&self, node: &SyntaxNode) -> SyntaxNode { |
527 | let _p = profile::span("rewrite_children"); | ||
528 | |||
520 | // FIXME: this could be made much faster. | 529 | // FIXME: this could be made much faster. |
521 | let mut new_children = Vec::new(); | 530 | let mut new_children = Vec::new(); |
522 | if let Some(elements) = self.insertions(&InsertPos::FirstChildOf(node.clone())) { | 531 | if let Some(elements) = self.insertions(&InsertPos::FirstChildOf(node.clone())) { |
@@ -533,6 +542,8 @@ impl<'a> SyntaxRewriter<'a> { | |||
533 | acc: &mut Vec<NodeOrToken<rowan::GreenNode, rowan::GreenToken>>, | 542 | acc: &mut Vec<NodeOrToken<rowan::GreenNode, rowan::GreenToken>>, |
534 | element: &SyntaxElement, | 543 | element: &SyntaxElement, |
535 | ) { | 544 | ) { |
545 | let _p = profile::span("rewrite_self"); | ||
546 | |||
536 | if let Some(replacement) = self.replacement(&element) { | 547 | if let Some(replacement) = self.replacement(&element) { |
537 | match replacement { | 548 | match replacement { |
538 | Replacement::Single(element) => acc.push(element_to_green(element)), | 549 | Replacement::Single(element) => acc.push(element_to_green(element)), |
@@ -588,6 +599,8 @@ fn with_children( | |||
588 | parent: &SyntaxNode, | 599 | parent: &SyntaxNode, |
589 | new_children: Vec<NodeOrToken<rowan::GreenNode, rowan::GreenToken>>, | 600 | new_children: Vec<NodeOrToken<rowan::GreenNode, rowan::GreenToken>>, |
590 | ) -> SyntaxNode { | 601 | ) -> SyntaxNode { |
602 | let _p = profile::span("with_children"); | ||
603 | |||
591 | let len = new_children.iter().map(|it| it.text_len()).sum::<TextSize>(); | 604 | let len = new_children.iter().map(|it| it.text_len()).sum::<TextSize>(); |
592 | let new_node = 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); |
593 | let new_root_node = parent.replace_with(new_node); | 606 | let new_root_node = parent.replace_with(new_node); |
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs index ac0326420..b985861f2 100644 --- a/crates/syntax/src/ast/token_ext.rs +++ b/crates/syntax/src/ast/token_ext.rs | |||
@@ -130,19 +130,28 @@ impl ast::String { | |||
130 | let text = self.text().as_str(); | 130 | let text = self.text().as_str(); |
131 | let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()]; | 131 | let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()]; |
132 | 132 | ||
133 | let mut buf = String::with_capacity(text.len()); | 133 | let mut buf = String::new(); |
134 | let mut text_iter = text.chars(); | ||
134 | let mut has_error = false; | 135 | let mut has_error = false; |
135 | unescape_literal(text, Mode::Str, &mut |_, unescaped_char| match unescaped_char { | 136 | unescape_literal(text, Mode::Str, &mut |char_range, unescaped_char| match ( |
136 | Ok(c) => buf.push(c), | 137 | unescaped_char, |
137 | Err(_) => has_error = true, | 138 | buf.capacity() == 0, |
139 | ) { | ||
140 | (Ok(c), false) => buf.push(c), | ||
141 | (Ok(c), true) if Some(c) == text_iter.next() => (), | ||
142 | (Ok(c), true) => { | ||
143 | buf.reserve_exact(text.len()); | ||
144 | buf.push_str(&text[..char_range.start]); | ||
145 | buf.push(c); | ||
146 | } | ||
147 | (Err(_), _) => has_error = true, | ||
138 | }); | 148 | }); |
139 | 149 | ||
140 | if has_error { | 150 | match (has_error, buf.capacity() == 0) { |
141 | return None; | 151 | (true, _) => None, |
152 | (false, true) => Some(Cow::Borrowed(text)), | ||
153 | (false, false) => Some(Cow::Owned(buf)), | ||
142 | } | 154 | } |
143 | // FIXME: don't actually allocate for borrowed case | ||
144 | let res = if buf == text { Cow::Borrowed(text) } else { Cow::Owned(buf) }; | ||
145 | Some(res) | ||
146 | } | 155 | } |
147 | 156 | ||
148 | pub fn quote_offsets(&self) -> Option<QuoteOffsets> { | 157 | pub fn quote_offsets(&self) -> Option<QuoteOffsets> { |