puppet-strings 2.4.0 → 2.5.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.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -2
  3. data/lib/puppet-strings.rb +2 -2
  4. data/lib/puppet-strings/markdown.rb +1 -1
  5. data/lib/puppet-strings/markdown/base.rb +6 -0
  6. data/lib/puppet-strings/markdown/data_type.rb +16 -0
  7. data/lib/puppet-strings/markdown/resource_type.rb +19 -2
  8. data/lib/puppet-strings/markdown/templates/classes_and_defines.erb +4 -4
  9. data/lib/puppet-strings/markdown/templates/data_type.erb +11 -4
  10. data/lib/puppet-strings/markdown/templates/data_type_function.erb +67 -0
  11. data/lib/puppet-strings/markdown/templates/function.erb +2 -1
  12. data/lib/puppet-strings/markdown/templates/puppet_task.erb +1 -1
  13. data/lib/puppet-strings/markdown/templates/resource_type.erb +12 -12
  14. data/lib/puppet-strings/markdown/templates/table_of_contents.erb +6 -6
  15. data/lib/puppet-strings/version.rb +1 -1
  16. data/lib/puppet-strings/yard/code_objects/data_type.rb +26 -6
  17. data/lib/puppet-strings/yard/code_objects/type.rb +46 -5
  18. data/lib/puppet-strings/yard/handlers/ruby/data_type_handler.rb +190 -43
  19. data/lib/puppet-strings/yard/handlers/ruby/type_base.rb +6 -0
  20. data/lib/puppet-strings/yard/handlers/ruby/type_extras_handler.rb +1 -1
  21. data/lib/puppet-strings/yard/handlers/ruby/type_handler.rb +6 -0
  22. data/lib/puppet-strings/yard/templates/default/puppet_data_type/html/method_details_list.erb +6 -0
  23. data/lib/puppet-strings/yard/templates/default/puppet_data_type/html/setup.rb +9 -1
  24. data/lib/puppet-strings/yard/templates/default/puppet_type/html/setup.rb +3 -1
  25. metadata +4 -46
  26. data/CODEOWNERS +0 -1
  27. data/Gemfile +0 -53
  28. data/HISTORY.md +0 -218
  29. data/JSON.md +0 -832
  30. data/Rakefile +0 -160
  31. data/codecov.yml +0 -3
  32. data/misc/ANNOUNCEMENT_TEMPLATE.md +0 -40
  33. data/spec/acceptance/emit_json_options_spec.rb +0 -69
  34. data/spec/acceptance/generate_markdown_spec.rb +0 -47
  35. data/spec/acceptance/running_strings_generate_spec.rb +0 -88
  36. data/spec/fixtures/acceptance/modules/test/functions/add.pp +0 -9
  37. data/spec/fixtures/acceptance/modules/test/lib/puppet/functions/4x_function.rb +0 -5
  38. data/spec/fixtures/acceptance/modules/test/lib/puppet/parser/functions/function3x.rb +0 -2
  39. data/spec/fixtures/acceptance/modules/test/lib/puppet/provider/server/linux.rb +0 -9
  40. data/spec/fixtures/acceptance/modules/test/lib/puppet/type/database.rb +0 -15
  41. data/spec/fixtures/acceptance/modules/test/manifests/init.pp +0 -31
  42. data/spec/fixtures/acceptance/modules/test/manifests/triple_nested_classes.pp +0 -27
  43. data/spec/fixtures/acceptance/modules/test/metadata.json +0 -10
  44. data/spec/fixtures/acceptance/modules/test/types/elephant.pp +0 -2
  45. data/spec/fixtures/unit/markdown/output.md +0 -561
  46. data/spec/fixtures/unit/markdown/output_with_data_types.md +0 -606
  47. data/spec/fixtures/unit/markdown/output_with_plan.md +0 -595
  48. data/spec/spec_helper.rb +0 -49
  49. data/spec/spec_helper_acceptance.rb +0 -58
  50. data/spec/spec_helper_acceptance_local.rb +0 -10
  51. data/spec/unit/puppet-strings/describe_spec.rb +0 -141
  52. data/spec/unit/puppet-strings/json_spec.rb +0 -302
  53. data/spec/unit/puppet-strings/markdown/base_spec.rb +0 -146
  54. data/spec/unit/puppet-strings/markdown_spec.rb +0 -374
  55. data/spec/unit/puppet-strings/yard/code_objects/task_spec.rb +0 -92
  56. data/spec/unit/puppet-strings/yard/handlers/json/task_handler_spec.rb +0 -116
  57. data/spec/unit/puppet-strings/yard/handlers/puppet/class_handler_spec.rb +0 -217
  58. data/spec/unit/puppet-strings/yard/handlers/puppet/data_type_alias_handler_spec.rb +0 -65
  59. data/spec/unit/puppet-strings/yard/handlers/puppet/defined_type_handler_spec.rb +0 -231
  60. data/spec/unit/puppet-strings/yard/handlers/puppet/function_handler_spec.rb +0 -315
  61. data/spec/unit/puppet-strings/yard/handlers/ruby/data_type_handler_spec.rb +0 -309
  62. data/spec/unit/puppet-strings/yard/handlers/ruby/function_handler_spec.rb +0 -746
  63. data/spec/unit/puppet-strings/yard/handlers/ruby/provider_handler_spec.rb +0 -158
  64. data/spec/unit/puppet-strings/yard/handlers/ruby/rsapi_handler_spec.rb +0 -235
  65. data/spec/unit/puppet-strings/yard/handlers/ruby/type_handler_spec.rb +0 -311
  66. data/spec/unit/puppet-strings/yard/parsers/json/parser_spec.rb +0 -72
  67. data/spec/unit/puppet-strings/yard/parsers/json/task_statement_spec.rb +0 -56
  68. data/spec/unit/puppet-strings/yard/parsers/puppet/parser_spec.rb +0 -251
  69. data/spec/unit/puppet-strings/yard/util_spec.rb +0 -48
@@ -24,7 +24,6 @@ class PuppetStrings::Yard::CodeObjects::DataType < PuppetStrings::Yard::CodeObje
24
24
  # @return [void]
25
25
  def initialize(name)
26
26
  super(PuppetStrings::Yard::CodeObjects::DataTypes.instance, name)
27
- @parameters = []
28
27
  @defaults = {}
29
28
  end
30
29
 
@@ -41,10 +40,6 @@ class PuppetStrings::Yard::CodeObjects::DataType < PuppetStrings::Yard::CodeObje
41
40
  nil
42
41
  end
43
42
 
44
- def parameter_exist?(name)
45
- !docstring.tags(:param).find { |item| item.name == name }.nil?
46
- end
47
-
48
43
  def add_parameter(name, type, default)
49
44
  tag = docstring.tags(:param).find { |item| item.name == name }
50
45
  if tag.nil?
@@ -65,6 +60,24 @@ class PuppetStrings::Yard::CodeObjects::DataType < PuppetStrings::Yard::CodeObje
65
60
  docstring.tags(:param).map { |tag| [tag.name, defaults[tag.name]] }
66
61
  end
67
62
 
63
+ def add_function(name, return_type, parameter_types)
64
+ meth_obj = YARD::CodeObjects::MethodObject.new(self, name, :class)
65
+
66
+ # Add return tag
67
+ meth_obj.add_tag(YARD::Tags::Tag.new(:return, '', return_type))
68
+
69
+ # Add parameters
70
+ parameter_types.each_with_index do |param_type, index|
71
+ meth_obj.add_tag(YARD::Tags::Tag.new(:param, '', [param_type], "param#{index + 1}"))
72
+ end
73
+
74
+ self.meths << meth_obj
75
+ end
76
+
77
+ def functions
78
+ meths
79
+ end
80
+
68
81
  # Converts the code object to a hash representation.
69
82
  # @return [Hash] Returns a hash representation of the code object.
70
83
  def to_hash
@@ -72,9 +85,16 @@ class PuppetStrings::Yard::CodeObjects::DataType < PuppetStrings::Yard::CodeObje
72
85
  hash[:name] = name
73
86
  hash[:file] = file
74
87
  hash[:line] = line
75
- hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring)
88
+ hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring, %i[param option enum return example])
76
89
  hash[:defaults] = defaults unless defaults.empty?
77
90
  hash[:source] = source unless source && source.empty?
91
+ hash[:functions] = functions.map do |func|
92
+ {
93
+ name: func.name,
94
+ signature: func.signature,
95
+ docstring: PuppetStrings::Yard::Util.docstring_to_hash(func.docstring, %i[param option enum return example])
96
+ }
97
+ end
78
98
  hash
79
99
  end
80
100
  end
@@ -73,6 +73,9 @@ class PuppetStrings::Yard::CodeObjects::Type < PuppetStrings::Yard::CodeObjects:
73
73
  class Property < Parameter
74
74
  end
75
75
 
76
+ class Check < Parameter
77
+ end
78
+
76
79
  # Represents a resource type feature.
77
80
  class Feature
78
81
  attr_reader :name, :docstring
@@ -95,7 +98,7 @@ class PuppetStrings::Yard::CodeObjects::Type < PuppetStrings::Yard::CodeObjects:
95
98
  end
96
99
  end
97
100
 
98
- attr_reader :properties, :parameters, :features
101
+ attr_reader :properties, :features, :checks
99
102
 
100
103
  # Initializes a new resource type.
101
104
  # @param [String] name The resource type name.
@@ -134,17 +137,55 @@ class PuppetStrings::Yard::CodeObjects::Type < PuppetStrings::Yard::CodeObjects:
134
137
  @features << feature
135
138
  end
136
139
 
140
+ # Adds a check to the resource type.
141
+ # @param [PuppetStrings::Yard::CodeObjects::Type::Check] check The check to add.
142
+ # @return [void]
143
+ def add_check(check)
144
+ @checks ||= []
145
+ @checks << check
146
+ end
147
+
148
+ def parameters
149
+ # just return params if there are no providers
150
+ return @parameters if providers.empty?
151
+
152
+ # return existing params if we have already added provider
153
+ return @parameters if @parameters.any? { |p| p.name == 'provider' }
154
+
155
+ provider_param = Parameter.new(
156
+ 'provider',
157
+ "The specific backend to use for this `#{self.name.to_s}` resource. You will seldom need " + \
158
+ "to specify this --- Puppet will usually discover the appropriate provider for your platform."
159
+ )
160
+
161
+ @parameters << provider_param
162
+ end
163
+
164
+ # Not sure if this is where this belongs or if providers should only be resolved at
165
+ # render-time. For now, this should re-resolve on every call.
166
+ # may be able to memoize this
167
+ def providers
168
+ providers = YARD::Registry.all("puppet_providers_#{name}".intern)
169
+ return providers if providers.empty?
170
+ providers.first.children
171
+ end
172
+
137
173
  # Converts the code object to a hash representation.
138
174
  # @return [Hash] Returns a hash representation of the code object.
139
175
  def to_hash
140
176
  hash = {}
177
+
141
178
  hash[:name] = name
142
179
  hash[:file] = file
143
180
  hash[:line] = line
144
- hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring)
145
- hash[:properties] = properties.map(&:to_hash) if properties && !properties.empty?
146
- hash[:parameters] = parameters.map(&:to_hash) if parameters && !parameters.empty?
147
- hash[:features] = features.map(&:to_hash) if features && !features.empty?
181
+
182
+ hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring)
183
+ hash[:properties] = properties.sort_by { |p| p.name }.map(&:to_hash) if properties && !properties.empty?
184
+ hash[:parameters] = parameters.sort_by { |p| p.name }.map(&:to_hash) if parameters && !parameters.empty?
185
+ hash[:checks] = checks.sort_by { |c| c.name }.map(&:to_hash) if checks && !checks.empty?
186
+ hash[:features] = features.sort_by { |f| f.name }.map(&:to_hash) if features && !features.empty?
187
+ hash[:providers] = providers.sort_by { |p| p.name }.map(&:to_hash) if providers && !providers.empty?
188
+
148
189
  hash
149
190
  end
150
191
  end
@@ -13,13 +13,16 @@ class PuppetStrings::Yard::Handlers::Ruby::DataTypeHandler < PuppetStrings::Yard
13
13
  ruby_module_name = statement[0].source
14
14
  return unless ruby_module_name == 'Puppet::DataTypes' || ruby_module_name == 'DataTypes' # rubocop:disable Style/MultipleComparison This reads better
15
15
  object = get_datatype_yard_object(get_name(statement, 'Puppet::DataTypes.create_type'))
16
-
17
- actual_params = extract_params_for_data_type
16
+ # Extract the interface definition
17
+ type_interface = extract_data_type_interface
18
+ actual_params = extract_params(type_interface)
19
+ actual_funcs = extract_functions(object, type_interface)
18
20
 
19
21
  # Mark the data type as public if it doesn't already have an api tag
20
22
  object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api
21
23
 
22
- validate_tags!(object, actual_params)
24
+ validate_param_tags!(object, actual_params)
25
+ validate_methods!(object, actual_funcs)
23
26
 
24
27
  # Set the default values for all parameters
25
28
  actual_params.each { |name, data| object.set_parameter_default(name, data[:default]) }
@@ -49,44 +52,60 @@ class PuppetStrings::Yard::Handlers::Ruby::DataTypeHandler < PuppetStrings::Yard
49
52
  object
50
53
  end
51
54
 
52
- def extract_params_for_data_type
53
- params = {}
54
- # Traverse the block looking for interface
55
+ # @return [Hash{Object => Object}] The Puppet DataType interface definition as a ruby Hash
56
+ def extract_data_type_interface
55
57
  block = statement.block
56
- return unless block && block.count >= 2
57
- block[1].children.each do |node|
58
- next unless node.is_a?(YARD::Parser::Ruby::MethodCallNode) &&
59
- node.method_name
58
+ return {} unless block
59
+
60
+ # Declare the parsed interface outside of the closure
61
+ parsed_interface = nil
60
62
 
61
- method_name = node.method_name.source
63
+ # Recursively traverse the block looking for the first valid 'interface' call
64
+ interface_node = find_ruby_ast_node(block, true) do |node|
65
+ next false unless node.is_a?(YARD::Parser::Ruby::MethodCallNode) &&
66
+ node.method_name &&
67
+ node.method_name.source == 'interface'
62
68
  parameters = node.parameters(false)
63
- if method_name == 'interface'
64
- next unless parameters.count >= 1
65
- interface_string = node_as_string(parameters[0])
66
- next unless interface_string
69
+ next false unless parameters.count >= 1
70
+ interface_string = node_as_string(parameters[0])
71
+ next false unless interface_string
72
+
73
+ begin
67
74
  # Ref - https://github.com/puppetlabs/puppet/blob/ba4d1a1aba0095d3c70b98fea5c67434a4876a61/lib/puppet/datatypes.rb#L159
68
- parsed_interface = nil
69
- begin
70
- parsed_interface = Puppet::Pops::Parser::EvaluatingParser.new.parse_string("{ #{interface_string} }").body
71
- rescue Puppet::Error => e
72
- log.warn "Invalid datatype definition at #{statement.file}:#{statement.line}: #{e.basic_message}"
73
- next
74
- end
75
- next unless parsed_interface
76
-
77
- # Now that we parsed the Puppet code (as a string) into a LiteralHash PCore type (Puppet AST),
78
- #
79
- # We need to convert the LiteralHash into a conventional ruby hash of strings. The
80
- # LazyLiteralEvaluator does this by traversing the AST tree can converting objects to strings
81
- # where possible and ignoring object types which cannot (thus the 'Lazy' name)
82
- #
83
- # Once we have it as a standard ruby hash we can then look at the keys and populate the YARD
84
- # Code object with the correct attributes etc.
85
- literal_eval = LazyLiteralEvaluator.new
86
- populate_data_type_params_from_literal_hash!(literal_eval.literal(parsed_interface), params)
75
+ parsed_interface = Puppet::Pops::Parser::EvaluatingParser.new.parse_string("{ #{interface_string} }").body
76
+ rescue Puppet::Error => e
77
+ log.warn "Invalid datatype definition at #{statement.file}:#{statement.line}: #{e.basic_message}"
78
+ next false
79
+ end
80
+ !parsed_interface.nil?
81
+ end
82
+
83
+ # Now that we parsed the Puppet code (as a string) into a LiteralHash PCore type (Puppet AST),
84
+ # We need to convert the LiteralHash into a conventional ruby hash of strings. The
85
+ # LazyLiteralEvaluator does this by traversing the AST tree can converting objects to strings
86
+ # where possible and ignoring object types which cannot (thus the 'Lazy' name)
87
+ literal_eval = LazyLiteralEvaluator.new
88
+ literal_eval.literal(parsed_interface)
89
+ end
90
+
91
+ # Find the first Ruby AST node within an AST Tree, optionally recursively. Returns nil of none could be found
92
+ #
93
+ # @param [YARD::Parser::Ruby::AstNode] ast_node The root AST node object to inspect
94
+ # @param [Boolean] recurse Whether to search the tree recursively. Defaults to false
95
+ # @yieldparam [YARD::Parser::Ruby::AstNode] ast_node The AST Node that should be checked
96
+ # @yieldreturn [Boolean] Whether the node was what was searched for
97
+ # @return [YARD::Parser::Ruby::AstNode, nil]
98
+ def find_ruby_ast_node(ast_node, recurse = false, &block)
99
+ raise ArgumentError, 'find_ruby_ast_node requires a block' unless block_given?
100
+ is_found = yield ast_node
101
+ return ast_node if is_found
102
+ if ast_node.respond_to?(:children)
103
+ ast_node.children.each do |child_node|
104
+ child_found = find_ruby_ast_node(child_node, recurse, &block)
105
+ return child_found unless child_found.nil?
87
106
  end
88
107
  end
89
- params
108
+ nil
90
109
  end
91
110
 
92
111
  # Lazily evaluates a Pops object, ignoring any objects that cannot
@@ -179,7 +198,7 @@ class PuppetStrings::Yard::Handlers::Ruby::DataTypeHandler < PuppetStrings::Yard
179
198
  end
180
199
 
181
200
  def literal_LiteralList(o) # rubocop:disable Naming/UncommunicativeMethodParamName
182
- o.values.map {|v| literal(v) }
201
+ o.values.map { |v| literal(v) }
183
202
  end
184
203
 
185
204
  def literal_LiteralHash(o) # rubocop:disable Naming/UncommunicativeMethodParamName
@@ -190,27 +209,58 @@ class PuppetStrings::Yard::Handlers::Ruby::DataTypeHandler < PuppetStrings::Yard
190
209
  end
191
210
  end
192
211
 
193
- def populate_data_type_params_from_literal_hash!(hash, params_hash)
194
- return if hash.nil?
212
+ # Extracts the datatype attributes from a Puppet Data Type interface hash.
213
+ # Returns a Hash with a :types key (Array of data types for the parameter) and :default key (The default value of the parameter)
214
+ # @return Hash[Symbol => Hash] The Datatype Attributes as a hash
215
+ def extract_params(hash)
216
+ params_hash = {}
195
217
  # Exit early if there are no entries in the hash
196
- return if hash['attributes'].nil? || hash['attributes'].count.zero?
218
+ return params_hash if hash.nil? || hash['attributes'].nil? || hash['attributes'].empty?
197
219
 
198
220
  hash['attributes'].each do |key, value|
199
221
  data_type = nil
200
222
  default = nil
201
- case value
202
- when String
223
+ if value.is_a?(String)
203
224
  data_type = value
204
- when Hash
225
+ elsif value.is_a?(Hash)
205
226
  data_type = value['type'] unless value['type'].nil?
206
227
  default = value['value'] unless value['value'].nil?
207
228
  end
208
229
  data_type = [data_type] unless data_type.nil? || data_type.is_a?(Array)
209
230
  params_hash[key] = { :types => data_type, :default => default }
210
231
  end
232
+
233
+ params_hash
211
234
  end
212
235
 
213
- def validate_tags!(object, actual_params_hash)
236
+ # Extracts the datatype functions from a Puppet Data Type interface hash.
237
+ # Returns a Hash with a :param_types key (Array of types for each parameter) and :return_type key (The return type of the function)
238
+ # @return Hash[Symbol => Hash] The Datatype Attributes as a hash
239
+ def extract_functions(object, hash)
240
+ funcs_hash = {}
241
+ # Exit early if there are no entries in the hash
242
+ return funcs_hash if hash.nil? || hash['functions'].nil? || hash['functions'].empty?
243
+
244
+ hash['functions'].each do |key, func_type|
245
+ func_hash = { :param_types => [], :return_type => nil }
246
+ begin
247
+ callable_type = Puppet::Pops::Types::TypeParser.singleton.parse(func_type)
248
+ if callable_type.is_a?(Puppet::Pops::Types::PCallableType)
249
+ func_hash[:param_types] = callable_type.param_types.map { |pt| pt.to_s }
250
+ func_hash[:return_type] = callable_type.return_type.to_s
251
+ else
252
+ log.warn "The function definition for '#{key}' near #{object.file}:#{object.line} is not a Callable type"
253
+ end
254
+ rescue Puppet::ParseError => e
255
+ log.warn "Unable to parse the function definition for '#{key}' near #{object.file}:#{object.line}. #{e}"
256
+ end
257
+ funcs_hash[key] = func_hash
258
+ end
259
+ funcs_hash
260
+ end
261
+
262
+ # Validates and automatically fixes yard @param tags for the data type
263
+ def validate_param_tags!(object, actual_params_hash)
214
264
  actual_param_names = actual_params_hash.keys
215
265
  tagged_param_names = object.tags(:param).map(&:name)
216
266
  # Log any errors
@@ -243,4 +293,101 @@ class PuppetStrings::Yard::Handlers::Ruby::DataTypeHandler < PuppetStrings::Yard
243
293
  tag.types = actual_params_hash[tag.name][:types]
244
294
  end
245
295
  end
296
+
297
+ # Validates and automatically fixes yard @method! tags for the data type
298
+ def validate_methods!(object, actual_functions_hash)
299
+ actual_func_names = actual_functions_hash.keys
300
+ tagged_func_names = object.meths.map { |meth| meth.name.to_s }
301
+
302
+ # Log any errors
303
+ # Find functions which are not documented
304
+ (actual_func_names - tagged_func_names).each do |item|
305
+ log.warn "Missing @!method tag for function '#{item}' near #{object.file}:#{object.line}."
306
+ end
307
+ # Find functions which are not defined
308
+ (tagged_func_names - actual_func_names).each do |item|
309
+ log.warn "The @!method tag for '#{item}' has no matching function definition near #{object.file}:#{object.line}."
310
+ end
311
+ # Functions with the wrong return type
312
+ object.meths.each do |meth|
313
+ next unless actual_func_names.include?(meth.name.to_s)
314
+ return_tag = meth.docstring.tag(:return)
315
+ next if return_tag.nil?
316
+ actual_return_types = [actual_functions_hash[meth.name.to_s][:return_type]]
317
+ next if return_tag.types == actual_return_types
318
+ log.warn "The @return tag for '#{meth.name}' has a different type definition than the actual function near #{object.file}:#{object.line}. Expected #{actual_return_types}"
319
+ return_tag.types = actual_return_types
320
+ end
321
+
322
+ # Automatically fix missing methods
323
+ (actual_func_names - tagged_func_names).each do |name|
324
+ object.add_function(name, actual_functions_hash[name][:return_type], actual_functions_hash[name][:param_types])
325
+ end
326
+ # Remove extra methods. Can't use `meths` as that's a derived property
327
+ object.children.reject! { |child| child.is_a?(YARD::CodeObjects::MethodObject) && !actual_func_names.include?(child.name.to_s) }
328
+
329
+ # Add the return type for the methods if missing
330
+ object.meths.each do |meth|
331
+ next unless meth.docstring.tag(:return).nil?
332
+ meth.docstring.add_tag(YARD::Tags::Tag.new(:return, '', actual_functions_hash[meth.name.to_s][:return_type]))
333
+ end
334
+
335
+ # Sync the method properties and add the return type for the methods if missing
336
+ object.meths.each do |meth|
337
+ validate_function_method!(object, meth, actual_functions_hash[meth.name.to_s])
338
+ next unless meth.docstring.tag(:return).nil?
339
+ meth.docstring.add_tag(YARD::Tags::Tag.new(:return, '', actual_functions_hash[meth.name.to_s][:return_type]))
340
+ end
341
+
342
+ # The default meth.signature assumes ruby invocation (e.g. def meth(...)) but this doesn't make sense for a
343
+ # Puppet Data Type function invocation. So instead we derive a signature from the method definition.
344
+ object.meths.each do |meth|
345
+ params = ''
346
+ unless meth.docstring.tags(:param).empty?
347
+ params += '(' + meth.docstring.tags(:param).map { |t| t.name }.join(', ') + ')'
348
+ end
349
+ meth.signature = "#{object.name}.#{meth.name}" + params
350
+ end
351
+
352
+ nil
353
+ end
354
+
355
+ # Validates and automatically fixes a single yard @method!
356
+ # Used by the validate_methods! method.
357
+ def validate_function_method!(object, meth, actual_function)
358
+ # Remove extra params
359
+ if meth.docstring.tags(:param).count > actual_function[:param_types].count
360
+ index = 0
361
+ meth.docstring.delete_tag_if do |tag|
362
+ if tag.tag_name == 'param'
363
+ index += 1
364
+ if index > actual_function[:param_types].count
365
+ log.warn "The @param tag for '#{tag.name}' should not exist for function '#{meth.name}' that is defined near #{object.file}:#{object.line}. Expected only #{actual_function[:param_types].count} parameter/s"
366
+ true
367
+ else
368
+ false
369
+ end
370
+ else
371
+ false
372
+ end
373
+ end
374
+ end
375
+
376
+ # Add missing params
377
+ if meth.docstring.tags(:param).count < actual_function[:param_types].count
378
+ start = meth.docstring.tags(:param).count + 1
379
+ (start..actual_function[:param_types].count).each do |index| # Using 1-based index here instead of usual zero
380
+ meth.add_tag(YARD::Tags::Tag.new(:param, '', actual_function[:param_types][index - 1], "param#{index}"))
381
+ end
382
+ end
383
+
384
+ # Ensure the parameter types are correct
385
+ meth.docstring.tags(:param).each_with_index do |tag, index|
386
+ actual_types = [actual_function[:param_types][index]]
387
+ if tag.types != actual_types
388
+ log.warn "The @param tag for '#{tag.name}' for function '#{meth.name}' has a different type definition than the actual function near #{object.file}:#{object.line}. Expected #{actual_types}"
389
+ tag.types = actual_types
390
+ end
391
+ end
392
+ end
246
393
  end
@@ -52,6 +52,12 @@ class PuppetStrings::Yard::Handlers::Ruby::TypeBase < PuppetStrings::Yard::Handl
52
52
  property
53
53
  end
54
54
 
55
+ def create_check(name, node)
56
+ check = PuppetStrings::Yard::CodeObjects::Type::Check.new(name, find_docstring(node, "Puppet resource check '#{name}'"))
57
+ set_values(node, check)
58
+ check
59
+ end
60
+
55
61
  def set_values(node, object)
56
62
  return unless node.block && node.block.count >= 2
57
63
 
@@ -32,7 +32,7 @@ class PuppetStrings::Yard::Handlers::Ruby::TypeExtrasHandler < PuppetStrings::Ya
32
32
 
33
33
  return unless (statement.count > 1) && (statement[0].children.count > 2)
34
34
  module_name = statement[0].children[0].source
35
- method1_name = statement[0].children[1].source
35
+ method1_name = statement[0].children.drop(1).find{ |c| c.type == :ident }.source
36
36
  return unless (module_name == 'Puppet::Type' || module_name == 'Type') && method1_name == 'type'
37
37
 
38
38
  typename = get_name(statement[0], 'Puppet::Type.type')
@@ -59,6 +59,12 @@ class PuppetStrings::Yard::Handlers::Ruby::TypeHandler < PuppetStrings::Yard::Ha
59
59
  name = node_as_string(parameters[0])
60
60
  next unless name
61
61
  object.add_parameter(create_parameter(name, node))
62
+ elsif method_name == 'newcheck'
63
+ # Add a check to the object
64
+ next unless parameters.count >= 1
65
+ name = node_as_string(parameters[0])
66
+ next unless name
67
+ object.add_check(create_check(name, node))
62
68
  elsif method_name == 'feature'
63
69
  # Add a feature to the object
64
70
  next unless parameters.count >= 2