Module: Rubycom::YardDoc

Defined in:
lib/rubycom/yard_doc.rb

Class Method Summary collapse

Class Method Details

.check(commands, source_fn) ⇒ Object

Provides upfront checking for this inputs to #document_commands

Raises:

  • (ArgumentError)


25
26
27
28
29
30
# File 'lib/rubycom/yard_doc.rb', line 25

def self.check(commands, source_fn)
  YARD::Logger.instance.level = YARD::Logger::FATAL
  raise ArgumentError, "#{source_fn} should be a Method or Proc but was #{source_fn.class}" unless [Method, Proc].include?(source_fn.class)
  raise ArgumentError, "#{commands} should be an Array but was #{commands.class}" unless commands.class == Array
  [commands, source_fn]
end

.document_command(command, source_method) ⇒ Array

Transforms the command to a Hash representing the command and it’s documentation

Parameters:

  • command (Array)

    a Module or Method to be documented

  • source_method (Module)

    a Module which will be used to retrieve module and method source code

Returns:

  • (Array)

    a Hash which is the result calling #map_doc



10
11
12
# File 'lib/rubycom/yard_doc.rb', line 10

def self.document_command(command, source_method)
  self.document_commands([command], source_method).first[:doc]
end

.document_commands(commands, source_method) ⇒ Array

Transforms each command in commands to a Hash representing the command and it’s documentation

Parameters:

  • commands (Array)

    a set of Modules and Methods to be documented

  • source_method (Module)

    a Module which will be used to retrieve module and method source code

Returns:

  • (Array)

    a set of Hashes which are the result calling #map_doc



19
20
21
22
# File 'lib/rubycom/yard_doc.rb', line 19

def self.document_commands(commands, source_method)
  commands, source_method = self.check(commands, source_method)
  self.map_doc(commands, source_method)
end

.map_doc(commands, source_method) ⇒ Array

Transforms each command in commands to a Hash representing the command and it’s documentation

Parameters:

  • commands (Array)

    a set of Modules and Methods to be documented

  • source_method (Method|Proc)

    used to retrieve module and method source code

Returns:

  • (Array)

    a set of Hashes which are the result of calls to #module_doc and #method_doc



37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/rubycom/yard_doc.rb', line 37

def self.map_doc(commands, source_method)
  commands.map { |cmd|
    {
        command: cmd,
        doc: if cmd.class == Module
               self.module_doc(cmd, source_method)
             elsif cmd.class == Method
               self.method_doc(cmd, source_method)
             else
               {short_doc: '', full_doc: ''}
             end
    }
  }
end

.method_doc(method, source_method) ⇒ Hash

Extracts elements of source code documentation for the given method. Calls #source_command on the given source_plugin to retrieve the method’s source code.

Alternately this parameter can be a YARD::CodeObjects::MethodObject which will be used instead of looking up the method’s source code :tags => [ { :tag_name => String, :name => String, :types => [String], :text => String } ], :parameters => [ { :param_name => String, :type => :req|:opt|:rest, :default => Object, :doc_type => String, :doc => String } ]

Parameters:

  • method (Method)

    a Method instance representing the method whose documentation should be parsed

  • source_method (Method|Proc|YARD::CodeObjects::MethodObject)

    called to retrieve the method’s source code.

Returns:

  • (Hash)

    :short_doc => String, :full_doc => String,

Raises:

  • (ArgumentError)


96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/rubycom/yard_doc.rb', line 96

def self.method_doc(method, source_method)
  raise ArgumentError, "method should be a Method but was #{method.class}" unless method.class == Method
  method_param_types = method.parameters.map { |type, sym| {sym => type} }.reduce({}, &:merge)
  if source_method.class == YARD::CodeObjects::MethodObject
    doc_obj = source_method
  elsif source_method.is_a?(Proc) || source_method.is_a?(Method)
    YARD::Registry.clear
    YARD.parse_string(source_method.call(method))
    method_name = method.name
    doc_obj = YARD::Registry.at(method_name.to_s)
    doc_obj = YARD::Registry.at("::#{method_name.to_s}") if doc_obj.nil?
    doc_obj = YARD::Registry.at("\##{method_name.to_s}") if doc_obj.nil?
    doc_obj = YARD::Registry.at(method_name.to_s.split('.').last) if doc_obj.nil?
    raise ArgumentError, "No such method #{method_name} in the given source." if doc_obj.nil?
  else
    raise ArgumentError, "source_plugin should be YARD::CodeObjects::MethodObject|Method but was #{source_method.class}"
  end
  {
      parameters: doc_obj.parameters.map { |k, v|
        # YARD's parsing returns pairs of params and values
        # if the param has a default value then the value is wrapped in a string
        # required arguments have a value of nil
        param_type = method_param_types[k.reverse.chomp('*').reverse.to_sym]
        param_default = if param_type == :rest
                          []
                        else
                          (v.class == String) ? method.receiver.module_eval(v) : v
                        end
        {
            param_name: k,
            type: param_type,
            default: param_default,
            doc_type: doc_obj.tags.select { |tag| tag.name == k.to_s }.map { |tag| tag.types }.join(','),
            doc: doc_obj.tags.select { |tag| tag.name == k.to_s }.map { |tag| tag.text }.join("\n")
        }
      },
      short_doc: doc_obj.base_docstring.summary.to_s,
      full_doc: doc_obj.base_docstring.to_s,
      tags: doc_obj.tags.map { |tag|
        {
            tag_name: tag.tag_name,
            name: tag.name,
            types: tag.types,
            text: tag.text
        }
      }
  }
end

.module_doc(mod, source_method) ⇒ Hash

Extracts elements of source code documentation for the given module. Calls #source_command on the given source_plugin to retrieve the method’s source code.

Parameters:

  • mod (Module)

    a Module instance representing the module whose documentation should be parsed

  • source_method (Method)

    a Module which will be used to retrieve module and method source code

Returns:

  • (Hash)

    :short_doc => String, :full_doc => String, :sub_command_docs => [ { sub_command_name_symbol => String } ]



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/rubycom/yard_doc.rb', line 58

def self.module_doc(mod, source_method)
  module_source = source_method.call(mod)
  YARD::Registry.clear
  YARD.parse_string(module_source.to_s)
  doc_obj = YARD::Registry.at(mod.to_s)
  return {short_doc: '', full_doc: ''} if doc_obj.nil?
  {
      short_doc: doc_obj.docstring.summary,
      full_doc: doc_obj.docstring.to_s,
      sub_command_docs: doc_obj.meths(:visibility => :public, :scope => :class).map { |doc_method|
        {
            doc_method.name => self.method_doc(mod.public_method(doc_method.name), doc_method)[:short_doc]
        }
      }.reduce({}, &:merge).merge(
          doc_obj.mixins.select { |doc_mod| doc_mod.name != :Rubycom }.map { |doc_mod|
            namespaced_mod_name = "#{doc_mod.namespace}::#{doc_mod.name}"
            mod_source = source_method.call(namespaced_mod_name)
            mod_source = source_method.call(doc_mod.name) if mod_source == namespaced_mod_name
            YARD.parse_string(mod_source.to_s)
            sub_doc_obj = YARD::Registry.at(doc_mod.to_s)
            {
                doc_mod.name => (sub_doc_obj.nil?) ? '' : sub_doc_obj.docstring.summary.to_s
            }
          }.reduce({}, &:merge)
      )
  }
end