puppet-strings 2.2.0 → 2.6.0

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