openvox-strings 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +407 -0
- data/LICENSE +177 -0
- data/README.md +116 -0
- data/lib/openvox-strings/describe.rb +75 -0
- data/lib/openvox-strings/json.rb +33 -0
- data/lib/openvox-strings/markdown/base.rb +236 -0
- data/lib/openvox-strings/markdown/data_type.rb +39 -0
- data/lib/openvox-strings/markdown/defined_type.rb +20 -0
- data/lib/openvox-strings/markdown/function.rb +59 -0
- data/lib/openvox-strings/markdown/helpers.rb +21 -0
- data/lib/openvox-strings/markdown/puppet_class.rb +20 -0
- data/lib/openvox-strings/markdown/puppet_plan.rb +20 -0
- data/lib/openvox-strings/markdown/puppet_task.rb +29 -0
- data/lib/openvox-strings/markdown/resource_type.rb +56 -0
- data/lib/openvox-strings/markdown/templates/classes_and_defines.erb +94 -0
- data/lib/openvox-strings/markdown/templates/data_type.erb +101 -0
- data/lib/openvox-strings/markdown/templates/data_type_function.erb +67 -0
- data/lib/openvox-strings/markdown/templates/function.erb +106 -0
- data/lib/openvox-strings/markdown/templates/puppet_task.erb +28 -0
- data/lib/openvox-strings/markdown/templates/resource_type.erb +156 -0
- data/lib/openvox-strings/markdown/templates/table_of_contents.erb +26 -0
- data/lib/openvox-strings/markdown.rb +81 -0
- data/lib/openvox-strings/monkey_patches/display_object_command.rb +16 -0
- data/lib/openvox-strings/tasks/generate.rb +54 -0
- data/lib/openvox-strings/tasks/gh_pages.rb +72 -0
- data/lib/openvox-strings/tasks/validate.rb +42 -0
- data/lib/openvox-strings/tasks.rb +14 -0
- data/lib/openvox-strings/version.rb +5 -0
- data/lib/openvox-strings/yard/code_objects/base.rb +16 -0
- data/lib/openvox-strings/yard/code_objects/class.rb +60 -0
- data/lib/openvox-strings/yard/code_objects/data_type.rb +102 -0
- data/lib/openvox-strings/yard/code_objects/data_type_alias.rb +60 -0
- data/lib/openvox-strings/yard/code_objects/defined_type.rb +59 -0
- data/lib/openvox-strings/yard/code_objects/function.rb +106 -0
- data/lib/openvox-strings/yard/code_objects/group.rb +33 -0
- data/lib/openvox-strings/yard/code_objects/plan.rb +59 -0
- data/lib/openvox-strings/yard/code_objects/provider.rb +98 -0
- data/lib/openvox-strings/yard/code_objects/task.rb +69 -0
- data/lib/openvox-strings/yard/code_objects/type.rb +196 -0
- data/lib/openvox-strings/yard/code_objects.rb +14 -0
- data/lib/openvox-strings/yard/handlers/helpers.rb +10 -0
- data/lib/openvox-strings/yard/handlers/json/base.rb +8 -0
- data/lib/openvox-strings/yard/handlers/json/task_handler.rb +34 -0
- data/lib/openvox-strings/yard/handlers/puppet/base.rb +52 -0
- data/lib/openvox-strings/yard/handlers/puppet/class_handler.rb +29 -0
- data/lib/openvox-strings/yard/handlers/puppet/data_type_alias_handler.rb +26 -0
- data/lib/openvox-strings/yard/handlers/puppet/defined_type_handler.rb +29 -0
- data/lib/openvox-strings/yard/handlers/puppet/function_handler.rb +54 -0
- data/lib/openvox-strings/yard/handlers/puppet/plan_handler.rb +29 -0
- data/lib/openvox-strings/yard/handlers/ruby/base.rb +55 -0
- data/lib/openvox-strings/yard/handlers/ruby/data_type_handler.rb +411 -0
- data/lib/openvox-strings/yard/handlers/ruby/function_handler.rb +386 -0
- data/lib/openvox-strings/yard/handlers/ruby/provider_handler.rb +127 -0
- data/lib/openvox-strings/yard/handlers/ruby/rsapi_handler.rb +157 -0
- data/lib/openvox-strings/yard/handlers/ruby/type_base.rb +146 -0
- data/lib/openvox-strings/yard/handlers/ruby/type_extras_handler.rb +65 -0
- data/lib/openvox-strings/yard/handlers/ruby/type_handler.rb +105 -0
- data/lib/openvox-strings/yard/handlers.rb +28 -0
- data/lib/openvox-strings/yard/parsers/json/parser.rb +38 -0
- data/lib/openvox-strings/yard/parsers/json/task_statement.rb +37 -0
- data/lib/openvox-strings/yard/parsers/puppet/parser.rb +89 -0
- data/lib/openvox-strings/yard/parsers/puppet/statement.rb +182 -0
- data/lib/openvox-strings/yard/parsers.rb +14 -0
- data/lib/openvox-strings/yard/tags/enum_tag.rb +13 -0
- data/lib/openvox-strings/yard/tags/factory.rb +18 -0
- data/lib/openvox-strings/yard/tags/overload_tag.rb +112 -0
- data/lib/openvox-strings/yard/tags/parameter_directive.rb +25 -0
- data/lib/openvox-strings/yard/tags/property_directive.rb +25 -0
- data/lib/openvox-strings/yard/tags/summary_tag.rb +10 -0
- data/lib/openvox-strings/yard/tags.rb +11 -0
- data/lib/openvox-strings/yard/templates/default/fulldoc/html/css/common.css +8 -0
- data/lib/openvox-strings/yard/templates/default/fulldoc/html/full_list_puppet_class.erb +9 -0
- data/lib/openvox-strings/yard/templates/default/fulldoc/html/full_list_puppet_data_type.erb +10 -0
- data/lib/openvox-strings/yard/templates/default/fulldoc/html/full_list_puppet_defined_type.erb +9 -0
- data/lib/openvox-strings/yard/templates/default/fulldoc/html/full_list_puppet_function.erb +10 -0
- data/lib/openvox-strings/yard/templates/default/fulldoc/html/full_list_puppet_plan.erb +9 -0
- data/lib/openvox-strings/yard/templates/default/fulldoc/html/full_list_puppet_provider.erb +10 -0
- data/lib/openvox-strings/yard/templates/default/fulldoc/html/full_list_puppet_task.erb +9 -0
- data/lib/openvox-strings/yard/templates/default/fulldoc/html/full_list_puppet_type.erb +9 -0
- data/lib/openvox-strings/yard/templates/default/fulldoc/html/setup.rb +93 -0
- data/lib/openvox-strings/yard/templates/default/layout/html/footer.erb +3 -0
- data/lib/openvox-strings/yard/templates/default/layout/html/objects.erb +37 -0
- data/lib/openvox-strings/yard/templates/default/layout/html/setup.rb +231 -0
- data/lib/openvox-strings/yard/templates/default/puppet_class/html/box_info.erb +26 -0
- data/lib/openvox-strings/yard/templates/default/puppet_class/html/deprecated.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_class/html/header.erb +1 -0
- data/lib/openvox-strings/yard/templates/default/puppet_class/html/note.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_class/html/overview.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_class/html/setup.rb +16 -0
- data/lib/openvox-strings/yard/templates/default/puppet_class/html/source.erb +12 -0
- data/lib/openvox-strings/yard/templates/default/puppet_class/html/summary.erb +4 -0
- data/lib/openvox-strings/yard/templates/default/puppet_class/html/todo.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/box_info.erb +10 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/deprecated.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/header.erb +1 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/method_details_list.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/note.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/overview.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/setup.rb +15 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/source.erb +12 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/summary.erb +4 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/todo.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/alias_of.erb +10 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/box_info.erb +10 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/deprecated.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/header.erb +1 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/note.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/overview.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/setup.rb +19 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/source.erb +12 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/summary.erb +4 -0
- data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/todo.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/box_info.erb +10 -0
- data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/deprecated.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/header.erb +1 -0
- data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/note.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/overview.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/setup.rb +7 -0
- data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/source.erb +12 -0
- data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/summary.erb +4 -0
- data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/todo.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_function/html/box_info.erb +14 -0
- data/lib/openvox-strings/yard/templates/default/puppet_function/html/deprecated.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_function/html/header.erb +1 -0
- data/lib/openvox-strings/yard/templates/default/puppet_function/html/note.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_function/html/overview.erb +18 -0
- data/lib/openvox-strings/yard/templates/default/puppet_function/html/setup.rb +7 -0
- data/lib/openvox-strings/yard/templates/default/puppet_function/html/source.erb +12 -0
- data/lib/openvox-strings/yard/templates/default/puppet_function/html/summary.erb +4 -0
- data/lib/openvox-strings/yard/templates/default/puppet_function/html/todo.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_plan/html/box_info.erb +10 -0
- data/lib/openvox-strings/yard/templates/default/puppet_plan/html/deprecated.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_plan/html/header.erb +1 -0
- data/lib/openvox-strings/yard/templates/default/puppet_plan/html/note.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_plan/html/overview.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_plan/html/setup.rb +13 -0
- data/lib/openvox-strings/yard/templates/default/puppet_plan/html/source.erb +12 -0
- data/lib/openvox-strings/yard/templates/default/puppet_plan/html/summary.erb +4 -0
- data/lib/openvox-strings/yard/templates/default/puppet_plan/html/todo.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_provider/html/box_info.erb +14 -0
- data/lib/openvox-strings/yard/templates/default/puppet_provider/html/collection.erb +17 -0
- data/lib/openvox-strings/yard/templates/default/puppet_provider/html/features.erb +12 -0
- data/lib/openvox-strings/yard/templates/default/puppet_provider/html/header.erb +1 -0
- data/lib/openvox-strings/yard/templates/default/puppet_provider/html/overview.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_provider/html/setup.rb +31 -0
- data/lib/openvox-strings/yard/templates/default/puppet_provider/html/summary.erb +4 -0
- data/lib/openvox-strings/yard/templates/default/puppet_task/html/box_info.erb +9 -0
- data/lib/openvox-strings/yard/templates/default/puppet_task/html/header.erb +1 -0
- data/lib/openvox-strings/yard/templates/default/puppet_task/html/input.erb +5 -0
- data/lib/openvox-strings/yard/templates/default/puppet_task/html/overview.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_task/html/parameters.erb +16 -0
- data/lib/openvox-strings/yard/templates/default/puppet_task/html/setup.rb +24 -0
- data/lib/openvox-strings/yard/templates/default/puppet_task/html/supports_noop.erb +3 -0
- data/lib/openvox-strings/yard/templates/default/puppet_type/html/box_info.erb +20 -0
- data/lib/openvox-strings/yard/templates/default/puppet_type/html/deprecated.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_type/html/features.erb +13 -0
- data/lib/openvox-strings/yard/templates/default/puppet_type/html/header.erb +1 -0
- data/lib/openvox-strings/yard/templates/default/puppet_type/html/note.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_type/html/overview.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/puppet_type/html/parameters.erb +35 -0
- data/lib/openvox-strings/yard/templates/default/puppet_type/html/setup.rb +36 -0
- data/lib/openvox-strings/yard/templates/default/puppet_type/html/summary.erb +4 -0
- data/lib/openvox-strings/yard/templates/default/puppet_type/html/todo.erb +6 -0
- data/lib/openvox-strings/yard/templates/default/tags/html/enum.erb +17 -0
- data/lib/openvox-strings/yard/templates/default/tags/html/puppet_overload.erb +12 -0
- data/lib/openvox-strings/yard/templates/default/tags/setup.rb +20 -0
- data/lib/openvox-strings/yard/util.rb +87 -0
- data/lib/openvox-strings/yard.rb +132 -0
- data/lib/openvox-strings.rb +88 -0
- data/lib/puppet/application/strings.rb +7 -0
- data/lib/puppet/face/strings.rb +185 -0
- data/lib/puppet/feature/rgen.rb +5 -0
- data/lib/puppet/feature/yard.rb +5 -0
- metadata +263 -0
@@ -0,0 +1,386 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'openvox-strings/yard/handlers/helpers'
|
4
|
+
require 'openvox-strings/yard/handlers/ruby/base'
|
5
|
+
require 'openvox-strings/yard/code_objects'
|
6
|
+
require 'openvox-strings/yard/util'
|
7
|
+
|
8
|
+
# Implements the handler for Puppet functions written in Ruby.
|
9
|
+
class OpenvoxStrings::Yard::Handlers::Ruby::FunctionHandler < OpenvoxStrings::Yard::Handlers::Ruby::Base
|
10
|
+
# Represents the list of Puppet 4.x function API methods to support.
|
11
|
+
DISPATCH_METHOD_NAMES = %w[
|
12
|
+
param
|
13
|
+
required_param
|
14
|
+
optional_param
|
15
|
+
repeated_param
|
16
|
+
optional_repeated_param
|
17
|
+
required_repeated_param
|
18
|
+
block_param
|
19
|
+
required_block_param
|
20
|
+
optional_block_param
|
21
|
+
return_type
|
22
|
+
].freeze
|
23
|
+
|
24
|
+
namespace_only
|
25
|
+
handles method_call(:create_function)
|
26
|
+
handles method_call(:newfunction)
|
27
|
+
|
28
|
+
process do
|
29
|
+
# Only accept calls to Puppet::Functions (4.x) or Puppet::Parser::Functions (3.x)
|
30
|
+
# When `newfunction` is separated from the Puppet::Parser::Functions module name by a
|
31
|
+
# newline, YARD ignores the namespace and uses `newfunction` as the source of the
|
32
|
+
# first statement.
|
33
|
+
return unless statement.count > 1
|
34
|
+
|
35
|
+
module_name = statement[0].source
|
36
|
+
return unless ['Puppet::Functions', 'Puppet::Parser::Functions', 'newfunction'].include?(module_name)
|
37
|
+
|
38
|
+
# Create and register the function object
|
39
|
+
is_3x = ['Puppet::Parser::Functions', 'newfunction'].include?(module_name)
|
40
|
+
object = OpenvoxStrings::Yard::CodeObjects::Function.new(
|
41
|
+
get_name(statement, 'Puppet::Functions.create_function'),
|
42
|
+
is_3x ? OpenvoxStrings::Yard::CodeObjects::Function::RUBY_3X : OpenvoxStrings::Yard::CodeObjects::Function::RUBY_4X
|
43
|
+
)
|
44
|
+
object.source = statement
|
45
|
+
register object
|
46
|
+
|
47
|
+
# For 3x, parse the doc parameter for the docstring
|
48
|
+
# This must be done after the `register` call above because `register` always uses the statement's docstring
|
49
|
+
if is_3x
|
50
|
+
docstring = get_3x_docstring(object.name)
|
51
|
+
register_docstring(object, docstring, nil) if docstring
|
52
|
+
|
53
|
+
# Default any typeless param tag to 'Any'
|
54
|
+
object.tags(:param).each do |tag|
|
55
|
+
tag.types = ['Any'] unless tag.types && !tag.types.empty?
|
56
|
+
end
|
57
|
+
|
58
|
+
# Populate the parameters and the return tag
|
59
|
+
object.parameters = object.tags(:param).map { |p| [p.name, nil] }
|
60
|
+
add_return_tag(object, statement.file, statement.line)
|
61
|
+
else
|
62
|
+
# For 4x, auto generate tags based on dispatch docstrings
|
63
|
+
add_tags(object)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Mark the function as public if it doesn't already have an api tag
|
67
|
+
object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api
|
68
|
+
|
69
|
+
# Warn if a summary longer than 140 characters was provided
|
70
|
+
OpenvoxStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def add_tags(object)
|
76
|
+
log.warn "Missing documentation for Puppet function '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? && object.tags.empty?
|
77
|
+
|
78
|
+
unless object.tags(:param).empty?
|
79
|
+
log.warn "The docstring for Puppet 4.x function '#{object.name}' " \
|
80
|
+
"contains @param tags near #{object.file}:#{object.line}: parameter " \
|
81
|
+
'documentation should be made on the dispatch call.'
|
82
|
+
end
|
83
|
+
|
84
|
+
unless object.tags(:return).empty?
|
85
|
+
log.warn "The docstring for Puppet 4.x function '#{object.name}' " \
|
86
|
+
"contains @return tags near #{object.file}:#{object.line}: return " \
|
87
|
+
'value documentation should be made on the dispatch call.'
|
88
|
+
end
|
89
|
+
|
90
|
+
unless object.tags(:overload).empty?
|
91
|
+
log.warn "The docstring for Puppet 4.x function '#{object.name}' " \
|
92
|
+
"contains @overload tags near #{object.file}:#{object.line}: overload " \
|
93
|
+
'tags are automatically generated from the dispatch calls.'
|
94
|
+
end
|
95
|
+
|
96
|
+
# Delete any existing param/return/overload tags
|
97
|
+
object.docstring.delete_tags(:param)
|
98
|
+
object.docstring.delete_tags(:return)
|
99
|
+
object.docstring.delete_tags(:overload)
|
100
|
+
|
101
|
+
block = statement.block
|
102
|
+
return unless block && block.count >= 2
|
103
|
+
|
104
|
+
# Get the unqualified name of the Puppet function
|
105
|
+
unqualified_name = object.name.to_s.split('::').last
|
106
|
+
|
107
|
+
# Walk the block statements looking for dispatch calls and methods with the same name as the Puppet function
|
108
|
+
default = nil
|
109
|
+
block[1].children.each do |node|
|
110
|
+
if node.is_a?(YARD::Parser::Ruby::MethodCallNode)
|
111
|
+
add_overload_tag(object, node)
|
112
|
+
elsif node.is_a?(YARD::Parser::Ruby::MethodDefinitionNode)
|
113
|
+
default = node if node.method_name && node.method_name.source == unqualified_name
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Create an overload for the default method if there is one
|
118
|
+
overloads = object.tags(:overload)
|
119
|
+
if overloads.empty? && default
|
120
|
+
add_method_overload(object, default)
|
121
|
+
overloads = object.tags(:overload)
|
122
|
+
end
|
123
|
+
|
124
|
+
# If there's only one overload, move the tags to the object itself
|
125
|
+
return unless overloads.length == 1
|
126
|
+
|
127
|
+
overload = overloads.first
|
128
|
+
object.parameters = overload.parameters
|
129
|
+
object.add_tag(*overload.tags)
|
130
|
+
object.docstring.delete_tags(:overload)
|
131
|
+
end
|
132
|
+
|
133
|
+
def add_overload_tag(object, node)
|
134
|
+
# Look for a call to a dispatch method with a block
|
135
|
+
return unless node.is_a?(YARD::Parser::Ruby::MethodCallNode) &&
|
136
|
+
node.method_name &&
|
137
|
+
node.method_name.source == 'dispatch' &&
|
138
|
+
node.parameters(false).count == 1 &&
|
139
|
+
node.block &&
|
140
|
+
node.block.count >= 2
|
141
|
+
|
142
|
+
overload_tag = OpenvoxStrings::Yard::Tags::OverloadTag.new(object.name, node.docstring || '')
|
143
|
+
param_tags = overload_tag.tags(:param)
|
144
|
+
|
145
|
+
block = nil
|
146
|
+
node.block[1].children.each do |child|
|
147
|
+
next unless child.is_a?(YARD::Parser::Ruby::MethodCallNode) && child.method_name
|
148
|
+
|
149
|
+
method_name = child.method_name.source
|
150
|
+
next unless DISPATCH_METHOD_NAMES.include?(method_name)
|
151
|
+
|
152
|
+
if method_name == 'return_type'
|
153
|
+
# Add a return tag if missing
|
154
|
+
overload_tag.add_tag YARD::Tags::Tag.new(:return, '', 'Any') if overload_tag.tag(:return).nil?
|
155
|
+
|
156
|
+
overload_tag.tag(:return).types = [node_as_string(child.parameters[0])]
|
157
|
+
next
|
158
|
+
end
|
159
|
+
|
160
|
+
# Check for block
|
161
|
+
if method_name.include?('block')
|
162
|
+
if block
|
163
|
+
log.warn "A duplicate block parameter was found for Puppet function '#{object.name}' at #{child.file}:#{child.line}."
|
164
|
+
next
|
165
|
+
end
|
166
|
+
|
167
|
+
# Store the block; needs to be appended last
|
168
|
+
block = child
|
169
|
+
next
|
170
|
+
end
|
171
|
+
|
172
|
+
# Ensure two parameters to parameter definition
|
173
|
+
parameters = child.parameters(false)
|
174
|
+
unless parameters.count == 2
|
175
|
+
log.warn "Expected 2 arguments to '#{method_name}' call at #{child.file}:#{child.line}: parameter information may not be correct."
|
176
|
+
next
|
177
|
+
end
|
178
|
+
|
179
|
+
add_param_tag(
|
180
|
+
overload_tag,
|
181
|
+
param_tags,
|
182
|
+
node_as_string(parameters[1]),
|
183
|
+
child.file,
|
184
|
+
child.line,
|
185
|
+
node_as_string(parameters[0]),
|
186
|
+
nil, # TODO: determine default from corresponding Ruby method signature?
|
187
|
+
method_name.include?('optional'),
|
188
|
+
method_name.include?('repeated')
|
189
|
+
)
|
190
|
+
end
|
191
|
+
|
192
|
+
# Handle the block parameter after others so it appears last in the list
|
193
|
+
if block
|
194
|
+
parameters = block.parameters(false)
|
195
|
+
if parameters.empty?
|
196
|
+
name = 'block'
|
197
|
+
type = 'Callable'
|
198
|
+
elsif parameters.count == 1
|
199
|
+
name = node_as_string(parameters[0])
|
200
|
+
type = 'Callable'
|
201
|
+
elsif parameters.count == 2
|
202
|
+
type = node_as_string(parameters[0])
|
203
|
+
name = node_as_string(parameters[1])
|
204
|
+
else
|
205
|
+
log.warn "Unexpected number of arguments to block definition at #{block.file}:#{block.line}."
|
206
|
+
end
|
207
|
+
|
208
|
+
if name && type
|
209
|
+
add_param_tag(
|
210
|
+
overload_tag,
|
211
|
+
param_tags,
|
212
|
+
name,
|
213
|
+
block.file,
|
214
|
+
block.line,
|
215
|
+
type,
|
216
|
+
nil, # TODO: determine default from corresponding Ruby method signature?
|
217
|
+
block.method_name.source.include?('optional'),
|
218
|
+
false, # Not repeated
|
219
|
+
true # Is block
|
220
|
+
)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
# Add a return tag if missing
|
225
|
+
add_return_tag(overload_tag, node.file, node.line)
|
226
|
+
|
227
|
+
# Validate that tags have parameters
|
228
|
+
validate_overload(overload_tag, node.file, node.line)
|
229
|
+
|
230
|
+
object.add_tag overload_tag
|
231
|
+
end
|
232
|
+
|
233
|
+
def add_method_overload(object, node)
|
234
|
+
overload_tag = OpenvoxStrings::Yard::Tags::OverloadTag.new(object.name, node.docstring || '')
|
235
|
+
param_tags = overload_tag.tags(:param)
|
236
|
+
|
237
|
+
parameters = node.parameters
|
238
|
+
|
239
|
+
# Populate the required parameters
|
240
|
+
params = parameters.unnamed_required_params
|
241
|
+
params&.each do |parameter|
|
242
|
+
add_param_tag(
|
243
|
+
overload_tag,
|
244
|
+
param_tags,
|
245
|
+
parameter.source,
|
246
|
+
parameter.file,
|
247
|
+
parameter.line
|
248
|
+
)
|
249
|
+
end
|
250
|
+
|
251
|
+
# Populate the optional parameters
|
252
|
+
params = parameters.unnamed_optional_params
|
253
|
+
params&.each do |parameter|
|
254
|
+
add_param_tag(
|
255
|
+
overload_tag,
|
256
|
+
param_tags,
|
257
|
+
parameter[0].source,
|
258
|
+
parameter.file,
|
259
|
+
parameter.line,
|
260
|
+
nil,
|
261
|
+
parameter[1].source,
|
262
|
+
true
|
263
|
+
)
|
264
|
+
end
|
265
|
+
|
266
|
+
# Populate the splat parameter
|
267
|
+
param = parameters.splat_param
|
268
|
+
if param
|
269
|
+
add_param_tag(
|
270
|
+
overload_tag,
|
271
|
+
param_tags,
|
272
|
+
param.source,
|
273
|
+
param.file,
|
274
|
+
param.line,
|
275
|
+
nil,
|
276
|
+
nil,
|
277
|
+
false,
|
278
|
+
true
|
279
|
+
)
|
280
|
+
end
|
281
|
+
|
282
|
+
# Populate the block parameter
|
283
|
+
param = parameters.block_param
|
284
|
+
if param
|
285
|
+
add_param_tag(
|
286
|
+
overload_tag,
|
287
|
+
param_tags,
|
288
|
+
param.source,
|
289
|
+
param.file,
|
290
|
+
param.line,
|
291
|
+
nil,
|
292
|
+
nil,
|
293
|
+
false,
|
294
|
+
false,
|
295
|
+
true
|
296
|
+
)
|
297
|
+
end
|
298
|
+
|
299
|
+
# Add a return tag if missing
|
300
|
+
add_return_tag(overload_tag, node.file, node.line)
|
301
|
+
|
302
|
+
# Validate that tags have parameters
|
303
|
+
validate_overload(overload_tag, node.file, node.line)
|
304
|
+
|
305
|
+
object.add_tag overload_tag
|
306
|
+
end
|
307
|
+
|
308
|
+
def add_param_tag(object, tags, name, file, line, type = nil, default = nil, optional = false, repeated = false, block = false)
|
309
|
+
tag = tags.find { |t| t.name == name } if tags
|
310
|
+
log.warn "Missing @param tag for parameter '#{name}' near #{file}:#{line}." unless tag || object.docstring.all.empty?
|
311
|
+
|
312
|
+
if type && tag && tag.types && !tag.types.empty?
|
313
|
+
log.warn "The @param tag for parameter '#{name}' should not contain a " \
|
314
|
+
"type specification near #{file}:#{line}: ignoring in favor of " \
|
315
|
+
'dispatch type information.'
|
316
|
+
end
|
317
|
+
|
318
|
+
if repeated
|
319
|
+
name = "*#{name}"
|
320
|
+
elsif block
|
321
|
+
name = "&#{name}"
|
322
|
+
end
|
323
|
+
|
324
|
+
type ||= tag&.types ? tag.type : 'Any'
|
325
|
+
type = "Optional[#{type}]" if optional
|
326
|
+
|
327
|
+
object.parameters << [name, to_puppet_literal(default)]
|
328
|
+
|
329
|
+
if tag
|
330
|
+
tag.name = name
|
331
|
+
tag.types = [type]
|
332
|
+
else
|
333
|
+
object.add_tag YARD::Tags::Tag.new(:param, '', type, name)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
def add_return_tag(object, file, line)
|
338
|
+
tag = object.tag(:return)
|
339
|
+
if tag
|
340
|
+
tag.types = ['Any'] unless tag.types
|
341
|
+
return
|
342
|
+
end
|
343
|
+
log.warn "Missing @return tag near #{file}:#{line}."
|
344
|
+
object.add_tag YARD::Tags::Tag.new(:return, '', 'Any')
|
345
|
+
end
|
346
|
+
|
347
|
+
def validate_overload(overload, file, line)
|
348
|
+
# Validate that tags have matching parameters
|
349
|
+
overload.tags(:param).each do |tag|
|
350
|
+
next if overload.parameters.find { |p| tag.name == p[0] }
|
351
|
+
|
352
|
+
log.warn "The @param tag for parameter '#{tag.name}' has no matching parameter at #{file}:#{line}."
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
def get_3x_docstring(name)
|
357
|
+
parameters = statement.parameters(false)
|
358
|
+
if parameters.count >= 2
|
359
|
+
parameters[1].each do |kvp|
|
360
|
+
next unless kvp.count == 2
|
361
|
+
next unless node_as_string(kvp[0]) == 'doc'
|
362
|
+
|
363
|
+
docstring = node_as_string(kvp[1])
|
364
|
+
|
365
|
+
log.error "Failed to parse docstring for 3.x Puppet function '#{name}' near #{statement.file}:#{statement.line}." and return nil unless docstring
|
366
|
+
|
367
|
+
return OpenvoxStrings::Yard::Util.scrub_string(docstring)
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
# Log a warning for missing docstring
|
372
|
+
log.warn "Missing documentation for Puppet function '#{name}' at #{statement.file}:#{statement.line}."
|
373
|
+
nil
|
374
|
+
end
|
375
|
+
|
376
|
+
def to_puppet_literal(literal)
|
377
|
+
case literal
|
378
|
+
when 'nil'
|
379
|
+
'undef'
|
380
|
+
when ':default'
|
381
|
+
'default'
|
382
|
+
else
|
383
|
+
literal
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'openvox-strings/yard/handlers/helpers'
|
4
|
+
require 'openvox-strings/yard/handlers/ruby/base'
|
5
|
+
require 'openvox-strings/yard/code_objects'
|
6
|
+
require 'openvox-strings/yard/util'
|
7
|
+
|
8
|
+
# Implements the handler for Puppet providers written in Ruby.
|
9
|
+
class OpenvoxStrings::Yard::Handlers::Ruby::ProviderHandler < OpenvoxStrings::Yard::Handlers::Ruby::Base
|
10
|
+
namespace_only
|
11
|
+
handles method_call(:provide)
|
12
|
+
|
13
|
+
process do
|
14
|
+
return unless statement.count >= 2
|
15
|
+
|
16
|
+
# Check that provide is being called on Puppet::Type.type(<name>)
|
17
|
+
type_call = statement[0]
|
18
|
+
return unless type_call.is_a?(YARD::Parser::Ruby::MethodCallNode) && type_call.count >= 3
|
19
|
+
return unless type_call[0].source == 'Puppet::Type'
|
20
|
+
return unless type_call[2].source == 'type'
|
21
|
+
|
22
|
+
# Extract the type name
|
23
|
+
type_call_parameters = type_call.parameters(false)
|
24
|
+
return unless type_call_parameters.count >= 1
|
25
|
+
|
26
|
+
type_name = node_as_string(type_call_parameters.first)
|
27
|
+
raise YARD::Parser::UndocumentableError, "Could not determine the resource type name for the provider defined at #{statement.file}:#{statement.line}." unless type_name
|
28
|
+
|
29
|
+
# Register the object
|
30
|
+
object = OpenvoxStrings::Yard::CodeObjects::Provider.new(type_name, get_name(statement, "'provide'"))
|
31
|
+
register object
|
32
|
+
|
33
|
+
# Extract the docstring
|
34
|
+
register_provider_docstring object
|
35
|
+
|
36
|
+
# Populate the provider data
|
37
|
+
populate_provider_data object
|
38
|
+
|
39
|
+
# Mark the provider as public if it doesn't already have an api tag
|
40
|
+
object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api
|
41
|
+
|
42
|
+
# Warn if a summary longer than 140 characters was provided
|
43
|
+
OpenvoxStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def register_provider_docstring(object)
|
49
|
+
# Walk the tree searching for assignments or calls to desc/doc=
|
50
|
+
statement.traverse do |child|
|
51
|
+
if child.type == :assign
|
52
|
+
ivar = child.jump(:ivar)
|
53
|
+
next unless ivar != child && ivar.source == '@doc'
|
54
|
+
|
55
|
+
docstring = node_as_string(child[1])
|
56
|
+
log.error "Failed to parse docstring for Puppet provider '#{object.name}' (resource type '#{object.type_name}') near #{child.file}:#{child.line}." and return nil unless docstring
|
57
|
+
|
58
|
+
register_docstring(object, OpenvoxStrings::Yard::Util.scrub_string(docstring), nil)
|
59
|
+
return nil
|
60
|
+
elsif child.is_a?(YARD::Parser::Ruby::MethodCallNode)
|
61
|
+
# Look for a call to a dispatch method with a block
|
62
|
+
next unless
|
63
|
+
child.method_name &&
|
64
|
+
['desc', 'doc='].include?(child.method_name.source) &&
|
65
|
+
child.parameters(false).count == 1
|
66
|
+
|
67
|
+
docstring = node_as_string(child.parameters[0])
|
68
|
+
log.error "Failed to parse docstring for Puppet provider '#{object.name}' (resource type '#{object.type_name}') near #{child.file}:#{child.line}." and return nil unless docstring
|
69
|
+
|
70
|
+
register_docstring(object, OpenvoxStrings::Yard::Util.scrub_string(docstring), nil)
|
71
|
+
return nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
log.warn "Missing a description for Puppet provider '#{object.name}' (resource type '#{object.type_name}') at #{statement.file}:#{statement.line}."
|
75
|
+
end
|
76
|
+
|
77
|
+
def populate_provider_data(object)
|
78
|
+
# Traverse the block looking for confines/defaults/commands
|
79
|
+
block = statement.block
|
80
|
+
return unless block && block.count >= 2
|
81
|
+
|
82
|
+
block[1].children.each do |node|
|
83
|
+
next unless node.is_a?(YARD::Parser::Ruby::MethodCallNode) && node.method_name
|
84
|
+
|
85
|
+
method_name = node.method_name.source
|
86
|
+
parameters = node.parameters(false)
|
87
|
+
|
88
|
+
if method_name == 'confine'
|
89
|
+
# Add a confine to the object
|
90
|
+
next unless parameters.count >= 1
|
91
|
+
|
92
|
+
parameters[0].each do |kvp|
|
93
|
+
next unless kvp.count == 2
|
94
|
+
|
95
|
+
object.add_confine(node_as_string(kvp[0]) || kvp[0].source, node_as_string(kvp[1]) || kvp[1].source)
|
96
|
+
end
|
97
|
+
elsif %w[has_feature has_features].include?(method_name)
|
98
|
+
# Add the features to the object
|
99
|
+
parameters.each do |parameter|
|
100
|
+
object.add_feature(node_as_string(parameter) || parameter.source)
|
101
|
+
end
|
102
|
+
elsif method_name == 'defaultfor'
|
103
|
+
# Add a default to the object
|
104
|
+
next unless parameters.count >= 1
|
105
|
+
|
106
|
+
# Some defaultfor statements contain multiple constraints.
|
107
|
+
parameters.each do |kvps|
|
108
|
+
next unless kvps.count >= 1
|
109
|
+
|
110
|
+
defaultfor = kvps.map do |kvp|
|
111
|
+
[node_as_string(kvp[0]) || kvp[0].source, node_as_string(kvp[1]) || kvp[1].source]
|
112
|
+
end
|
113
|
+
object.add_default(defaultfor)
|
114
|
+
end
|
115
|
+
elsif method_name == 'commands'
|
116
|
+
# Add the commands to the object
|
117
|
+
next unless parameters.count >= 1
|
118
|
+
|
119
|
+
parameters[0].each do |kvp|
|
120
|
+
next unless kvp.count == 2
|
121
|
+
|
122
|
+
object.add_command(node_as_string(kvp[0]) || kvp[0].source, node_as_string(kvp[1]) || kvp[1].source)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'openvox-strings/yard/handlers/helpers'
|
4
|
+
require 'openvox-strings/yard/handlers/ruby/base'
|
5
|
+
require 'openvox-strings/yard/code_objects'
|
6
|
+
require 'openvox-strings/yard/util'
|
7
|
+
|
8
|
+
# Implements the handler for Puppet resource types written in Ruby.
|
9
|
+
class OpenvoxStrings::Yard::Handlers::Ruby::RsapiHandler < OpenvoxStrings::Yard::Handlers::Ruby::Base
|
10
|
+
# The default docstring when ensurable is used without given a docstring.
|
11
|
+
DEFAULT_ENSURABLE_DOCSTRING = 'The basic property that the resource should be in.'
|
12
|
+
|
13
|
+
namespace_only
|
14
|
+
handles method_call(:register_type)
|
15
|
+
|
16
|
+
process do
|
17
|
+
# Only accept calls to Puppet::ResourceApi
|
18
|
+
return unless statement.count > 1
|
19
|
+
|
20
|
+
module_name = statement[0].source
|
21
|
+
return unless ['Puppet::ResourceApi'].include? module_name
|
22
|
+
|
23
|
+
schema = extract_schema
|
24
|
+
|
25
|
+
# puts "Schema: #{schema.inspect}"
|
26
|
+
|
27
|
+
object = OpenvoxStrings::Yard::CodeObjects::Type.new(schema['name'])
|
28
|
+
register object
|
29
|
+
|
30
|
+
docstring = schema['docs']
|
31
|
+
if docstring
|
32
|
+
register_docstring(object, OpenvoxStrings::Yard::Util.scrub_string(docstring.to_s), nil)
|
33
|
+
else
|
34
|
+
log.warn "Missing a description for Puppet resource type '#{object.name}' at #{statement.file}:#{statement.line}."
|
35
|
+
end
|
36
|
+
|
37
|
+
# Populate the parameters/properties/features to the type
|
38
|
+
populate_type_data(object, schema)
|
39
|
+
|
40
|
+
# Mark the type as public if it doesn't already have an api tag
|
41
|
+
object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api
|
42
|
+
|
43
|
+
# Warn if a summary longer than 140 characters was provided
|
44
|
+
OpenvoxStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def raise_parse_error(msg, location = statement)
|
50
|
+
raise YARD::Parser::UndocumentableError, "#{msg} at #{location.file}:#{location.line}."
|
51
|
+
end
|
52
|
+
|
53
|
+
# check that the params of the register_type call are key/value pairs.
|
54
|
+
def kv_arg_list?(params)
|
55
|
+
params.type == :list &&
|
56
|
+
params.children.count.positive? &&
|
57
|
+
params.children.first.type == :list &&
|
58
|
+
params.children.first.children.count.positive? &&
|
59
|
+
statement.parameters.children.first.children.first.type == :assoc
|
60
|
+
end
|
61
|
+
|
62
|
+
def extract_schema
|
63
|
+
raise_parse_error('Expected list of key/value pairs as argument') unless kv_arg_list?(statement.parameters)
|
64
|
+
hash_from_node(statement.parameters.children.first)
|
65
|
+
end
|
66
|
+
|
67
|
+
def value_from_node(node)
|
68
|
+
return nil unless node
|
69
|
+
|
70
|
+
# puts "value from #{node.inspect}"
|
71
|
+
|
72
|
+
case node.type
|
73
|
+
when :int
|
74
|
+
node.source.to_i
|
75
|
+
when :hash
|
76
|
+
hash_from_node(node)
|
77
|
+
when :array
|
78
|
+
array_from_node(node)
|
79
|
+
when :var_ref
|
80
|
+
var_ref_from_node(node)
|
81
|
+
when :symbol, :symbol_literal, :label, :dyna_symbol, :string_literal, :regexp_literal
|
82
|
+
node_as_string(node)
|
83
|
+
else
|
84
|
+
raise_parse_error("unexpected construct #{node.type}")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def array_from_node(node)
|
89
|
+
return nil unless node
|
90
|
+
|
91
|
+
node.children.map do |assoc|
|
92
|
+
value_from_node(assoc.children[0])
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def hash_from_node(node)
|
97
|
+
return nil unless node
|
98
|
+
|
99
|
+
# puts "hash from #{node.inspect}"
|
100
|
+
|
101
|
+
kv_pairs = node.children.map do |assoc|
|
102
|
+
[value_from_node(assoc.children[0]), value_from_node(assoc.children[1])]
|
103
|
+
end
|
104
|
+
kv_pairs.to_h
|
105
|
+
end
|
106
|
+
|
107
|
+
def var_ref_from_node(node)
|
108
|
+
return nil unless node
|
109
|
+
|
110
|
+
# puts "var_ref from #{node.inspect}"
|
111
|
+
|
112
|
+
if node.children.first.type == :kw
|
113
|
+
case node.children.first.source
|
114
|
+
when 'false'
|
115
|
+
return false
|
116
|
+
when 'true'
|
117
|
+
return true
|
118
|
+
when 'nil'
|
119
|
+
return nil
|
120
|
+
else
|
121
|
+
raise_parse_error("unexpected keyword '#{node.children.first.source}'")
|
122
|
+
end
|
123
|
+
end
|
124
|
+
raise_parse_error('unexpected variable')
|
125
|
+
end
|
126
|
+
|
127
|
+
def populate_type_data(object, schema)
|
128
|
+
return if schema['attributes'].nil?
|
129
|
+
|
130
|
+
schema['attributes'].each do |name, definition|
|
131
|
+
# puts "Processing #{name}: #{definition.inspect}"
|
132
|
+
if %w[parameter namevar].include? definition['behaviour']
|
133
|
+
object.add_parameter(create_parameter(name, definition))
|
134
|
+
else
|
135
|
+
object.add_property(create_property(name, definition))
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def create_parameter(name, definition)
|
141
|
+
parameter = OpenvoxStrings::Yard::CodeObjects::Type::Parameter.new(name, definition['desc'])
|
142
|
+
set_values(definition, parameter)
|
143
|
+
parameter
|
144
|
+
end
|
145
|
+
|
146
|
+
def create_property(name, definition)
|
147
|
+
property = OpenvoxStrings::Yard::CodeObjects::Type::Property.new(name, definition['desc'])
|
148
|
+
set_values(definition, property)
|
149
|
+
property
|
150
|
+
end
|
151
|
+
|
152
|
+
def set_values(definition, object)
|
153
|
+
object.data_type = definition['type'] if definition.key? 'type'
|
154
|
+
object.default = definition['default'] if definition.key? 'default'
|
155
|
+
object.isnamevar = definition.key?('behaviour') && definition['behaviour'] == 'namevar'
|
156
|
+
end
|
157
|
+
end
|