puppet-strings 2.2.0 → 2.6.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 (150) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +87 -1
  3. data/CONTRIBUTING.md +32 -2
  4. data/README.md +81 -17
  5. data/lib/puppet-strings.rb +5 -3
  6. data/lib/puppet-strings/describe.rb +2 -0
  7. data/lib/puppet-strings/json.rb +4 -0
  8. data/lib/puppet-strings/markdown.rb +13 -9
  9. data/lib/puppet-strings/markdown/base.rb +30 -3
  10. data/lib/puppet-strings/markdown/data_type.rb +36 -0
  11. data/lib/puppet-strings/markdown/data_types.rb +43 -0
  12. data/lib/puppet-strings/markdown/defined_type.rb +2 -0
  13. data/lib/puppet-strings/markdown/defined_types.rb +3 -1
  14. data/lib/puppet-strings/markdown/function.rb +9 -7
  15. data/lib/puppet-strings/markdown/functions.rb +3 -1
  16. data/lib/puppet-strings/markdown/puppet_class.rb +2 -0
  17. data/lib/puppet-strings/markdown/puppet_classes.rb +3 -1
  18. data/lib/puppet-strings/markdown/puppet_plan.rb +2 -0
  19. data/lib/puppet-strings/markdown/puppet_plans.rb +3 -1
  20. data/lib/puppet-strings/markdown/puppet_task.rb +2 -0
  21. data/lib/puppet-strings/markdown/puppet_tasks.rb +3 -1
  22. data/lib/puppet-strings/markdown/resource_type.rb +21 -2
  23. data/lib/puppet-strings/markdown/resource_types.rb +3 -1
  24. data/lib/puppet-strings/markdown/table_of_contents.rb +4 -1
  25. data/lib/puppet-strings/markdown/templates/classes_and_defines.erb +18 -6
  26. data/lib/puppet-strings/markdown/templates/data_type.erb +101 -0
  27. data/lib/puppet-strings/markdown/templates/data_type_function.erb +67 -0
  28. data/lib/puppet-strings/markdown/templates/function.erb +10 -1
  29. data/lib/puppet-strings/markdown/templates/puppet_task.erb +1 -1
  30. data/lib/puppet-strings/markdown/templates/resource_type.erb +35 -13
  31. data/lib/puppet-strings/markdown/templates/table_of_contents.erb +6 -6
  32. data/lib/puppet-strings/monkey_patches/display_object_command.rb +2 -0
  33. data/lib/puppet-strings/tasks.rb +2 -0
  34. data/lib/puppet-strings/tasks/generate.rb +5 -2
  35. data/lib/puppet-strings/tasks/gh_pages.rb +3 -0
  36. data/lib/puppet-strings/version.rb +3 -1
  37. data/lib/puppet-strings/yard.rb +19 -0
  38. data/lib/puppet-strings/yard/code_objects.rb +4 -0
  39. data/lib/puppet-strings/yard/code_objects/base.rb +2 -0
  40. data/lib/puppet-strings/yard/code_objects/class.rb +5 -3
  41. data/lib/puppet-strings/yard/code_objects/data_type.rb +102 -0
  42. data/lib/puppet-strings/yard/code_objects/data_type_alias.rb +60 -0
  43. data/lib/puppet-strings/yard/code_objects/defined_type.rb +5 -3
  44. data/lib/puppet-strings/yard/code_objects/function.rb +9 -6
  45. data/lib/puppet-strings/yard/code_objects/group.rb +3 -0
  46. data/lib/puppet-strings/yard/code_objects/plan.rb +5 -3
  47. data/lib/puppet-strings/yard/code_objects/provider.rb +6 -0
  48. data/lib/puppet-strings/yard/code_objects/task.rb +3 -1
  49. data/lib/puppet-strings/yard/code_objects/type.rb +49 -5
  50. data/lib/puppet-strings/yard/handlers.rb +4 -0
  51. data/lib/puppet-strings/yard/handlers/helpers.rb +2 -0
  52. data/lib/puppet-strings/yard/handlers/json/base.rb +2 -0
  53. data/lib/puppet-strings/yard/handlers/json/task_handler.rb +2 -0
  54. data/lib/puppet-strings/yard/handlers/puppet/base.rb +3 -0
  55. data/lib/puppet-strings/yard/handlers/puppet/class_handler.rb +2 -0
  56. data/lib/puppet-strings/yard/handlers/puppet/data_type_alias_handler.rb +26 -0
  57. data/lib/puppet-strings/yard/handlers/puppet/defined_type_handler.rb +2 -0
  58. data/lib/puppet-strings/yard/handlers/puppet/function_handler.rb +3 -1
  59. data/lib/puppet-strings/yard/handlers/puppet/plan_handler.rb +2 -0
  60. data/lib/puppet-strings/yard/handlers/ruby/base.rb +7 -2
  61. data/lib/puppet-strings/yard/handlers/ruby/data_type_handler.rb +409 -0
  62. data/lib/puppet-strings/yard/handlers/ruby/function_handler.rb +9 -9
  63. data/lib/puppet-strings/yard/handlers/ruby/provider_handler.rb +13 -0
  64. data/lib/puppet-strings/yard/handlers/ruby/rsapi_handler.rb +6 -3
  65. data/lib/puppet-strings/yard/handlers/ruby/type_base.rb +25 -12
  66. data/lib/puppet-strings/yard/handlers/ruby/type_extras_handler.rb +6 -3
  67. data/lib/puppet-strings/yard/handlers/ruby/type_handler.rb +18 -1
  68. data/lib/puppet-strings/yard/parsers.rb +2 -0
  69. data/lib/puppet-strings/yard/parsers/json/parser.rb +3 -1
  70. data/lib/puppet-strings/yard/parsers/json/task_statement.rb +2 -0
  71. data/lib/puppet-strings/yard/parsers/puppet/parser.rb +11 -2
  72. data/lib/puppet-strings/yard/parsers/puppet/statement.rb +29 -0
  73. data/lib/puppet-strings/yard/tags.rb +4 -0
  74. data/lib/puppet-strings/yard/tags/enum_tag.rb +14 -0
  75. data/lib/puppet-strings/yard/tags/factory.rb +18 -0
  76. data/lib/puppet-strings/yard/tags/overload_tag.rb +5 -2
  77. data/lib/puppet-strings/yard/tags/parameter_directive.rb +5 -4
  78. data/lib/puppet-strings/yard/tags/property_directive.rb +5 -4
  79. data/lib/puppet-strings/yard/tags/summary_tag.rb +2 -0
  80. data/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_data_type.erb +10 -0
  81. data/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb +9 -0
  82. data/lib/puppet-strings/yard/templates/default/layout/html/objects.erb +2 -0
  83. data/lib/puppet-strings/yard/templates/default/layout/html/setup.rb +18 -1
  84. data/lib/puppet-strings/yard/templates/default/puppet_data_type/html/box_info.erb +10 -0
  85. data/lib/puppet-strings/yard/templates/default/puppet_data_type/html/header.erb +1 -0
  86. data/lib/puppet-strings/yard/templates/default/puppet_data_type/html/method_details_list.erb +6 -0
  87. data/lib/puppet-strings/yard/templates/default/puppet_data_type/html/note.erb +6 -0
  88. data/lib/puppet-strings/yard/templates/default/puppet_data_type/html/overview.erb +6 -0
  89. data/lib/puppet-strings/yard/templates/default/puppet_data_type/html/setup.rb +13 -0
  90. data/lib/puppet-strings/yard/templates/default/puppet_data_type/html/source.erb +12 -0
  91. data/lib/puppet-strings/yard/templates/default/puppet_data_type/html/summary.erb +4 -0
  92. data/lib/puppet-strings/yard/templates/default/puppet_data_type/html/todo.erb +6 -0
  93. data/lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/alias_of.erb +10 -0
  94. data/lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/box_info.erb +10 -0
  95. data/lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/header.erb +1 -0
  96. data/lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/note.erb +6 -0
  97. data/lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/overview.erb +6 -0
  98. data/lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/setup.rb +17 -0
  99. data/lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/source.erb +12 -0
  100. data/lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/summary.erb +4 -0
  101. data/lib/puppet-strings/yard/templates/default/puppet_data_type_alias/html/todo.erb +6 -0
  102. data/lib/puppet-strings/yard/templates/default/puppet_function/html/setup.rb +1 -1
  103. data/lib/puppet-strings/yard/templates/default/puppet_type/html/setup.rb +3 -1
  104. data/lib/puppet-strings/yard/templates/default/tags/html/enum.erb +17 -0
  105. data/lib/puppet-strings/yard/templates/default/tags/setup.rb +7 -0
  106. data/lib/puppet-strings/yard/util.rb +7 -4
  107. data/lib/puppet/application/strings.rb +2 -0
  108. data/lib/puppet/face/strings.rb +7 -4
  109. data/lib/puppet/feature/rgen.rb +2 -0
  110. data/lib/puppet/feature/yard.rb +2 -0
  111. metadata +35 -45
  112. data/Gemfile +0 -38
  113. data/HISTORY.md +0 -218
  114. data/JSON.md +0 -802
  115. data/Rakefile +0 -98
  116. data/codecov.yml +0 -3
  117. data/misc/ANNOUNCEMENT_TEMPLATE.md +0 -40
  118. data/spec/acceptance/emit_json_options.rb +0 -71
  119. data/spec/acceptance/generate_markdown_spec.rb +0 -49
  120. data/spec/acceptance/lib/util.rb +0 -163
  121. data/spec/acceptance/running_strings_generate.rb +0 -54
  122. data/spec/fixtures/acceptance/modules/test/functions/add.pp +0 -9
  123. data/spec/fixtures/acceptance/modules/test/lib/puppet/functions/4x_function.rb +0 -5
  124. data/spec/fixtures/acceptance/modules/test/lib/puppet/parser/functions/function3x.rb +0 -2
  125. data/spec/fixtures/acceptance/modules/test/lib/puppet/provider/server/linux.rb +0 -9
  126. data/spec/fixtures/acceptance/modules/test/lib/puppet/type/database.rb +0 -15
  127. data/spec/fixtures/acceptance/modules/test/manifests/init.pp +0 -27
  128. data/spec/fixtures/acceptance/modules/test/manifests/triple_nested_classes.pp +0 -27
  129. data/spec/fixtures/acceptance/modules/test/metadata.json +0 -6
  130. data/spec/fixtures/unit/markdown/output.md +0 -508
  131. data/spec/fixtures/unit/markdown/output_with_plan.md +0 -542
  132. data/spec/spec_helper.rb +0 -46
  133. data/spec/spec_helper_acceptance.rb +0 -28
  134. data/spec/unit/puppet-strings/describe_spec.rb +0 -141
  135. data/spec/unit/puppet-strings/json_spec.rb +0 -283
  136. data/spec/unit/puppet-strings/markdown/base_spec.rb +0 -146
  137. data/spec/unit/puppet-strings/markdown_spec.rb +0 -296
  138. data/spec/unit/puppet-strings/yard/code_objects/task_spec.rb +0 -92
  139. data/spec/unit/puppet-strings/yard/handlers/json/task_handler_spec.rb +0 -116
  140. data/spec/unit/puppet-strings/yard/handlers/puppet/class_handler_spec.rb +0 -217
  141. data/spec/unit/puppet-strings/yard/handlers/puppet/defined_type_handler_spec.rb +0 -231
  142. data/spec/unit/puppet-strings/yard/handlers/puppet/function_handler_spec.rb +0 -315
  143. data/spec/unit/puppet-strings/yard/handlers/ruby/function_handler_spec.rb +0 -729
  144. data/spec/unit/puppet-strings/yard/handlers/ruby/provider_handler_spec.rb +0 -139
  145. data/spec/unit/puppet-strings/yard/handlers/ruby/rsapi_handler_spec.rb +0 -235
  146. data/spec/unit/puppet-strings/yard/handlers/ruby/type_handler_spec.rb +0 -295
  147. data/spec/unit/puppet-strings/yard/parsers/json/parser_spec.rb +0 -72
  148. data/spec/unit/puppet-strings/yard/parsers/json/task_statement_spec.rb +0 -56
  149. data/spec/unit/puppet-strings/yard/parsers/puppet/parser_spec.rb +0 -209
  150. data/spec/unit/puppet-strings/yard/util_spec.rb +0 -48
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'puppet-strings/yard/code_objects/group'
4
+ require 'puppet-strings/yard/util'
5
+
6
+ # Implements the group for Puppet DataTypeAliases.
7
+ class PuppetStrings::Yard::CodeObjects::DataTypeAliases < PuppetStrings::Yard::CodeObjects::Group
8
+ # Gets the singleton instance of the group.
9
+ # @return Returns the singleton instance of the group.
10
+ def self.instance
11
+ super(:puppet_data_type_aliases)
12
+ end
13
+
14
+ # Gets the display name of the group.
15
+ # @param [Boolean] prefix whether to show a prefix. Ignored for Puppet group namespaces.
16
+ # @return [String] Returns the display name of the group.
17
+ def name(prefix = false)
18
+ 'Puppet Data Type Aliases'
19
+ end
20
+ end
21
+
22
+ # Implements the Puppet DataTypeAlias code object.
23
+ class PuppetStrings::Yard::CodeObjects::DataTypeAlias < PuppetStrings::Yard::CodeObjects::Base
24
+ attr_reader :statement
25
+ attr_accessor :alias_of
26
+
27
+ # Initializes a Puppet data type alias code object.
28
+ # @param [PuppetStrings::Parsers::DataTypeAliasStatement] statement The data type alias statement that was parsed.
29
+ # @return [void]
30
+ def initialize(statement)
31
+ @statement = statement
32
+ @alias_of = statement.alias_of
33
+ super(PuppetStrings::Yard::CodeObjects::DataTypeAliases.instance, statement.name)
34
+ end
35
+
36
+ # Gets the type of the code object.
37
+ # @return Returns the type of the code object.
38
+ def type
39
+ :puppet_data_type_alias
40
+ end
41
+
42
+ # Gets the source of the code object.
43
+ # @return Returns the source of the code object.
44
+ def source
45
+ # Not implemented, but would be nice!
46
+ nil
47
+ end
48
+
49
+ # Converts the code object to a hash representation.
50
+ # @return [Hash] Returns a hash representation of the code object.
51
+ def to_hash
52
+ hash = {}
53
+ hash[:name] = name
54
+ hash[:file] = file
55
+ hash[:line] = line
56
+ hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring)
57
+ hash[:alias_of] = alias_of
58
+ hash
59
+ end
60
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'puppet-strings/yard/code_objects/group'
2
4
 
3
5
  # Implements the group for Puppet defined types.
@@ -50,9 +52,9 @@ class PuppetStrings::Yard::CodeObjects::DefinedType < PuppetStrings::Yard::CodeO
50
52
  hash[:file] = file
51
53
  hash[:line] = line
52
54
  hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring)
53
- defaults = Hash[*parameters.select{ |p| !p[1].nil? }.flatten]
54
- hash[:defaults] = defaults unless defaults.empty?
55
- hash[:source] = source unless source && source.empty?
55
+ defaults = Hash[*parameters.reject{ |p| p[1].nil? }.flatten]
56
+ hash[:defaults] = defaults unless defaults.nil? || defaults.empty?
57
+ hash[:source] = source unless source.nil? || source.empty?
56
58
  hash
57
59
  end
58
60
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'puppet-strings/yard/code_objects/group'
2
4
 
3
5
  # Implements the group for Puppet functions.
@@ -61,11 +63,12 @@ class PuppetStrings::Yard::CodeObjects::Function < PuppetStrings::Yard::CodeObje
61
63
  # @return [String] Returns the Puppet signature of the function.
62
64
  def signature
63
65
  return '' if self.has_tag? :overload
66
+
64
67
  tags = self.tags(:param)
65
68
  args = @parameters.map do |parameter|
66
69
  name, default = parameter
67
70
  tag = tags.find { |t| t.name == name } if tags
68
- type = tag && tag.types ? "#{tag.type} " : 'Any '
71
+ type = tag&.types ? "#{tag.type} " : 'Any '
69
72
  prefix = "#{name[0]}" if name.start_with?('*', '&')
70
73
  name = name[1..-1] if prefix
71
74
  default = " = #{default}" if default
@@ -88,16 +91,16 @@ class PuppetStrings::Yard::CodeObjects::Function < PuppetStrings::Yard::CodeObje
88
91
  if self.has_tag? :overload
89
92
  # loop over overloads and append onto the signatures array
90
93
  self.tags(:overload).each do |o|
91
- hash[:signatures] << { :signature => o.signature, :docstring => PuppetStrings::Yard::Util.docstring_to_hash(o.docstring, [:param, :option, :return, :example]) }
94
+ hash[:signatures] << { :signature => o.signature, :docstring => PuppetStrings::Yard::Util.docstring_to_hash(o.docstring, %i[param option enum return example]) }
92
95
  end
93
96
  else
94
- hash[:signatures] << { :signature => self.signature, :docstring => PuppetStrings::Yard::Util.docstring_to_hash(docstring, [:param, :option, :return, :example]) }
97
+ hash[:signatures] << { :signature => self.signature, :docstring => PuppetStrings::Yard::Util.docstring_to_hash(docstring, %i[param option enum return example]) }
95
98
  end
96
99
 
97
100
  hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring)
98
- defaults = Hash[*parameters.select{ |p| !p[1].nil? }.flatten]
99
- hash[:defaults] = defaults unless defaults.empty?
100
- hash[:source] = source unless source && source.empty?
101
+ defaults = Hash[*parameters.reject{ |p| p[1].nil? }.flatten]
102
+ hash[:defaults] = defaults unless defaults.nil? || defaults.empty?
103
+ hash[:source] = source unless source.nil? || source.empty?
101
104
  hash
102
105
  end
103
106
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'puppet-strings/yard/code_objects/base'
2
4
 
3
5
  # Implements the base class for "groups".
@@ -10,6 +12,7 @@ class PuppetStrings::Yard::CodeObjects::Group < PuppetStrings::Yard::CodeObjects
10
12
  def self.instance(key)
11
13
  instance = P(:root, key)
12
14
  return instance unless instance.is_a?(YARD::CodeObjects::Proxy)
15
+
13
16
  instance = self.new(:root, key)
14
17
  instance.visibility = :hidden
15
18
  P(:root).children << instance
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'puppet-strings/yard/code_objects/group'
2
4
 
3
5
  class PuppetStrings::Yard::CodeObjects::Plans < PuppetStrings::Yard::CodeObjects::Group
@@ -48,9 +50,9 @@ class PuppetStrings::Yard::CodeObjects::Plan < PuppetStrings::Yard::CodeObjects:
48
50
  hash[:file] = file
49
51
  hash[:line] = line
50
52
  hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring)
51
- defaults = Hash[*parameters.select{ |p| !p[1].nil? }.flatten]
52
- hash[:defaults] = defaults unless defaults.empty?
53
- hash[:source] = source unless source && source.empty?
53
+ defaults = Hash[*parameters.reject{ |p| p[1].nil? }.flatten]
54
+ hash[:defaults] = defaults unless defaults.nil? || defaults.empty?
55
+ hash[:source] = source unless source.nil? || source.empty?
54
56
  hash
55
57
  end
56
58
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'puppet-strings/yard/code_objects/group'
2
4
 
3
5
  # Implements the group for Puppet providers.
@@ -42,6 +44,7 @@ class PuppetStrings::Yard::CodeObjects::Provider < PuppetStrings::Yard::CodeObje
42
44
  # @return [void]
43
45
  def add_confine(key, value)
44
46
  return unless key && value
47
+
45
48
  @confines ||= {}
46
49
  @confines[key] = value
47
50
  end
@@ -51,6 +54,7 @@ class PuppetStrings::Yard::CodeObjects::Provider < PuppetStrings::Yard::CodeObje
51
54
  # @return [void]
52
55
  def add_feature(feature)
53
56
  return unless feature
57
+
54
58
  @features ||= []
55
59
  @features << feature
56
60
  end
@@ -60,6 +64,7 @@ class PuppetStrings::Yard::CodeObjects::Provider < PuppetStrings::Yard::CodeObje
60
64
  # @return [void]
61
65
  def add_default(constraints)
62
66
  return unless constraints
67
+
63
68
  @defaults ||= []
64
69
  @defaults << constraints
65
70
  end
@@ -70,6 +75,7 @@ class PuppetStrings::Yard::CodeObjects::Provider < PuppetStrings::Yard::CodeObje
70
75
  # @return [void]
71
76
  def add_command(key, value)
72
77
  return unless key && value
78
+
73
79
  @commands ||= {}
74
80
  @commands[key] = value
75
81
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'puppet-strings/yard/code_objects/group'
2
4
 
3
5
  # Implements the group for Puppet tasks.
@@ -43,7 +45,7 @@ class PuppetStrings::Yard::CodeObjects::Task < PuppetStrings::Yard::CodeObjects:
43
45
 
44
46
  def parameters
45
47
  parameters = []
46
- statement.json['parameters'].each do |name,props|
48
+ statement.parameters.each do |name,props|
47
49
  parameters.push({ name: name.to_s,
48
50
  tag_name: 'param',
49
51
  text: props['description'] || "",
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'puppet-strings/yard/code_objects/group'
2
4
  require 'puppet-strings/yard/util'
3
5
 
@@ -73,6 +75,9 @@ class PuppetStrings::Yard::CodeObjects::Type < PuppetStrings::Yard::CodeObjects:
73
75
  class Property < Parameter
74
76
  end
75
77
 
78
+ class Check < Parameter
79
+ end
80
+
76
81
  # Represents a resource type feature.
77
82
  class Feature
78
83
  attr_reader :name, :docstring
@@ -95,7 +100,7 @@ class PuppetStrings::Yard::CodeObjects::Type < PuppetStrings::Yard::CodeObjects:
95
100
  end
96
101
  end
97
102
 
98
- attr_reader :properties, :parameters, :features
103
+ attr_reader :properties, :features, :checks
99
104
 
100
105
  # Initializes a new resource type.
101
106
  # @param [String] name The resource type name.
@@ -134,17 +139,56 @@ class PuppetStrings::Yard::CodeObjects::Type < PuppetStrings::Yard::CodeObjects:
134
139
  @features << feature
135
140
  end
136
141
 
142
+ # Adds a check to the resource type.
143
+ # @param [PuppetStrings::Yard::CodeObjects::Type::Check] check The check to add.
144
+ # @return [void]
145
+ def add_check(check)
146
+ @checks ||= []
147
+ @checks << check
148
+ end
149
+
150
+ def parameters
151
+ # just return params if there are no providers
152
+ return @parameters if providers.empty?
153
+
154
+ # return existing params if we have already added provider
155
+ return @parameters if @parameters.any? { |p| p.name == 'provider' }
156
+
157
+ provider_param = Parameter.new(
158
+ 'provider',
159
+ "The specific backend to use for this `#{self.name.to_s}` resource. You will seldom need " + \
160
+ "to specify this --- Puppet will usually discover the appropriate provider for your platform."
161
+ )
162
+
163
+ @parameters << provider_param
164
+ end
165
+
166
+ # Not sure if this is where this belongs or if providers should only be resolved at
167
+ # render-time. For now, this should re-resolve on every call.
168
+ # may be able to memoize this
169
+ def providers
170
+ providers = YARD::Registry.all("puppet_providers_#{name}".intern)
171
+ return providers if providers.empty?
172
+
173
+ providers.first.children
174
+ end
175
+
137
176
  # Converts the code object to a hash representation.
138
177
  # @return [Hash] Returns a hash representation of the code object.
139
178
  def to_hash
140
179
  hash = {}
180
+
141
181
  hash[:name] = name
142
182
  hash[:file] = file
143
183
  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?
184
+
185
+ hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring)
186
+ hash[:properties] = properties.sort_by { |p| p.name }.map(&:to_hash) if properties && !properties.empty?
187
+ hash[:parameters] = parameters.sort_by { |p| p.name }.map(&:to_hash) if parameters && !parameters.empty?
188
+ hash[:checks] = checks.sort_by { |c| c.name }.map(&:to_hash) if checks && !checks.empty?
189
+ hash[:features] = features.sort_by { |f| f.name }.map(&:to_hash) if features && !features.empty?
190
+ hash[:providers] = providers.sort_by { |p| p.name }.map(&:to_hash) if providers && !providers.empty?
191
+
148
192
  hash
149
193
  end
150
194
  end
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # The module for custom YARD handlers.
2
4
  module PuppetStrings::Yard::Handlers
3
5
  # The module for custom Ruby YARD handlers.
4
6
  module Ruby
7
+ require 'puppet-strings/yard/handlers/ruby/data_type_handler'
5
8
  require 'puppet-strings/yard/handlers/ruby/type_handler'
6
9
  require 'puppet-strings/yard/handlers/ruby/type_extras_handler'
7
10
  require 'puppet-strings/yard/handlers/ruby/rsapi_handler'
@@ -17,6 +20,7 @@ module PuppetStrings::Yard::Handlers
17
20
  # The module for custom Puppet YARD handlers.
18
21
  module Puppet
19
22
  require 'puppet-strings/yard/handlers/puppet/class_handler'
23
+ require 'puppet-strings/yard/handlers/puppet/data_type_alias_handler'
20
24
  require 'puppet-strings/yard/handlers/puppet/defined_type_handler'
21
25
  require 'puppet-strings/yard/handlers/puppet/function_handler'
22
26
  require 'puppet-strings/yard/handlers/puppet/plan_handler'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PuppetStrings::Yard::Handlers::Helpers
2
4
  # Logs a warning if a summary tag has more than 140 characters
3
5
  def self.validate_summary_tag(object)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class PuppetStrings::Yard::Handlers::JSON::Base < YARD::Handlers::Base
2
4
  def self.handles?(statement)
3
5
  handlers.any? {|handler| statement.is_a?(handler)}
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'puppet-strings/yard/handlers/json/base'
2
4
  require 'puppet-strings/yard/parsers'
3
5
  require 'puppet-strings/yard/parsers/json/parser'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Implements the base handler for Puppet language handlers.
2
4
  class PuppetStrings::Yard::Handlers::Puppet::Base < YARD::Handlers::Base
3
5
  # Determine sif the handler handles the given statement.
@@ -17,6 +19,7 @@ class PuppetStrings::Yard::Handlers::Puppet::Base < YARD::Handlers::Base
17
19
  tags = object.tags(:param)
18
20
  tags.each do |tag|
19
21
  next if statement.parameters.find { |p| tag.name == p.name }
22
+
20
23
  log.warn "The @param tag for parameter '#{tag.name}' has no matching parameter at #{statement.file}:#{statement.line}." unless tag.name == 'name' || tag.name == 'title'
21
24
  end
22
25
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'puppet-strings/yard/handlers/helpers'
2
4
  require 'puppet-strings/yard/handlers/puppet/base'
3
5
  require 'puppet-strings/yard/parsers'
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'puppet-strings/yard/handlers/helpers'
4
+ require 'puppet-strings/yard/handlers/puppet/base'
5
+ require 'puppet-strings/yard/parsers'
6
+ require 'puppet-strings/yard/code_objects'
7
+
8
+ # Implements the handler for Puppet Data Type Alias.
9
+ class PuppetStrings::Yard::Handlers::Puppet::DataTypeAliasHandler < PuppetStrings::Yard::Handlers::Puppet::Base
10
+ handles PuppetStrings::Yard::Parsers::Puppet::DataTypeAliasStatement
11
+
12
+ process do
13
+ # Register the object
14
+ object = PuppetStrings::Yard::CodeObjects::DataTypeAlias.new(statement)
15
+ register object
16
+
17
+ # Log a warning if missing documentation
18
+ log.warn "Missing documentation for Puppet type alias '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? && object.tags.empty?
19
+
20
+ # Mark the class as public if it doesn't already have an api tag
21
+ object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api
22
+
23
+ # Warn if a summary longer than 140 characters was provided
24
+ PuppetStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary
25
+ end
26
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'puppet-strings/yard/handlers/helpers'
2
4
  require 'puppet-strings/yard/handlers/puppet/base'
3
5
  require 'puppet-strings/yard/parsers'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'puppet-strings/yard/handlers/helpers'
2
4
  require 'puppet-strings/yard/handlers/puppet/base'
3
5
  require 'puppet-strings/yard/parsers'
@@ -37,7 +39,7 @@ class PuppetStrings::Yard::Handlers::Puppet::FunctionHandler < PuppetStrings::Ya
37
39
  def add_return_tag(object, type=nil)
38
40
  tag = object.tag(:return)
39
41
  if tag
40
- if (type && tag.types.first) && (type != tag.types.first)
42
+ if (type && tag.types && tag.types.first) && (type != tag.types.first)
41
43
  log.warn "Documented return type does not match return type in function definition near #{statement.file}:#{statement.line}."
42
44
  end
43
45
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'puppet-strings/yard/handlers/helpers'
2
4
  require 'puppet-strings/yard/handlers/puppet/base'
3
5
  require 'puppet-strings/yard/parsers'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'ripper'
2
4
 
3
5
  # Implements the base handler for Ruby language handlers.
@@ -12,13 +14,15 @@ class PuppetStrings::Yard::Handlers::Ruby::Base < YARD::Handlers::Ruby::Base
12
14
  # @return [String] Returns a string representation of the node or nil if a string representation was not possible.
13
15
  def node_as_string(node)
14
16
  return nil unless node
17
+
15
18
  case node.type
16
19
  when :symbol, :symbol_literal
17
20
  node.source[1..-1]
18
21
  when :label
19
22
  node.source[0..-2]
20
23
  when :dyna_symbol
21
- node.source
24
+ content = node.jump(:tstring_content)
25
+ content.nil? ? node.source : content.source
22
26
  when :string_literal
23
27
  content = node.jump(:tstring_content)
24
28
  return content.source if content != node
@@ -41,9 +45,10 @@ class PuppetStrings::Yard::Handlers::Ruby::Base < YARD::Handlers::Ruby::Base
41
45
  def get_name(statementobject, statementtype)
42
46
  parameters = statementobject.parameters(false)
43
47
  raise YARD::Parser::UndocumentableError, "Expected at least one parameter to #{statementtype} at #{statementobject.file}:#{statementobject.line}." if parameters.empty?
48
+
44
49
  name = node_as_string(parameters.first)
45
50
  raise YARD::Parser::UndocumentableError, "Expected a symbol or string literal for first parameter but found '#{parameters.first.type}' at #{statement.file}:#{statement.line}." unless name
51
+
46
52
  name
47
53
  end
48
-
49
54
  end
@@ -0,0 +1,409 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'puppet-strings/yard/handlers/helpers'
4
+ require 'puppet-strings/yard/handlers/ruby/base'
5
+ require 'puppet-strings/yard/code_objects'
6
+ require 'puppet-strings/yard/util'
7
+
8
+ # Implements the handler for Puppet Data Types written in Ruby.
9
+ class PuppetStrings::Yard::Handlers::Ruby::DataTypeHandler < PuppetStrings::Yard::Handlers::Ruby::Base
10
+ namespace_only
11
+ handles method_call(:create_type)
12
+
13
+ process do
14
+ return unless statement.count > 1
15
+
16
+ ruby_module_name = statement[0].source
17
+ return unless ruby_module_name == 'Puppet::DataTypes' || ruby_module_name == 'DataTypes' # rubocop:disable Style/MultipleComparison This reads better
18
+
19
+ object = get_datatype_yard_object(get_name(statement, 'Puppet::DataTypes.create_type'))
20
+ # Extract the interface definition
21
+ type_interface = extract_data_type_interface
22
+ actual_params = extract_params(type_interface)
23
+ actual_funcs = extract_functions(object, type_interface)
24
+
25
+ # Mark the data type as public if it doesn't already have an api tag
26
+ object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api
27
+
28
+ validate_param_tags!(object, actual_params)
29
+ validate_methods!(object, actual_funcs)
30
+
31
+ # Set the default values for all parameters
32
+ actual_params.each { |name, data| object.set_parameter_default(name, data[:default]) }
33
+
34
+ # Default any typeless param tag to 'Any'
35
+ object.tags(:param).each do |tag|
36
+ tag.types = ['Any'] unless tag.types && !tag.types.empty?
37
+ end
38
+
39
+ # Warn if a summary longer than 140 characters was provided
40
+ PuppetStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary
41
+ end
42
+
43
+ private
44
+
45
+ def get_datatype_yard_object(name)
46
+ # Have to guess the path - if we create the object to get the true path from the code,
47
+ # it also shows up in the .at call - self registering?
48
+ guess_path = "puppet_data_types::#{name}"
49
+ object = YARD::Registry.at(guess_path)
50
+
51
+ return object unless object.nil?
52
+
53
+ # Didn't find, create instead
54
+ object = PuppetStrings::Yard::CodeObjects::DataType.new(name)
55
+ register object
56
+ object
57
+ end
58
+
59
+ # @return [Hash{Object => Object}] The Puppet DataType interface definition as a ruby Hash
60
+ def extract_data_type_interface
61
+ block = statement.block
62
+ return {} unless block
63
+
64
+ # Declare the parsed interface outside of the closure
65
+ parsed_interface = nil
66
+
67
+ # Recursively traverse the block looking for the first valid 'interface' call
68
+ interface_node = find_ruby_ast_node(block, true) do |node|
69
+ next false unless node.is_a?(YARD::Parser::Ruby::MethodCallNode) &&
70
+ node.method_name &&
71
+ node.method_name.source == 'interface'
72
+
73
+ parameters = node.parameters(false)
74
+ next false unless parameters.count >= 1
75
+
76
+ interface_string = node_as_string(parameters[0])
77
+ next false unless interface_string
78
+
79
+ begin
80
+ # Ref - https://github.com/puppetlabs/puppet/blob/ba4d1a1aba0095d3c70b98fea5c67434a4876a61/lib/puppet/datatypes.rb#L159
81
+ parsed_interface = Puppet::Pops::Parser::EvaluatingParser.new.parse_string("{ #{interface_string} }").body
82
+ rescue Puppet::Error => e
83
+ log.warn "Invalid datatype definition at #{statement.file}:#{statement.line}: #{e.basic_message}"
84
+ next false
85
+ end
86
+ !parsed_interface.nil?
87
+ end
88
+
89
+ # Now that we parsed the Puppet code (as a string) into a LiteralHash PCore type (Puppet AST),
90
+ # We need to convert the LiteralHash into a conventional ruby hash of strings. The
91
+ # LazyLiteralEvaluator does this by traversing the AST tree can converting objects to strings
92
+ # where possible and ignoring object types which cannot (thus the 'Lazy' name)
93
+ literal_eval = LazyLiteralEvaluator.new
94
+ literal_eval.literal(parsed_interface)
95
+ end
96
+
97
+ # Find the first Ruby AST node within an AST Tree, optionally recursively. Returns nil of none could be found
98
+ #
99
+ # @param [YARD::Parser::Ruby::AstNode] ast_node The root AST node object to inspect
100
+ # @param [Boolean] recurse Whether to search the tree recursively. Defaults to false
101
+ # @yieldparam [YARD::Parser::Ruby::AstNode] ast_node The AST Node that should be checked
102
+ # @yieldreturn [Boolean] Whether the node was what was searched for
103
+ # @return [YARD::Parser::Ruby::AstNode, nil]
104
+ def find_ruby_ast_node(ast_node, recurse = false, &block)
105
+ raise ArgumentError, 'find_ruby_ast_node requires a block' unless block_given?
106
+
107
+ is_found = yield ast_node
108
+ return ast_node if is_found
109
+
110
+ if ast_node.respond_to?(:children)
111
+ ast_node.children.each do |child_node|
112
+ child_found = find_ruby_ast_node(child_node, recurse, &block)
113
+ return child_found unless child_found.nil?
114
+ end
115
+ end
116
+ nil
117
+ end
118
+
119
+ # Lazily evaluates a Pops object, ignoring any objects that cannot
120
+ # be converted to a literal value. Based on the Puppet Literal Evaluator
121
+ # Ref - https://github.com/puppetlabs/puppet/blob/ba4d1a1aba0095d3c70b98fea5c67434a4876a61/lib/puppet/pops/evaluator/literal_evaluator.rb
122
+ #
123
+ # Literal values for:
124
+ # String (not containing interpolation)
125
+ # Numbers
126
+ # Booleans
127
+ # Undef (produces nil)
128
+ # Array
129
+ # Hash
130
+ # QualifiedName
131
+ # Default (produced :default)
132
+ # Regular Expression (produces ruby regular expression)
133
+ # QualifiedReference e.g. File, FooBar
134
+ # AccessExpression
135
+ #
136
+ # Anything else is ignored
137
+ class LazyLiteralEvaluator
138
+ def initialize
139
+ @literal_visitor = ::Puppet::Pops::Visitor.new(self, "literal", 0, 0)
140
+ end
141
+
142
+ def literal(ast)
143
+ @literal_visitor.visit_this_0(self, ast)
144
+ end
145
+
146
+ # ----- The following methods are different/additions from the original Literal_evaluator
147
+ def literal_Object(o)
148
+ # Ignore any other object types
149
+ end
150
+
151
+ def literal_AccessExpression(o)
152
+ # Extract the raw text of the Access Expression
153
+ ::Puppet::Pops::Adapters::SourcePosAdapter.adapt(o).extract_text
154
+ end
155
+
156
+ def literal_QualifiedReference(o)
157
+ # Extract the raw text of the Qualified Reference
158
+ ::Puppet::Pops::Adapters::SourcePosAdapter.adapt(o).extract_text
159
+ end
160
+
161
+ # ----- The following methods are the same as the original Literal_evaluator
162
+ def literal_Factory(o)
163
+ literal(o.model)
164
+ end
165
+
166
+ def literal_Program(o)
167
+ literal(o.body)
168
+ end
169
+
170
+ def literal_LiteralString(o)
171
+ o.value
172
+ end
173
+
174
+ def literal_QualifiedName(o)
175
+ o.value
176
+ end
177
+
178
+ def literal_LiteralNumber(o)
179
+ o.value
180
+ end
181
+
182
+ def literal_UnaryMinusExpression(o)
183
+ -1 * literal(o.expr)
184
+ end
185
+
186
+ def literal_LiteralBoolean(o)
187
+ o.value
188
+ end
189
+
190
+ def literal_LiteralUndef(o)
191
+ nil
192
+ end
193
+
194
+ def literal_LiteralDefault(o)
195
+ :default
196
+ end
197
+
198
+ def literal_LiteralRegularExpression(o)
199
+ o.value
200
+ end
201
+
202
+ def literal_ConcatenatedString(o)
203
+ # use double quoted string value if there is no interpolation
204
+ throw :not_literal unless o.segments.size == 1 && o.segments[0].is_a?(Model::LiteralString)
205
+ o.segments[0].value
206
+ end
207
+
208
+ def literal_LiteralList(o)
209
+ o.values.map { |v| literal(v) }
210
+ end
211
+
212
+ def literal_LiteralHash(o)
213
+ o.entries.reduce({}) do |result, entry|
214
+ result[literal(entry.key)] = literal(entry.value)
215
+ result
216
+ end
217
+ end
218
+ end
219
+
220
+ # Extracts the datatype attributes from a Puppet Data Type interface hash.
221
+ # Returns a Hash with a :types key (Array of data types for the parameter) and :default key (The default value of the parameter)
222
+ # @return Hash[Symbol => Hash] The Datatype Attributes as a hash
223
+ def extract_params(hash)
224
+ params_hash = {}
225
+ # Exit early if there are no entries in the hash
226
+ return params_hash if hash.nil? || hash['attributes'].nil? || hash['attributes'].empty?
227
+
228
+ hash['attributes'].each do |key, value|
229
+ data_type = nil
230
+ default = nil
231
+ if value.is_a?(String)
232
+ data_type = value
233
+ elsif value.is_a?(Hash)
234
+ data_type = value['type'] unless value['type'].nil?
235
+ default = value['value'] unless value['value'].nil?
236
+ end
237
+ data_type = [data_type] unless data_type.nil? || data_type.is_a?(Array)
238
+ params_hash[key] = { :types => data_type, :default => default }
239
+ end
240
+
241
+ params_hash
242
+ end
243
+
244
+ # Extracts the datatype functions from a Puppet Data Type interface hash.
245
+ # Returns a Hash with a :param_types key (Array of types for each parameter) and :return_type key (The return type of the function)
246
+ # @return Hash[Symbol => Hash] The Datatype Attributes as a hash
247
+ def extract_functions(object, hash)
248
+ funcs_hash = {}
249
+ # Exit early if there are no entries in the hash
250
+ return funcs_hash if hash.nil? || hash['functions'].nil? || hash['functions'].empty?
251
+
252
+ hash['functions'].each do |key, func_type|
253
+ func_hash = { :param_types => [], :return_type => nil }
254
+ begin
255
+ callable_type = Puppet::Pops::Types::TypeParser.singleton.parse(func_type)
256
+ if callable_type.is_a?(Puppet::Pops::Types::PCallableType)
257
+ func_hash[:param_types] = callable_type.param_types.map { |pt| pt.to_s }
258
+ func_hash[:return_type] = callable_type.return_type.to_s
259
+ else
260
+ log.warn "The function definition for '#{key}' near #{object.file}:#{object.line} is not a Callable type"
261
+ end
262
+ rescue Puppet::ParseError => e
263
+ log.warn "Unable to parse the function definition for '#{key}' near #{object.file}:#{object.line}. #{e}"
264
+ end
265
+ funcs_hash[key] = func_hash
266
+ end
267
+ funcs_hash
268
+ end
269
+
270
+ # Validates and automatically fixes yard @param tags for the data type
271
+ def validate_param_tags!(object, actual_params_hash)
272
+ actual_param_names = actual_params_hash.keys
273
+ tagged_param_names = object.tags(:param).map(&:name)
274
+ # Log any errors
275
+ # Find attributes which are not documented
276
+ (actual_param_names - tagged_param_names).each do |item|
277
+ log.warn "Missing @param tag for attribute '#{item}' near #{object.file}:#{object.line}."
278
+ end
279
+ # Find param tags with no matching attribute
280
+ (tagged_param_names - actual_param_names).each do |item|
281
+ log.warn "The @param tag for '#{item}' has no matching attribute near #{object.file}:#{object.line}."
282
+ end
283
+ # Find param tags with a type that is different from the actual definition
284
+ object.tags(:param).reject { |tag| tag.types.nil? }.each do |tag|
285
+ next if actual_params_hash[tag.name].nil?
286
+
287
+ actual_data_type = actual_params_hash[tag.name][:types]
288
+ next if actual_data_type.nil?
289
+
290
+ log.warn "The @param tag for '#{tag.name}' has a different type definition than the actual attribute near #{object.file}:#{object.line}." if tag.types != actual_data_type
291
+ end
292
+
293
+ # Automatically fix missing @param tags
294
+ (actual_param_names - tagged_param_names).each do |name|
295
+ object.add_parameter(name, actual_params_hash[name][:types], actual_params_hash[name][:default])
296
+ end
297
+ # Remove extra param tags
298
+ object.docstring.delete_tag_if { |item| item.tag_name == 'param' && !actual_param_names.include?(item.name) }
299
+
300
+ # Set the type in the param tag
301
+ object.tags(:param).each do |tag|
302
+ next if actual_params_hash[tag.name].nil?
303
+
304
+ tag.types = actual_params_hash[tag.name][:types]
305
+ end
306
+ end
307
+
308
+ # Validates and automatically fixes yard @method! tags for the data type
309
+ def validate_methods!(object, actual_functions_hash)
310
+ actual_func_names = actual_functions_hash.keys
311
+ tagged_func_names = object.meths.map { |meth| meth.name.to_s }
312
+
313
+ # Log any errors
314
+ # Find functions which are not documented
315
+ (actual_func_names - tagged_func_names).each do |item|
316
+ log.warn "Missing @!method tag for function '#{item}' near #{object.file}:#{object.line}."
317
+ end
318
+ # Find functions which are not defined
319
+ (tagged_func_names - actual_func_names).each do |item|
320
+ log.warn "The @!method tag for '#{item}' has no matching function definition near #{object.file}:#{object.line}."
321
+ end
322
+ # Functions with the wrong return type
323
+ object.meths.each do |meth|
324
+ next unless actual_func_names.include?(meth.name.to_s)
325
+
326
+ return_tag = meth.docstring.tag(:return)
327
+ next if return_tag.nil?
328
+
329
+ actual_return_types = [actual_functions_hash[meth.name.to_s][:return_type]]
330
+ next if return_tag.types == actual_return_types
331
+
332
+ 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}"
333
+ return_tag.types = actual_return_types
334
+ end
335
+
336
+ # Automatically fix missing methods
337
+ (actual_func_names - tagged_func_names).each do |name|
338
+ object.add_function(name, actual_functions_hash[name][:return_type], actual_functions_hash[name][:param_types])
339
+ end
340
+ # Remove extra methods. Can't use `meths` as that's a derived property
341
+ object.children.reject! { |child| child.is_a?(YARD::CodeObjects::MethodObject) && !actual_func_names.include?(child.name.to_s) }
342
+
343
+ # Add the return type for the methods if missing
344
+ object.meths.each do |meth|
345
+ next unless meth.docstring.tag(:return).nil?
346
+
347
+ meth.docstring.add_tag(YARD::Tags::Tag.new(:return, '', actual_functions_hash[meth.name.to_s][:return_type]))
348
+ end
349
+
350
+ # Sync the method properties and add the return type for the methods if missing
351
+ object.meths.each do |meth|
352
+ validate_function_method!(object, meth, actual_functions_hash[meth.name.to_s])
353
+ next unless meth.docstring.tag(:return).nil?
354
+
355
+ meth.docstring.add_tag(YARD::Tags::Tag.new(:return, '', actual_functions_hash[meth.name.to_s][:return_type]))
356
+ end
357
+
358
+ # The default meth.signature assumes ruby invocation (e.g. def meth(...)) but this doesn't make sense for a
359
+ # Puppet Data Type function invocation. So instead we derive a signature from the method definition.
360
+ object.meths.each do |meth|
361
+ params = ''
362
+ unless meth.docstring.tags(:param).empty?
363
+ params += '(' + meth.docstring.tags(:param).map { |t| t.name }.join(', ') + ')'
364
+ end
365
+ meth.signature = "#{object.name}.#{meth.name}" + params
366
+ end
367
+
368
+ nil
369
+ end
370
+
371
+ # Validates and automatically fixes a single yard @method!
372
+ # Used by the validate_methods! method.
373
+ def validate_function_method!(object, meth, actual_function)
374
+ # Remove extra params
375
+ if meth.docstring.tags(:param).count > actual_function[:param_types].count
376
+ index = 0
377
+ meth.docstring.delete_tag_if do |tag|
378
+ if tag.tag_name == 'param'
379
+ index += 1
380
+ if index > actual_function[:param_types].count
381
+ 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"
382
+ true
383
+ else
384
+ false
385
+ end
386
+ else
387
+ false
388
+ end
389
+ end
390
+ end
391
+
392
+ # Add missing params
393
+ if meth.docstring.tags(:param).count < actual_function[:param_types].count
394
+ start = meth.docstring.tags(:param).count + 1
395
+ (start..actual_function[:param_types].count).each do |index| # Using 1-based index here instead of usual zero
396
+ meth.add_tag(YARD::Tags::Tag.new(:param, '', actual_function[:param_types][index - 1], "param#{index}"))
397
+ end
398
+ end
399
+
400
+ # Ensure the parameter types are correct
401
+ meth.docstring.tags(:param).each_with_index do |tag, index|
402
+ actual_types = [actual_function[:param_types][index]]
403
+ if tag.types != actual_types
404
+ 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}"
405
+ tag.types = actual_types
406
+ end
407
+ end
408
+ end
409
+ end