dug
dug

Reputation: 2345

Get YARD comments for Ruby objects programmatically

Given the following ruby file, foo.rb:

# this is a module comment
module A
  # this is a constant comment
  B = 'hi'
  # this is a class comment
  class C
    # this is a method comment
    # @param [String] name Who to say hi to
    # @return [String]
    def self.hi(name)
      "#{B}, #{name}"
    end
  end
end

How can one programmatically get the comments associated with particular objects (e.g. {A::C => 'this is a class comment'}, {B => 'this is a constant comment'})?

I would expect YARD.parse(File.read('/path/to/foo.rb')) or YARD::Parser::SourceParser.parse(File.read('/path/to/foo.rb')) to do something, but they return empty arrays. YARD::Parser::Ruby::RubyParser.parse(File.read('/path/to/foo.rb')) returns a YARD::Parser::Ruby::RipperParser instance that appears to be an AST, but I'd prefer to avoid writing an AST traverser (YARD must have this functionality in order to structure the HTML documentation, but I haven't been able to find it).

(I'm using YARD v0.9.9 in case that's helpful.)

Upvotes: 4

Views: 501

Answers (1)

avellable
avellable

Reputation: 1395

So after playing around a little bit and going through the source of yard, I can understand how yard works. Basically it creates a registry of all code objects after YARD.parse. We can access it like this,

2.4.1 :033 > YARD.parse('./foo.rb')
=> []
2.4.1 :034 > YARD::Registry.all
=> [#<yardoc module A>, #<yardoc constant A::B>, #<yardoc class A::C>, #<yardoc method A::C.hi>]
2.4.1 :035 > code_objects = YARD::Registry.all.map {|object| {object.name => object.docstring} }.inject(&:merge)
{:A=>"this is a module comment", :B=>"this is a constant comment", :C=>"this is a class comment", :hi=>"this is a method comment"}
2.4.1 :036 > code_objects[:A]
=> "this is a module comment"

You should be able to use this and convert into a method as per your needs.

More here: https://github.com/lsegal/yard/blob/master/lib/yard/registry.rb#L225-L237

Upvotes: 6

Related Questions