Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

feat(rome_rowan): implement DoubleEndedIterator for node lists #2672

Merged
merged 10 commits into from
Jun 11, 2022

Conversation

ematipico
Copy link
Contributor

@ematipico ematipico commented Jun 7, 2022

Summary

This PR adds the ability to consume an AstSeparatedList from the back by implementing DoubleEndedIterator.

The reason why I implemented this is because there have been cases where I needed to retrieve the last elements of a list. This will be useful, for example, inside the formatter when implementing the formatting of call arguments.

Checking a separated list from the back adds a bit more of complexity because the last separator is not mandatory, which means that we should handle cases where this is not an error.

In order to achieve that, I had to make the slots peekable, because sometimes we don't want to consume two slots. An example is when we have [1, separator, 3, separator, 5]. We want to consume only 5 in the first iteration, but then we want to consume separator and 3.

I added the unreacheable macro. If we hit that macro, it means that are edge cases we have to handle.

Test Plan

Created new tests to cover the cases:

  • consuming from the back
  • consuming from both ends and make sure that once the iterator is consumed from both ends, None is returned
  • updated all the current tests with a new assertion called assert_rev_elements, we call rev on all vectors (rev needs next_back), so we should cover all the edge cases that were previously handled.

@ematipico ematipico requested a review from a team June 7, 2022 15:51
@ematipico ematipico temporarily deployed to aws June 7, 2022 15:51 Inactive
@cloudflare-pages
Copy link

cloudflare-pages bot commented Jun 7, 2022

Deploying with  Cloudflare Pages  Cloudflare Pages

Latest commit: 4120e45
Status: ✅  Deploy successful!
Preview URL: https://70f0004b.tools-8rn.pages.dev
Branch Preview URL: https://feature-slots-as-double-ende.tools-8rn.pages.dev

View logs

@ematipico ematipico temporarily deployed to aws June 7, 2022 15:55 Inactive
@github-actions
Copy link

github-actions bot commented Jun 7, 2022

@MichaReiser
Copy link
Contributor

!bench_formatter

@ematipico ematipico temporarily deployed to aws June 7, 2022 16:07 Inactive
@github-actions
Copy link

github-actions bot commented Jun 7, 2022

Formatter Benchmark Results

group                                    main                                   pr
-----                                    ----                                   --
formatter/checker.ts                     1.00   376.9±15.80ms     6.9 MB/sec    1.01   379.9±10.10ms     6.8 MB/sec
formatter/compiler.js                    1.00    191.8±8.83ms     5.5 MB/sec    1.01   194.3±12.17ms     5.4 MB/sec
formatter/d3.min.js                      1.05    179.0±8.24ms  1499.8 KB/sec    1.00   170.9±18.73ms  1570.7 KB/sec
formatter/dojo.js                        1.15     11.7±1.20ms     5.9 MB/sec    1.00     10.2±0.26ms     6.7 MB/sec
formatter/ios.d.ts                       1.00   257.4±16.93ms     7.2 MB/sec    1.02    262.4±9.99ms     7.1 MB/sec
formatter/jquery.min.js                  1.00     41.5±1.33ms  2037.5 KB/sec    1.01     42.0±1.15ms  2015.8 KB/sec
formatter/math.js                        1.00   326.5±10.90ms  2030.7 KB/sec    1.08   353.4±29.85ms  1876.1 KB/sec
formatter/parser.ts                      1.02      7.8±0.33ms     6.2 MB/sec    1.00      7.6±0.63ms     6.4 MB/sec
formatter/pixi.min.js                    1.00    194.5±8.86ms     2.3 MB/sec    1.03    201.1±8.15ms     2.2 MB/sec
formatter/react-dom.production.min.js    1.00     46.0±2.02ms     2.5 MB/sec    1.01     46.6±1.00ms     2.5 MB/sec
formatter/react.production.min.js        1.09      2.7±0.27ms     2.3 MB/sec    1.00      2.4±0.08ms     2.5 MB/sec
formatter/router.ts                      1.14      6.0±0.15ms    10.1 MB/sec    1.00      5.3±0.15ms    11.5 MB/sec
formatter/tex-chtml-full.js              1.00   481.3±42.41ms  1939.0 KB/sec    1.07   512.9±15.75ms  1819.5 KB/sec
formatter/three.min.js                   1.00    231.8±6.55ms     2.5 MB/sec    1.01    234.9±9.43ms     2.5 MB/sec
formatter/typescript.js                  1.01  1420.9±72.49ms     6.7 MB/sec    1.00  1412.9±96.98ms     6.7 MB/sec
formatter/vue.global.prod.js             1.03     64.0±6.78ms  1927.7 KB/sec    1.00     62.0±3.99ms  1991.0 KB/sec

@ematipico ematipico temporarily deployed to aws June 7, 2022 16:34 Inactive
@ematipico ematipico temporarily deployed to aws June 7, 2022 20:06 Inactive
@ematipico
Copy link
Contributor Author

!bench_formatter

@github-actions
Copy link

github-actions bot commented Jun 7, 2022

Formatter Benchmark Results

group                                    main                                   pr
-----                                    ----                                   --
formatter/checker.ts                     1.00    287.6±1.16ms     9.0 MB/sec    1.02    293.0±1.28ms     8.9 MB/sec
formatter/compiler.js                    1.01    188.3±0.93ms     5.6 MB/sec    1.00    185.8±1.11ms     5.6 MB/sec
formatter/d3.min.js                      1.01    140.6±0.91ms  1909.1 KB/sec    1.00    139.5±0.97ms  1924.1 KB/sec
formatter/dojo.js                        1.00      9.8±0.01ms     7.0 MB/sec    1.00      9.8±0.02ms     7.0 MB/sec
formatter/ios.d.ts                       1.00    208.7±0.53ms     8.9 MB/sec    1.02    212.8±0.74ms     8.8 MB/sec
formatter/jquery.min.js                  1.00     41.4±0.80ms  2044.1 KB/sec    1.07     44.3±2.52ms  1908.4 KB/sec
formatter/math.js                        1.00    304.0±1.39ms     2.1 MB/sec    1.12    339.6±1.48ms  1952.6 KB/sec
formatter/parser.ts                      1.00      6.5±0.01ms     7.4 MB/sec    1.00      6.5±0.01ms     7.4 MB/sec
formatter/pixi.min.js                    1.01    159.1±0.72ms     2.8 MB/sec    1.00    158.0±0.95ms     2.8 MB/sec
formatter/react-dom.production.min.js    1.01     47.2±1.01ms     2.4 MB/sec    1.00     46.7±0.93ms     2.5 MB/sec
formatter/react.production.min.js        1.00      2.3±0.00ms     2.7 MB/sec    1.13      2.6±0.00ms     2.4 MB/sec
formatter/router.ts                      1.00      5.0±0.00ms    12.1 MB/sec    1.00      5.0±0.00ms    12.1 MB/sec
formatter/tex-chtml-full.js              1.00    409.5±1.03ms     2.2 MB/sec    1.11    456.2±1.38ms  2045.4 KB/sec
formatter/three.min.js                   1.01    187.4±0.82ms     3.1 MB/sec    1.00    186.2±1.74ms     3.2 MB/sec
formatter/typescript.js                  1.00   1148.7±2.74ms     8.3 MB/sec    1.00   1144.7±2.22ms     8.3 MB/sec
formatter/vue.global.prod.js             1.00     61.5±1.10ms  2005.5 KB/sec    1.13     69.7±1.11ms  1771.2 KB/sec

crates/rome_rowan/src/ast/mod.rs Show resolved Hide resolved
crates/rome_rowan/src/ast/mod.rs Outdated Show resolved Hide resolved
crates/rome_rowan/src/ast/mod.rs Outdated Show resolved Hide resolved
crates/rome_rowan/src/ast/mod.rs Outdated Show resolved Hide resolved
crates/rome_rowan/src/ast/mod.rs Outdated Show resolved Hide resolved
crates/rome_rowan/src/ast/mod.rs Outdated Show resolved Hide resolved
crates/rome_rowan/src/ast/mod.rs Outdated Show resolved Hide resolved
@xunilrj
Copy link
Contributor

xunilrj commented Jun 8, 2022

Not sure we are implementing the std::iter::DoubleEndedIterator contract correctly. For example

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8e1cc1b755357cdd5546c3d270335d4d

fn main() {
    let list = vec![1,2,3,4];
    
    let mut iter = list.iter();
    println!("{:?}", iter.next());
    println!("{:?}", iter.next_back());
    
    println!("{:?}", iter.next());
    println!("{:?}", iter.next_back());
    
    println!("{:?}", iter.next());
    println!("{:?}", iter.next_back());
}

outputs

Some(1)
Some(4)
Some(2)
Some(3)
None
None

This happens because:

It is important to note that both back and forth work on the same range, and do not cross: iteration is over when they meet in the middle.
https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html

I tried the following test and failed:

 #[test]
  fn double_iterator_meet_at_middle() {
      let list = build_list(vec![
          (Some(1), Some(",")),
          (Some(2), Some(",")),
          (Some(3), Some(",")),
          (Some(4), None),
      ]);

      let mut iter = list.elements();

      let element = iter.next().unwrap();
      assert_eq!(element.node().unwrap().text(), "1");
      let element = iter.next_back().unwrap();
      assert_eq!(element.node().unwrap().text(), "4");

      let element = iter.next().unwrap();
      assert_eq!(element.node().unwrap().text(), "2");
      let element = iter.next_back().unwrap();
      assert_eq!(element.node().unwrap().text(), "3");

      assert!(iter.next().is_none());  // line 701
      assert!(iter.next_back().is_none());
  }

and failed with:

---- ast::tests::double_iterator_meet_at_middle stdout ----
thread 'ast::tests::double_iterator_meet_at_middle' panicked at 'assertion failed: iter.next().is_none()', crates\rome_rowan\src\ast\mod.rs:701:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

@ematipico
Copy link
Contributor Author

It is important to note that both back and forth work on the same range, and do not cross: iteration is over when they meet in the middle.
doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html

Damn I missed that part! Thank you for looking into this!

@ematipico ematipico temporarily deployed to aws June 8, 2022 19:37 Inactive
@github-actions
Copy link

github-actions bot commented Jun 8, 2022

Parser conformance results on ubuntu-latest

js/262

Test result main count This PR count Difference
Total 45878 45878 0
Passed 44938 44938 0
Failed 940 940 0
Panics 0 0 0
Coverage 97.95% 97.95% 0.00%

jsx/babel

Test result main count This PR count Difference
Total 39 39 0
Passed 36 36 0
Failed 3 3 0
Panics 0 0 0
Coverage 92.31% 92.31% 0.00%

symbols/microsoft

Test result main count This PR count Difference
Total 5946 5946 0
Passed 350 350 0
Failed 5596 5596 0
Panics 0 0 0
Coverage 5.89% 5.89% 0.00%

ts/babel

Test result main count This PR count Difference
Total 588 588 0
Passed 519 519 0
Failed 69 69 0
Panics 0 0 0
Coverage 88.27% 88.27% 0.00%

ts/microsoft

Test result main count This PR count Difference
Total 16257 16257 0
Passed 12391 12391 0
Failed 3866 3866 0
Panics 0 0 0
Coverage 76.22% 76.22% 0.00%

@ematipico ematipico temporarily deployed to aws June 8, 2022 19:47 Inactive
@ematipico ematipico requested a review from xunilrj June 8, 2022 19:47
@ematipico
Copy link
Contributor Author

Please re-read the description, there's more context now

Copy link
Contributor

@MichaReiser MichaReiser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good. I'm a bit surprised by the amount of special case handling that is necessary and are wondering if we can simplify that a bit. But you will know better because you looked into all edge cases

crates/rome_rowan/src/ast/mod.rs Outdated Show resolved Hide resolved
crates/rome_rowan/src/ast/mod.rs Outdated Show resolved Hide resolved
crates/rome_rowan/src/ast/mod.rs Outdated Show resolved Hide resolved
crates/rome_rowan/src/ast/mod.rs Show resolved Hide resolved
crates/rome_rowan/src/ast/mod.rs Outdated Show resolved Hide resolved
crates/rome_rowan/src/cursor/node.rs Show resolved Hide resolved
@ematipico ematipico temporarily deployed to aws June 9, 2022 12:39 Inactive
@ematipico ematipico force-pushed the feature/slots-as-double-ended-iterators branch from 3c17eb7 to 2339019 Compare June 9, 2022 12:49
@ematipico ematipico temporarily deployed to aws June 9, 2022 12:49 Inactive
@ematipico ematipico force-pushed the feature/slots-as-double-ended-iterators branch from 78ab67c to a9d1923 Compare June 10, 2022 18:00
@ematipico ematipico temporarily deployed to aws June 10, 2022 18:00 Inactive
@ematipico
Copy link
Contributor Author

@MichaReiser I addressed your concerns, your help was really helpful, thank you! Now the code should be clear and better to read. I believe we are ready to ship it!

@ematipico ematipico force-pushed the feature/slots-as-double-ended-iterators branch from a9d1923 to 4120e45 Compare June 10, 2022 18:03
@ematipico ematipico temporarily deployed to aws June 10, 2022 18:03 Inactive
Copy link
Contributor

@MichaReiser MichaReiser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

@ematipico ematipico merged commit cb809b8 into main Jun 11, 2022
@ematipico ematipico deleted the feature/slots-as-double-ended-iterators branch June 11, 2022 20:16
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants