Skip to content

Allow less strict attribute argument parsing - #1793

Open
nevans wants to merge 1 commit into
ruby:masterfrom
nevans:attribute-initial_symbol_arguments
Open

Allow less strict attribute argument parsing#1793
nevans wants to merge 1 commit into
ruby:masterfrom
nevans:attribute-initial_symbol_arguments

Conversation

@nevans

@nevans nevans commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

The prism parser is strict about attribute arguments: it only parses as an attribute when all arguments are symbols. rdoc 7.2's parser simply ignored any arguments after the initial symbol arguments.

As an example, the rdoc for Net::IMAP::Config intentionally took advantage of the looser parsing done by rdoc 7.2. That class redefines attr_reader, attr_writer and attr_accessor to add keyword arguments for type validation/coercion and defaults:

      # Seconds to wait until a connection is opened.
      #
      # Applied separately for establishing TCP connection and starting a TLS
      # connection.
      #
      # If the IMAP object cannot open a connection within this time,
      # it raises a Net::OpenTimeout exception.
      #
      # See Net::IMAP.new and Net::IMAP#starttls.
      #
      # The default value is +30+ seconds.
      attr_accessor :open_timeout, type: Integer, default: 30

rdoc 7.2 simply ignored the unknown keyword args, and parses this no differently from attr_accessor :open_timeout.

Fixes #1790.

The prism parser is strict about attribute arguments: it only parses as
an attribute when _all_ arguments are symbols.  rdoc 7.2's parser simply
ignored any arguments after the initial symbol arguments.

As an example, the rdoc for `Net::IMAP::Config` intentionally took
advantage of the looser parsing done by rdoc 7.2. That class redefines
`attr_reader`, `attr_writer` and `attr_accessor` to add keyword
arguments for type validation/coercion and defaults:

```ruby
      # Seconds to wait until a connection is opened.
      #
      # Applied separately for establishing TCP connection and starting a TLS
      # connection.
      #
      # If the IMAP object cannot open a connection within this time,
      # it raises a Net::OpenTimeout exception.
      #
      # See Net::IMAP.new and Net::IMAP#starttls.
      #
      # The default value is +30+ seconds.
      attr_accessor :open_timeout, type: Integer, default: 30
```

rdoc 7.2 simply ignored the unknown keyword args, and parses this no
differently from `attr_accessor :open_timeout.`

Fixes ruby#1790.
@nevans
nevans requested a deployment to fork-preview-protection August 28, 2026 14:29 — with GitHub Actions Waiting
@st0012 st0012 added the bug label Aug 29, 2026
Comment thread lib/rdoc/parser/ruby.rb
def _visit_call_attr_reader_writer_accessor(call_node, rw)
return if @scanner.in_proc_block
names = symbol_arguments(call_node)
names = initial_symbol_arguments(call_node)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I feel symbol_arguments should already work like initial_symbol_arguments.

@tompng why was it designed to return nil when there's any non-symbol arguments? What's the case we're guarding against?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

To handle alias_method.
We need to prevent alias_method :foo, bar, :baz, blah: true treated as alias_method :foo, :baz.
In all other case, we can just use the non-strict version.

Comment thread lib/rdoc/parser/ruby.rb

def initial_symbol_arguments(call_node)
return unless arguments = call_node.arguments&.arguments
symbol_args = arguments.take_while {|arg| arg.is_a?(Prism::SymbolNode) }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

How about using arguments.grep(Prism::SymbolNode) instead of take_while and renaming the method?
I think it's worth adding a test like this, which is possible in the original attr_accessor spec

# document :foo, :bar and :baz
attr_accessor :foo, *ignored1, :bar, (ignored2), :baz

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parser should be less strict about attribute arguments

3 participants