puppet-strings 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
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