yard
yard copied to clipboard
Generated docs for class is empty when a sub-file defines a module with the same name
I stumbled across this strange edge-case while refactoring an old project. If you have a class called Foo::Bar defined in lib/foo/bar.rb, but also have an older file laying around which defines Foo::Bar as a module in lib/foo/bar/old_file.rb and you have another sub-module named Foo::Bar::OtherModule defined in lib/foo/bar/other_module.rb, it someshow shadows the Foo::Bar class and causes it's generated documentation to be completely empty.
Steps to reproduce
Gemfile:
source 'https://rubygems.org'
gem 'kramdown'
gem 'yard', '0.9.28'
lib/foo/bar.rb:
module Foo
class Bar # Note: Bar is defined as a class
def self.a_class_method
end
def an_instance_method
end
end
end
lib/foo/bar/old_file.rb:
module Foo
module Bar # Wrong: this is the old Bar which is a module, not a class
def self.some_old_method
end
end
end
lib/foo/bar/other_module.rb:
module Foo
class Bar # Correct: Bar is correctly defined as a class
module OtherModule
def some_mixin_method
end
end
end
end
bundle installbundle exec yardoc- Open
doc/Foo/Bar.htmlin the browser.
Actual Output
[warn]: Could not load default RDoc formatter, ignoring any markup (install RDoc to get default formatting).
[debug]: Parsing ["{lib,app}/**/*.rb", "ext/**/*.{c,cc,cxx,cpp,rb}"] with `ruby` parser
[debug]: Parsing lib/foo/bar.rb
[debug]: Parsing lib/foo/bar/old_file.rb
[debug]: Parsing lib/foo/bar/other_module.rb
[debug]: Serializing to .yardoc/objects/root.dat
[debug]: Re-generating object ...
[debug]: Re-generating object Foo...
[debug]: Re-generating object Foo::Bar::OtherModule...
[debug]: Re-generating object Foo::Bar...
[debug]: Generating asset js/jquery.js
[debug]: Serializing to doc/js/jquery.js
[debug]: Generating asset js/app.js
[debug]: Serializing to doc/js/app.js
[debug]: Generating asset js/full_list.js
[debug]: Serializing to doc/js/full_list.js
[debug]: Generating asset css/style.css
[debug]: Serializing to doc/css/style.css
[debug]: Generating asset css/common.css
[debug]: Serializing to doc/css/common.css
[debug]: Generating asset css/full_list.css
[debug]: Serializing to doc/css/full_list.css
[debug]: Generating asset class_list.html
[debug]: Serializing to doc/class_list.html
[debug]: Generating asset method_list.html
[debug]: Serializing to doc/method_list.html
[debug]: Generating asset file_list.html
[debug]: Serializing to doc/file_list.html
[debug]: Generating asset frames.html
[debug]: Serializing to doc/frames.html
[debug]: Serializing to doc/index.html
[debug]: Serializing to doc/_index.html
[debug]: Serializing to doc/top-level-namespace.html
[debug]: Serializing to doc/Foo.html
[debug]: Serializing to doc/Foo/Bar/OtherModule.html
[debug]: Serializing to doc/Foo/Bar.html
Files: 3
Modules: 2 ( 2 undocumented)
Classes: 1 ( 1 undocumented)
Constants: 0 ( 0 undocumented)
Attributes: 0 ( 0 undocumented)
Methods: 4 ( 4 undocumented)
0.00% documented
Expected Output
A warning that Foo::Bar was defined as a class then re-defined as a module would be helpful.
Environment details:
- OS: Fedora Linux
- ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
- yard 0.9.28
- kramdown 2.4.0
- [x] I have read the Contributing Guide.

If I rename lib/foo/bar/other_module.rb to lib/foo/bar/baz.rb, the documentation for Foo::Bar in lib/foo/bar/old_file.rb suddenly appears, which implies the order of the files within lib/foo/bar/ matter.
The challenge here is that this Ruby code is fairly undefined in the larger context of the full codebase.
I'd say the only reasonable approach would be to have a warning for this type of use-case. YARD cannot really make a choice on your behalf, so it's pretty much for the end-user to resolve. A warning would at least surface the issue.
I will note, however, that given the extreme rarity of this case, this is likely not a high priority to resolve in the project. For that reason, this is likely going to be closed as a WontFix, with the following caveat/notice:
If you want to throw together a PR for this, I would gladly accept such a warning being surfaced. There are good APIs to perform such a check as well as precedent implementation for warnings, at least in the context of docstrings.
Hope that is helpful!