aboutsummaryrefslogtreecommitdiff
path: root/crates/syntax
diff options
context:
space:
mode:
Diffstat (limited to 'crates/syntax')
-rw-r--r--crates/syntax/src/algo.rs165
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0153_pub_parens_typepath.rast54
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0153_pub_parens_typepath.rs2
3 files changed, 197 insertions, 24 deletions
diff --git a/crates/syntax/src/algo.rs b/crates/syntax/src/algo.rs
index 4f9a7a6e8..065035fe6 100644
--- a/crates/syntax/src/algo.rs
+++ b/crates/syntax/src/algo.rs
@@ -289,11 +289,19 @@ fn _replace_children(
289 with_children(parent, new_children) 289 with_children(parent, new_children)
290} 290}
291 291
292#[derive(Debug, PartialEq, Eq, Hash)]
293enum InsertPos {
294 FirstChildOf(SyntaxNode),
295 // Before(SyntaxElement),
296 After(SyntaxElement),
297}
298
292#[derive(Default)] 299#[derive(Default)]
293pub struct SyntaxRewriter<'a> { 300pub struct SyntaxRewriter<'a> {
294 f: Option<Box<dyn Fn(&SyntaxElement) -> Option<SyntaxElement> + 'a>>, 301 f: Option<Box<dyn Fn(&SyntaxElement) -> Option<SyntaxElement> + 'a>>,
295 //FIXME: add debug_assertions that all elements are in fact from the same file. 302 //FIXME: add debug_assertions that all elements are in fact from the same file.
296 replacements: FxHashMap<SyntaxElement, Replacement>, 303 replacements: FxHashMap<SyntaxElement, Replacement>,
304 insertions: IndexMap<InsertPos, Vec<SyntaxElement>>,
297} 305}
298 306
299impl fmt::Debug for SyntaxRewriter<'_> { 307impl fmt::Debug for SyntaxRewriter<'_> {
@@ -304,13 +312,96 @@ impl fmt::Debug for SyntaxRewriter<'_> {
304 312
305impl<'a> SyntaxRewriter<'a> { 313impl<'a> SyntaxRewriter<'a> {
306 pub fn from_fn(f: impl Fn(&SyntaxElement) -> Option<SyntaxElement> + 'a) -> SyntaxRewriter<'a> { 314 pub fn from_fn(f: impl Fn(&SyntaxElement) -> Option<SyntaxElement> + 'a) -> SyntaxRewriter<'a> {
307 SyntaxRewriter { f: Some(Box::new(f)), replacements: FxHashMap::default() } 315 SyntaxRewriter {
316 f: Some(Box::new(f)),
317 replacements: FxHashMap::default(),
318 insertions: IndexMap::default(),
319 }
308 } 320 }
309 pub fn delete<T: Clone + Into<SyntaxElement>>(&mut self, what: &T) { 321 pub fn delete<T: Clone + Into<SyntaxElement>>(&mut self, what: &T) {
310 let what = what.clone().into(); 322 let what = what.clone().into();
311 let replacement = Replacement::Delete; 323 let replacement = Replacement::Delete;
312 self.replacements.insert(what, replacement); 324 self.replacements.insert(what, replacement);
313 } 325 }
326 pub fn insert_before<T: Clone + Into<SyntaxElement>, U: Clone + Into<SyntaxElement>>(
327 &mut self,
328 before: &T,
329 what: &U,
330 ) {
331 let before = before.clone().into();
332 let pos = match before.prev_sibling_or_token() {
333 Some(sibling) => InsertPos::After(sibling),
334 None => match before.parent() {
335 Some(parent) => InsertPos::FirstChildOf(parent),
336 None => return,
337 },
338 };
339 self.insertions.entry(pos).or_insert_with(Vec::new).push(what.clone().into());
340 }
341 pub fn insert_after<T: Clone + Into<SyntaxElement>, U: Clone + Into<SyntaxElement>>(
342 &mut self,
343 after: &T,
344 what: &U,
345 ) {
346 self.insertions
347 .entry(InsertPos::After(after.clone().into()))
348 .or_insert_with(Vec::new)
349 .push(what.clone().into());
350 }
351 pub fn insert_as_first_child<T: Clone + Into<SyntaxNode>, U: Clone + Into<SyntaxElement>>(
352 &mut self,
353 parent: &T,
354 what: &U,
355 ) {
356 self.insertions
357 .entry(InsertPos::FirstChildOf(parent.clone().into()))
358 .or_insert_with(Vec::new)
359 .push(what.clone().into());
360 }
361 pub fn insert_many_before<
362 T: Clone + Into<SyntaxElement>,
363 U: IntoIterator<Item = SyntaxElement>,
364 >(
365 &mut self,
366 before: &T,
367 what: U,
368 ) {
369 let before = before.clone().into();
370 let pos = match before.prev_sibling_or_token() {
371 Some(sibling) => InsertPos::After(sibling),
372 None => match before.parent() {
373 Some(parent) => InsertPos::FirstChildOf(parent),
374 None => return,
375 },
376 };
377 self.insertions.entry(pos).or_insert_with(Vec::new).extend(what);
378 }
379 pub fn insert_many_after<
380 T: Clone + Into<SyntaxElement>,
381 U: IntoIterator<Item = SyntaxElement>,
382 >(
383 &mut self,
384 after: &T,
385 what: U,
386 ) {
387 self.insertions
388 .entry(InsertPos::After(after.clone().into()))
389 .or_insert_with(Vec::new)
390 .extend(what);
391 }
392 pub fn insert_many_as_first_children<
393 T: Clone + Into<SyntaxNode>,
394 U: IntoIterator<Item = SyntaxElement>,
395 >(
396 &mut self,
397 parent: &T,
398 what: U,
399 ) {
400 self.insertions
401 .entry(InsertPos::FirstChildOf(parent.clone().into()))
402 .or_insert_with(Vec::new)
403 .extend(what)
404 }
314 pub fn replace<T: Clone + Into<SyntaxElement>>(&mut self, what: &T, with: &T) { 405 pub fn replace<T: Clone + Into<SyntaxElement>>(&mut self, what: &T, with: &T) {
315 let what = what.clone().into(); 406 let what = what.clone().into();
316 let replacement = Replacement::Single(with.clone().into()); 407 let replacement = Replacement::Single(with.clone().into());
@@ -330,7 +421,7 @@ impl<'a> SyntaxRewriter<'a> {
330 } 421 }
331 422
332 pub fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode { 423 pub fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode {
333 if self.f.is_none() && self.replacements.is_empty() { 424 if self.f.is_none() && self.replacements.is_empty() && self.insertions.is_empty() {
334 return node.clone(); 425 return node.clone();
335 } 426 }
336 self.rewrite_children(node) 427 self.rewrite_children(node)
@@ -346,14 +437,22 @@ impl<'a> SyntaxRewriter<'a> {
346 /// 437 ///
347 /// Returns `None` when there are no replacements. 438 /// Returns `None` when there are no replacements.
348 pub fn rewrite_root(&self) -> Option<SyntaxNode> { 439 pub fn rewrite_root(&self) -> Option<SyntaxNode> {
440 fn element_to_node_or_parent(element: &SyntaxElement) -> SyntaxNode {
441 match element {
442 SyntaxElement::Node(it) => it.clone(),
443 SyntaxElement::Token(it) => it.parent(),
444 }
445 }
446
349 assert!(self.f.is_none()); 447 assert!(self.f.is_none());
350 self.replacements 448 self.replacements
351 .keys() 449 .keys()
352 .map(|element| match element { 450 .map(element_to_node_or_parent)
353 SyntaxElement::Node(it) => it.clone(), 451 .chain(self.insertions.keys().map(|pos| match pos {
354 SyntaxElement::Token(it) => it.parent(), 452 InsertPos::FirstChildOf(it) => it.clone(),
355 }) 453 InsertPos::After(it) => element_to_node_or_parent(it),
356 // If we only have one replacement, we must return its parent node, since `rewrite` does 454 }))
455 // If we only have one replacement/insertion, we must return its parent node, since `rewrite` does
357 // not replace the node passed to it. 456 // not replace the node passed to it.
358 .map(|it| it.parent().unwrap_or(it)) 457 .map(|it| it.parent().unwrap_or(it))
359 .fold1(|a, b| least_common_ancestor(&a, &b).unwrap()) 458 .fold1(|a, b| least_common_ancestor(&a, &b).unwrap())
@@ -367,9 +466,16 @@ impl<'a> SyntaxRewriter<'a> {
367 self.replacements.get(element).cloned() 466 self.replacements.get(element).cloned()
368 } 467 }
369 468
469 fn insertions(&self, pos: &InsertPos) -> Option<impl Iterator<Item = SyntaxElement> + '_> {
470 self.insertions.get(pos).map(|insertions| insertions.iter().cloned())
471 }
472
370 fn rewrite_children(&self, node: &SyntaxNode) -> SyntaxNode { 473 fn rewrite_children(&self, node: &SyntaxNode) -> SyntaxNode {
371 // FIXME: this could be made much faster. 474 // FIXME: this could be made much faster.
372 let mut new_children = Vec::new(); 475 let mut new_children = Vec::new();
476 if let Some(elements) = self.insertions(&InsertPos::FirstChildOf(node.clone())) {
477 new_children.extend(elements.map(element_to_green));
478 }
373 for child in node.children_with_tokens() { 479 for child in node.children_with_tokens() {
374 self.rewrite_self(&mut new_children, &child); 480 self.rewrite_self(&mut new_children, &child);
375 } 481 }
@@ -383,34 +489,45 @@ impl<'a> SyntaxRewriter<'a> {
383 ) { 489 ) {
384 if let Some(replacement) = self.replacement(&element) { 490 if let Some(replacement) = self.replacement(&element) {
385 match replacement { 491 match replacement {
386 Replacement::Single(NodeOrToken::Node(it)) => { 492 Replacement::Single(element) => acc.push(element_to_green(element)),
387 acc.push(NodeOrToken::Node(it.green().clone()))
388 }
389 Replacement::Single(NodeOrToken::Token(it)) => {
390 acc.push(NodeOrToken::Token(it.green().clone()))
391 }
392 Replacement::Many(replacements) => { 493 Replacement::Many(replacements) => {
393 acc.extend(replacements.iter().map(|it| match it { 494 acc.extend(replacements.into_iter().map(element_to_green))
394 NodeOrToken::Node(it) => NodeOrToken::Node(it.green().clone()),
395 NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()),
396 }))
397 } 495 }
398 Replacement::Delete => (), 496 Replacement::Delete => (),
399 }; 497 };
400 return; 498 } else {
499 match element {
500 NodeOrToken::Token(it) => acc.push(NodeOrToken::Token(it.green().clone())),
501 NodeOrToken::Node(it) => {
502 acc.push(NodeOrToken::Node(self.rewrite_children(it).green().clone()));
503 }
504 }
505 }
506 if let Some(elements) = self.insertions(&InsertPos::After(element.clone())) {
507 acc.extend(elements.map(element_to_green));
401 } 508 }
402 let res = match element { 509 }
403 NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()), 510}
404 NodeOrToken::Node(it) => NodeOrToken::Node(self.rewrite_children(it).green().clone()), 511
405 }; 512fn element_to_green(element: SyntaxElement) -> NodeOrToken<rowan::GreenNode, rowan::GreenToken> {
406 acc.push(res) 513 match element {
514 NodeOrToken::Node(it) => NodeOrToken::Node(it.green().clone()),
515 NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()),
407 } 516 }
408} 517}
409 518
410impl ops::AddAssign for SyntaxRewriter<'_> { 519impl ops::AddAssign for SyntaxRewriter<'_> {
411 fn add_assign(&mut self, rhs: SyntaxRewriter) { 520 fn add_assign(&mut self, rhs: SyntaxRewriter) {
412 assert!(rhs.f.is_none()); 521 assert!(rhs.f.is_none());
413 self.replacements.extend(rhs.replacements) 522 self.replacements.extend(rhs.replacements);
523 for (pos, insertions) in rhs.insertions.into_iter() {
524 match self.insertions.entry(pos) {
525 indexmap::map::Entry::Occupied(mut occupied) => {
526 occupied.get_mut().extend(insertions)
527 }
528 indexmap::map::Entry::Vacant(vacant) => drop(vacant.insert(insertions)),
529 }
530 }
414 } 531 }
415} 532}
416 533
diff --git a/crates/syntax/test_data/parser/inline/ok/0153_pub_parens_typepath.rast b/crates/syntax/test_data/parser/inline/ok/0153_pub_parens_typepath.rast
new file mode 100644
index 000000000..c204f0e2d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0153_pub_parens_typepath.rast
@@ -0,0 +1,54 @@
1[email protected]
2 [email protected]
3 [email protected] "struct"
4 [email protected] " "
5 [email protected]
6 [email protected] "B"
7 [email protected]
8 [email protected] "("
9 [email protected]
10 [email protected]
11 [email protected] "pub"
12 [email protected] " "
13 [email protected]
14 [email protected] "("
15 [email protected]
16 [email protected]
17 [email protected]
18 [email protected]
19 [email protected] "super"
20 [email protected] "::"
21 [email protected]
22 [email protected]
23 [email protected] "A"
24 [email protected] ")"
25 [email protected] ")"
26 [email protected] ";"
27 [email protected] "\n"
28 [email protected]
29 [email protected] "struct"
30 [email protected] " "
31 [email protected]
32 [email protected] "B"
33 [email protected]
34 [email protected] "("
35 [email protected]
36 [email protected]
37 [email protected] "pub"
38 [email protected] " "
39 [email protected]
40 [email protected] "("
41 [email protected]
42 [email protected]
43 [email protected]
44 [email protected]
45 [email protected] "crate"
46 [email protected] "::"
47 [email protected]
48 [email protected]
49 [email protected] "A"
50 [email protected] ","
51 [email protected] ")"
52 [email protected] ")"
53 [email protected] ";"
54 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0153_pub_parens_typepath.rs b/crates/syntax/test_data/parser/inline/ok/0153_pub_parens_typepath.rs
new file mode 100644
index 000000000..d4c163822
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0153_pub_parens_typepath.rs
@@ -0,0 +1,2 @@
1struct B(pub (super::A));
2struct B(pub (crate::A,));