diff options
Diffstat (limited to 'crates/syntax/src')
-rw-r--r-- | crates/syntax/src/algo.rs | 35 | ||||
-rw-r--r-- | crates/syntax/src/ast.rs | 6 | ||||
-rw-r--r-- | crates/syntax/src/ast/make.rs | 10 |
3 files changed, 12 insertions, 39 deletions
diff --git a/crates/syntax/src/algo.rs b/crates/syntax/src/algo.rs index 3f9b84ab9..825ea3185 100644 --- a/crates/syntax/src/algo.rs +++ b/crates/syntax/src/algo.rs | |||
@@ -337,7 +337,7 @@ enum InsertPos { | |||
337 | } | 337 | } |
338 | 338 | ||
339 | #[derive(Default)] | 339 | #[derive(Default)] |
340 | pub struct SyntaxRewriter<'a> { | 340 | pub(crate) struct SyntaxRewriter<'a> { |
341 | //FIXME: add debug_assertions that all elements are in fact from the same file. | 341 | //FIXME: add debug_assertions that all elements are in fact from the same file. |
342 | replacements: FxHashMap<SyntaxElement, Replacement>, | 342 | replacements: FxHashMap<SyntaxElement, Replacement>, |
343 | insertions: IndexMap<InsertPos, Vec<SyntaxElement>>, | 343 | insertions: IndexMap<InsertPos, Vec<SyntaxElement>>, |
@@ -354,13 +354,13 @@ impl fmt::Debug for SyntaxRewriter<'_> { | |||
354 | } | 354 | } |
355 | 355 | ||
356 | impl SyntaxRewriter<'_> { | 356 | impl SyntaxRewriter<'_> { |
357 | pub fn replace<T: Clone + Into<SyntaxElement>>(&mut self, what: &T, with: &T) { | 357 | pub(crate) fn replace<T: Clone + Into<SyntaxElement>>(&mut self, what: &T, with: &T) { |
358 | let what = what.clone().into(); | 358 | let what = what.clone().into(); |
359 | let replacement = Replacement::Single(with.clone().into()); | 359 | let replacement = Replacement::Single(with.clone().into()); |
360 | self.replacements.insert(what, replacement); | 360 | self.replacements.insert(what, replacement); |
361 | } | 361 | } |
362 | 362 | ||
363 | pub fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode { | 363 | pub(crate) fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode { |
364 | let _p = profile::span("rewrite"); | 364 | let _p = profile::span("rewrite"); |
365 | 365 | ||
366 | if self.replacements.is_empty() && self.insertions.is_empty() { | 366 | if self.replacements.is_empty() && self.insertions.is_empty() { |
@@ -370,37 +370,10 @@ impl SyntaxRewriter<'_> { | |||
370 | with_green(node, green) | 370 | with_green(node, green) |
371 | } | 371 | } |
372 | 372 | ||
373 | pub fn rewrite_ast<N: AstNode>(self, node: &N) -> N { | 373 | pub(crate) fn rewrite_ast<N: AstNode>(self, node: &N) -> N { |
374 | N::cast(self.rewrite(node.syntax())).unwrap() | 374 | N::cast(self.rewrite(node.syntax())).unwrap() |
375 | } | 375 | } |
376 | 376 | ||
377 | /// Returns a node that encompasses all replacements to be done by this rewriter. | ||
378 | /// | ||
379 | /// Passing the returned node to `rewrite` will apply all replacements queued up in `self`. | ||
380 | /// | ||
381 | /// Returns `None` when there are no replacements. | ||
382 | pub fn rewrite_root(&self) -> Option<SyntaxNode> { | ||
383 | let _p = profile::span("rewrite_root"); | ||
384 | fn element_to_node_or_parent(element: &SyntaxElement) -> Option<SyntaxNode> { | ||
385 | match element { | ||
386 | SyntaxElement::Node(it) => Some(it.clone()), | ||
387 | SyntaxElement::Token(it) => it.parent(), | ||
388 | } | ||
389 | } | ||
390 | |||
391 | self.replacements | ||
392 | .keys() | ||
393 | .filter_map(element_to_node_or_parent) | ||
394 | .chain(self.insertions.keys().filter_map(|pos| match pos { | ||
395 | InsertPos::FirstChildOf(it) => Some(it.clone()), | ||
396 | InsertPos::After(it) => element_to_node_or_parent(it), | ||
397 | })) | ||
398 | // If we only have one replacement/insertion, we must return its parent node, since `rewrite` does | ||
399 | // not replace the node passed to it. | ||
400 | .map(|it| it.parent().unwrap_or(it)) | ||
401 | .fold1(|a, b| least_common_ancestor(&a, &b).unwrap()) | ||
402 | } | ||
403 | |||
404 | fn replacement(&self, element: &SyntaxElement) -> Option<Replacement> { | 377 | fn replacement(&self, element: &SyntaxElement) -> Option<Replacement> { |
405 | self.replacements.get(element).cloned() | 378 | self.replacements.get(element).cloned() |
406 | } | 379 | } |
diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs index 7f472d4db..a8071b51d 100644 --- a/crates/syntax/src/ast.rs +++ b/crates/syntax/src/ast.rs | |||
@@ -47,6 +47,12 @@ pub trait AstNode { | |||
47 | { | 47 | { |
48 | Self::cast(self.syntax().clone_for_update()).unwrap() | 48 | Self::cast(self.syntax().clone_for_update()).unwrap() |
49 | } | 49 | } |
50 | fn clone_subtree(&self) -> Self | ||
51 | where | ||
52 | Self: Sized, | ||
53 | { | ||
54 | Self::cast(self.syntax().clone_subtree()).unwrap() | ||
55 | } | ||
50 | } | 56 | } |
51 | 57 | ||
52 | /// Like `AstNode`, but wraps tokens rather than interior nodes. | 58 | /// Like `AstNode`, but wraps tokens rather than interior nodes. |
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 1998ad1f6..de04c8620 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs | |||
@@ -12,7 +12,7 @@ | |||
12 | use itertools::Itertools; | 12 | use itertools::Itertools; |
13 | use stdx::{format_to, never}; | 13 | use stdx::{format_to, never}; |
14 | 14 | ||
15 | use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken}; | 15 | use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxToken}; |
16 | 16 | ||
17 | /// While the parent module defines basic atomic "constructors", the `ext` | 17 | /// While the parent module defines basic atomic "constructors", the `ext` |
18 | /// module defines shortcuts for common things. | 18 | /// module defines shortcuts for common things. |
@@ -601,17 +601,11 @@ fn ast_from_text<N: AstNode>(text: &str) -> N { | |||
601 | panic!("Failed to make ast node `{}` from text {}", std::any::type_name::<N>(), text) | 601 | panic!("Failed to make ast node `{}` from text {}", std::any::type_name::<N>(), text) |
602 | } | 602 | } |
603 | }; | 603 | }; |
604 | let node = node.syntax().clone(); | 604 | let node = node.clone_subtree(); |
605 | let node = unroot(node); | ||
606 | let node = N::cast(node).unwrap(); | ||
607 | assert_eq!(node.syntax().text_range().start(), 0.into()); | 605 | assert_eq!(node.syntax().text_range().start(), 0.into()); |
608 | node | 606 | node |
609 | } | 607 | } |
610 | 608 | ||
611 | fn unroot(n: SyntaxNode) -> SyntaxNode { | ||
612 | SyntaxNode::new_root(n.green().into()) | ||
613 | } | ||
614 | |||
615 | pub fn token(kind: SyntaxKind) -> SyntaxToken { | 609 | pub fn token(kind: SyntaxKind) -> SyntaxToken { |
616 | tokens::SOURCE_FILE | 610 | tokens::SOURCE_FILE |
617 | .tree() | 611 | .tree() |