Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve selectors, fix complex selector parsing issues #58

Merged

Conversation

flavorjones
Copy link
Collaborator

@flavorjones flavorjones commented May 25, 2024

Dipping my toes into contributing with this first PR, focused on improving selectors for potential use in Nokogiri.

  • create Node classes for Combinator, CompoundSelector, and ComplexSelector
  • add some ad-hoc test coverage for selectors
  • fix .a + .b {} and .a > .b don't work #25 describing selector parsing issues
  • flatten the Complex Selector AST
  • introduce some basic selector formatting (incomplete, can finish in a future PR)

I'd love feedback on whether I'm properly following any conventions you want followed.

Comment on lines 131 to 143
assert_pattern do
actual => [
Selectors::ComplexSelector[
left: Selectors::TypeSelector[value: { name: { value: "section" } }],
combinator: { value: { value: ">" } },
right: Selectors::ComplexSelector[
left: Selectors::TypeSelector[value: { name: { value: "table" } }],
combinator: nil,
right: Selectors::TypeSelector[value: { name: { value: "tr" } }]
]
]
]
end
Copy link
Collaborator Author

@flavorjones flavorjones May 26, 2024

Choose a reason for hiding this comment

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

After sleeping on it, I don't like this recursive structure. The spec defines a complex-selector as:

<complex-selector> = <compound-selector> [ <combinator>? <compound-selector> ]*

which would imply a preferred AST like:

          assert_pattern do
            actual => [
              Selectors::ComplexSelector[
                child_nodes: [
                  Selectors::TypeSelector[value: { name: { value: "section" } }],
                  Selectors::Combinator[value: { value: ">" }],
                  Selectors::TypeSelector[value: { name: { value: "table" } }],
                  Selectors::TypeSelector[value: { name: { value: "tr" } }]
                ]
              ]
            ]
          end

I'd like to change this, either in this PR or in the next one. @kddnewton thoughts?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I've got a commit the converts to this flattened AST ... let me know what you want to do!

Copy link
Member

Choose a reason for hiding this comment

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

Flatter is better for sure

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

OK, pushed a commit that flattens this AST, LMK what you think.

@flavorjones
Copy link
Collaborator Author

@kddnewton I know there's a lot of code here -- let me know if it needs explanation. The tests drove out all the changes I made, if that's helpful information.

end

# <relative-selector> = <combinator>? <complex-selector>
def relative_selector
combinator = maybe { combinator }
c = maybe { combinator }

if combinator
Copy link
Member

Choose a reason for hiding this comment

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

I think I'm not understanding this line. combinator here is changing from a local variable read to a method call. Is that intentional?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

As originally written, the outer variable combinator clobbers the method combinator and so the variable is always nil.

For example:

#! /usr/bin/env ruby

def foo
  42
end

def bar(&block)
  yield
end

foo = bar { foo }

foo
# => nil

I'm happy to fix it some other way, this was just the simplest I came up with at the time.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sorry - I missed a replacement of combinator with c on the next line, will fix it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Pushed a complete changeset, let me know if it needs explanation.

Comment on lines 131 to 143
assert_pattern do
actual => [
Selectors::ComplexSelector[
left: Selectors::TypeSelector[value: { name: { value: "section" } }],
combinator: { value: { value: ">" } },
right: Selectors::ComplexSelector[
left: Selectors::TypeSelector[value: { name: { value: "table" } }],
combinator: nil,
right: Selectors::TypeSelector[value: { name: { value: "tr" } }]
]
]
]
end
Copy link
Member

Choose a reason for hiding this comment

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

Flatter is better for sure

@kddnewton
Copy link
Member

Sorry it took so long to review!

- avoid clobbering the combinator method with a local variable
- return a recursive tree of complex selectors

Partial fix for ruby-syntax-tree#25
@flavorjones flavorjones force-pushed the flavorjones-work-on-selectors branch from c78ef8c to bb5fcc0 Compare June 2, 2024 02:14
@flavorjones
Copy link
Collaborator Author

flavorjones commented Jun 2, 2024

@kddnewton I've added two commits to:

  • introduce some basic selector formatting (incomplete, can finish in a future PR)
  • flatten the Complex Selector AST

Sorry, I know this is a lot of code but I wrote the flatten-ast commit on top of the formatting commit and rebasing to isolate the flatten-ast commit was going to be time consuming.

@kddnewton kddnewton merged commit eb3e2a7 into ruby-syntax-tree:main Jun 3, 2024
2 checks passed
@flavorjones flavorjones deleted the flavorjones-work-on-selectors branch June 3, 2024 21:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

.a + .b {} and .a > .b don't work
2 participants