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

ProcessedSource#ast_with_comments doesn't differentiate between identical nodes #179

Closed
dvandersluis opened this issue May 1, 2021 · 4 comments

Comments

@dvandersluis
Copy link
Member

This spec passes but is strange behaviour:

RSpec.describe RuboCop::AST::ProcessedSource do
  describe '#ast_with_comments' do
    include RuboCop::AST::Sexp

    let(:source) do
      <<~RUBY
        # comment 1
        do_a
        # comment 2
        do_b
        # comment 3
        do_a
      RUBY
    end

    it do
      expect(processed_source.ast_with_comments).to include(
        s(:send, nil, :do_a) => [instance_of(Parser::Source::Comment), instance_of(Parser::Source::Comment)],
        s(:send, nil, :do_b) => [instance_of(Parser::Source::Comment)]
      )
    end
  end
end

Here is the actual hash created:

{
  s(:send, nil, :do_a) => [
    #<Parser::Source::Comment ast/and_node_spec.rb:1:1 "# comment 1">,
    #<Parser::Source::Comment ast/and_node_spec.rb:5:1 "# comment 3">
  ],
  s(:send, nil, :do_b) => [
    #<Parser::Source::Comment ast/and_node_spec.rb:3:1 "# comment 2">
  ]
}

Because there are two s(:send, nil, :do_a) nodes, both comments are associated with the same node in the hash, and then when this is used in rubocop (for instance CommentsHelp.begin_pos_with_comment), it returns potentially the wrong comment node.

I don't know that there is a good way to fix this necessarily without changing how the keys are constructed; this might also not be a RuboCop::AST bug directly either.

@marcandre
Copy link
Contributor

Indeed, this is surprising 😅

This was noted in whitequark/parser#184: "Note that {associate} produces unexpected result for nodes which are equal but have distinct locations; comments for these nodes are merged."

The proposed fix was associate_locations that does the same but uses the location as key.

IMO, a better method than either of them would be associate_by_identity, which does not use eql? but equal?. I'm proposing a PR for this: whitequark/parser#798

I believe that we could modify our ast_with_comments to use that without any incompatibility, but I didn't double check yet.

marcandre added a commit to marcandre/rubocop-ast that referenced this issue May 2, 2021
marcandre added a commit to marcandre/rubocop-ast that referenced this issue May 2, 2021
@mergify mergify bot closed this as completed in 8b783c1 May 2, 2021
@marcandre
Copy link
Contributor

As I expected, tests pass on master.
Released in 1.4.2 👍

@marcandre
Copy link
Contributor

Released 1.5.0...

@dvandersluis
Copy link
Member Author

Thanks for the quick work @marcandre! 🎉

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

No branches or pull requests

2 participants