yard icon indicating copy to clipboard operation
yard copied to clipboard

@!endgroup requires two blank lines between it and `class << self`

Open Mr0grog opened this issue 5 years ago • 2 comments

This is probably a bit obscure, but I’m running into a situation where @!endgroup has to be followed by two blank lines (rather than one or none) in order to take effect. Specifically, it’s when the directive is followed by a class << self block (but not sure if other method calls with blocks, internal classes, or other things might also cause this).

For example, I have some code like the following:

module A
    class B
        # @!group Foo
        
        def foo; end
        def self.bar; end
        
        # @!endgroup

        class << self
            def class_method; end
        end

        def instance_method; end
    end
end

In this setup, class_method and instance_method wind up in the Foo group, when they should not. If I add a second blank line after # @!endgroup, they are correctly removed from the group.

Steps to reproduce

For an exact reproduction, run the following Ruby:

require 'yard'
YARD::Registry.clear
parsed = YARD.parse_string <<-'eof'
    module A
        class B
            # @!group Foo
            
            def foo; end
            def self.bar; end
            
            # @!endgroup

            class << self
                def class_method; end
            end

            def instance_method; end
        end
    end
eof
YARD::Registry.at('A::B').meths.each {|m| puts "#{m}: group '#{m.group}'"}

…which outputs:

A::B#foo: group 'Foo'
A::B.bar: group 'Foo'
A::B.class_method: group 'Foo'
A::B#instance_method: group 'Foo'

Expected Output

Instead, I’m pretty sure I should have seen:

A::B#foo: group 'Foo'
A::B.bar: group 'Foo'
A::B.class_method: group ''
A::B#instance_method: group ''

Environment details:

  • OS: MacOS 10.14.6
  • Ruby version (ruby -v): ruby 2.6.6p146 (2020-03-31 revision 67876) [x86_64-darwin18]
  • YARD version (yard -v): yard 0.9.25
  • Relevant software dependency/versions: None

I have read the Contributing Guide.

Mr0grog avatar Sep 01 '20 19:09 Mr0grog

Looks like this is probably happening because:

  1. The source parser attaches the # @!endgroup comment to the class << self AST node if it’s less than two lines above (which seems OK, the same thing happens if the next thing is a method instead of class << self): https://github.com/lsegal/yard/blob/2b16190ced212bdb948fb47568645b29590bdbcd/lib/yard/parser/ruby/ruby_parser.rb#L623-L630

  2. The handler for sclass nodes parses inside the block, but never registers/parses the docstring: https://github.com/lsegal/yard/blob/2b16190ced212bdb948fb47568645b29590bdbcd/lib/yard/handlers/ruby/class_handler.rb#L32-L35

I’m not really familiar with Yard’s internals at all, but it doesn’t seem like creating a ClassObject and calling register with it makes sense there. Two approaches jump out to me given my limited knowledge:

  1. Maybe the sclass handler should be calling register_docstring(nil) like the comment handler does?
  2. Maybe the parser should special case this situation and not attach the comment to the sclass AST node in the first place?

Mr0grog avatar Sep 01 '20 20:09 Mr0grog

Anyway, I’m happy to work on a PR for this if someone here has a preference for one of the two solutions above.

Mr0grog avatar Sep 06 '20 18:09 Mr0grog