96 lines
3.3 KiB
Ruby
96 lines
3.3 KiB
Ruby
# Handles `dispatch` calls within a future parser function declaration. For
|
|
# now, it just treats any docstring as an `@overlaod` tag and attaches the
|
|
# overload to the parent function.
|
|
class PuppetX::PuppetLabs::Strings::YARD::Handlers::PuppetProviderHandler < YARD::Handlers::Ruby::Base
|
|
include PuppetX::PuppetLabs::Strings::YARD::CodeObjects
|
|
|
|
handles :command_call, :call
|
|
|
|
process do
|
|
@heredoc_helper = HereDocHelper.new
|
|
# Puppet types always begin with:
|
|
# Puppet::Types.newtype...
|
|
# Therefore, we match the corresponding trees which look like this:
|
|
# s(:call,
|
|
# s(:const_path_ref,
|
|
# s(:var_ref, s(:const, "Puppet", ...), ...),
|
|
# s(:const, "Type", ...),
|
|
# You think this is ugly? It's better than the alternative.
|
|
return unless statement.children.length > 2
|
|
first = statement.children.first.first
|
|
return unless (first.source == 'Puppet::Type') ||
|
|
(first.type == :var_ref &&
|
|
first.source == 'Type') &&
|
|
statement[2].source == 'provide'
|
|
i = statement.index { |s| YARD::Parser::Ruby::AstNode === s && s.type == :ident && s.source == 'provide' }
|
|
provider_name = statement[i+1].jump(:ident).source
|
|
type_name = statement.jump(:symbol).first.source
|
|
|
|
obj = ProviderObject.new(:root, "#{provider_name}_provider")
|
|
|
|
docstring = nil
|
|
features = []
|
|
commands = []
|
|
confines = {}
|
|
defaults = {}
|
|
do_block = statement.jump(:do_block)
|
|
do_block.traverse do |node|
|
|
if is_a_func_call_named?('desc', node)
|
|
content = node.jump(:tstring_content)
|
|
# if we found the string content extract its source
|
|
if content != node
|
|
# The docstring is either the source stripped of heredoc
|
|
# annotations or the raw source.
|
|
if @heredoc_helper.is_heredoc?(content.source)
|
|
docstring = @heredoc_helper.process_heredoc content.source
|
|
else
|
|
docstring = content.source
|
|
end
|
|
end
|
|
elsif is_a_func_call_named?('confine', node)
|
|
node.traverse do |s|
|
|
if s.type == :assoc
|
|
k = s.first.jump(:ident).source
|
|
v = s[1].first.source
|
|
confines[k] = v
|
|
end
|
|
end
|
|
elsif is_a_func_call_named?('has_feature', node)
|
|
list = node.jump :list
|
|
if list != nil && list != node
|
|
features += list.map { |s| s.source if YARD::Parser::Ruby::AstNode === s }.compact
|
|
end
|
|
elsif is_a_func_call_named?('commands', node)
|
|
assoc = node.jump(:assoc)
|
|
if assoc && assoc != node
|
|
ident = assoc.jump(:ident)
|
|
if ident && ident != assoc
|
|
commands << ident.source
|
|
end
|
|
end
|
|
elsif is_a_func_call_named?('defaultfor', node)
|
|
node.traverse do |s|
|
|
if s.type == :assoc
|
|
k = s.first.jump(:ident).source
|
|
v = s[1].first.source
|
|
defaults[k] = v
|
|
end
|
|
end
|
|
end
|
|
end
|
|
obj.features = features
|
|
obj.commands = commands
|
|
obj.confines = confines
|
|
obj.defaults = defaults
|
|
obj.type_name = type_name
|
|
obj.header_name = provider_name
|
|
|
|
register_docstring(obj, docstring, nil)
|
|
register obj
|
|
end
|
|
|
|
def is_a_func_call_named?(name, node)
|
|
(node.type == :fcall || node.type == :command || node.type == :vcall) && node.children.first.source == name
|
|
end
|
|
end
|