openvox-strings 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +407 -0
  3. data/LICENSE +177 -0
  4. data/README.md +116 -0
  5. data/lib/openvox-strings/describe.rb +75 -0
  6. data/lib/openvox-strings/json.rb +33 -0
  7. data/lib/openvox-strings/markdown/base.rb +236 -0
  8. data/lib/openvox-strings/markdown/data_type.rb +39 -0
  9. data/lib/openvox-strings/markdown/defined_type.rb +20 -0
  10. data/lib/openvox-strings/markdown/function.rb +59 -0
  11. data/lib/openvox-strings/markdown/helpers.rb +21 -0
  12. data/lib/openvox-strings/markdown/puppet_class.rb +20 -0
  13. data/lib/openvox-strings/markdown/puppet_plan.rb +20 -0
  14. data/lib/openvox-strings/markdown/puppet_task.rb +29 -0
  15. data/lib/openvox-strings/markdown/resource_type.rb +56 -0
  16. data/lib/openvox-strings/markdown/templates/classes_and_defines.erb +94 -0
  17. data/lib/openvox-strings/markdown/templates/data_type.erb +101 -0
  18. data/lib/openvox-strings/markdown/templates/data_type_function.erb +67 -0
  19. data/lib/openvox-strings/markdown/templates/function.erb +106 -0
  20. data/lib/openvox-strings/markdown/templates/puppet_task.erb +28 -0
  21. data/lib/openvox-strings/markdown/templates/resource_type.erb +156 -0
  22. data/lib/openvox-strings/markdown/templates/table_of_contents.erb +26 -0
  23. data/lib/openvox-strings/markdown.rb +81 -0
  24. data/lib/openvox-strings/monkey_patches/display_object_command.rb +16 -0
  25. data/lib/openvox-strings/tasks/generate.rb +54 -0
  26. data/lib/openvox-strings/tasks/gh_pages.rb +72 -0
  27. data/lib/openvox-strings/tasks/validate.rb +42 -0
  28. data/lib/openvox-strings/tasks.rb +14 -0
  29. data/lib/openvox-strings/version.rb +5 -0
  30. data/lib/openvox-strings/yard/code_objects/base.rb +16 -0
  31. data/lib/openvox-strings/yard/code_objects/class.rb +60 -0
  32. data/lib/openvox-strings/yard/code_objects/data_type.rb +102 -0
  33. data/lib/openvox-strings/yard/code_objects/data_type_alias.rb +60 -0
  34. data/lib/openvox-strings/yard/code_objects/defined_type.rb +59 -0
  35. data/lib/openvox-strings/yard/code_objects/function.rb +106 -0
  36. data/lib/openvox-strings/yard/code_objects/group.rb +33 -0
  37. data/lib/openvox-strings/yard/code_objects/plan.rb +59 -0
  38. data/lib/openvox-strings/yard/code_objects/provider.rb +98 -0
  39. data/lib/openvox-strings/yard/code_objects/task.rb +69 -0
  40. data/lib/openvox-strings/yard/code_objects/type.rb +196 -0
  41. data/lib/openvox-strings/yard/code_objects.rb +14 -0
  42. data/lib/openvox-strings/yard/handlers/helpers.rb +10 -0
  43. data/lib/openvox-strings/yard/handlers/json/base.rb +8 -0
  44. data/lib/openvox-strings/yard/handlers/json/task_handler.rb +34 -0
  45. data/lib/openvox-strings/yard/handlers/puppet/base.rb +52 -0
  46. data/lib/openvox-strings/yard/handlers/puppet/class_handler.rb +29 -0
  47. data/lib/openvox-strings/yard/handlers/puppet/data_type_alias_handler.rb +26 -0
  48. data/lib/openvox-strings/yard/handlers/puppet/defined_type_handler.rb +29 -0
  49. data/lib/openvox-strings/yard/handlers/puppet/function_handler.rb +54 -0
  50. data/lib/openvox-strings/yard/handlers/puppet/plan_handler.rb +29 -0
  51. data/lib/openvox-strings/yard/handlers/ruby/base.rb +55 -0
  52. data/lib/openvox-strings/yard/handlers/ruby/data_type_handler.rb +411 -0
  53. data/lib/openvox-strings/yard/handlers/ruby/function_handler.rb +386 -0
  54. data/lib/openvox-strings/yard/handlers/ruby/provider_handler.rb +127 -0
  55. data/lib/openvox-strings/yard/handlers/ruby/rsapi_handler.rb +157 -0
  56. data/lib/openvox-strings/yard/handlers/ruby/type_base.rb +146 -0
  57. data/lib/openvox-strings/yard/handlers/ruby/type_extras_handler.rb +65 -0
  58. data/lib/openvox-strings/yard/handlers/ruby/type_handler.rb +105 -0
  59. data/lib/openvox-strings/yard/handlers.rb +28 -0
  60. data/lib/openvox-strings/yard/parsers/json/parser.rb +38 -0
  61. data/lib/openvox-strings/yard/parsers/json/task_statement.rb +37 -0
  62. data/lib/openvox-strings/yard/parsers/puppet/parser.rb +89 -0
  63. data/lib/openvox-strings/yard/parsers/puppet/statement.rb +182 -0
  64. data/lib/openvox-strings/yard/parsers.rb +14 -0
  65. data/lib/openvox-strings/yard/tags/enum_tag.rb +13 -0
  66. data/lib/openvox-strings/yard/tags/factory.rb +18 -0
  67. data/lib/openvox-strings/yard/tags/overload_tag.rb +112 -0
  68. data/lib/openvox-strings/yard/tags/parameter_directive.rb +25 -0
  69. data/lib/openvox-strings/yard/tags/property_directive.rb +25 -0
  70. data/lib/openvox-strings/yard/tags/summary_tag.rb +10 -0
  71. data/lib/openvox-strings/yard/tags.rb +11 -0
  72. data/lib/openvox-strings/yard/templates/default/fulldoc/html/css/common.css +8 -0
  73. data/lib/openvox-strings/yard/templates/default/fulldoc/html/full_list_puppet_class.erb +9 -0
  74. data/lib/openvox-strings/yard/templates/default/fulldoc/html/full_list_puppet_data_type.erb +10 -0
  75. data/lib/openvox-strings/yard/templates/default/fulldoc/html/full_list_puppet_defined_type.erb +9 -0
  76. data/lib/openvox-strings/yard/templates/default/fulldoc/html/full_list_puppet_function.erb +10 -0
  77. data/lib/openvox-strings/yard/templates/default/fulldoc/html/full_list_puppet_plan.erb +9 -0
  78. data/lib/openvox-strings/yard/templates/default/fulldoc/html/full_list_puppet_provider.erb +10 -0
  79. data/lib/openvox-strings/yard/templates/default/fulldoc/html/full_list_puppet_task.erb +9 -0
  80. data/lib/openvox-strings/yard/templates/default/fulldoc/html/full_list_puppet_type.erb +9 -0
  81. data/lib/openvox-strings/yard/templates/default/fulldoc/html/setup.rb +93 -0
  82. data/lib/openvox-strings/yard/templates/default/layout/html/footer.erb +3 -0
  83. data/lib/openvox-strings/yard/templates/default/layout/html/objects.erb +37 -0
  84. data/lib/openvox-strings/yard/templates/default/layout/html/setup.rb +231 -0
  85. data/lib/openvox-strings/yard/templates/default/puppet_class/html/box_info.erb +26 -0
  86. data/lib/openvox-strings/yard/templates/default/puppet_class/html/deprecated.erb +6 -0
  87. data/lib/openvox-strings/yard/templates/default/puppet_class/html/header.erb +1 -0
  88. data/lib/openvox-strings/yard/templates/default/puppet_class/html/note.erb +6 -0
  89. data/lib/openvox-strings/yard/templates/default/puppet_class/html/overview.erb +6 -0
  90. data/lib/openvox-strings/yard/templates/default/puppet_class/html/setup.rb +16 -0
  91. data/lib/openvox-strings/yard/templates/default/puppet_class/html/source.erb +12 -0
  92. data/lib/openvox-strings/yard/templates/default/puppet_class/html/summary.erb +4 -0
  93. data/lib/openvox-strings/yard/templates/default/puppet_class/html/todo.erb +6 -0
  94. data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/box_info.erb +10 -0
  95. data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/deprecated.erb +6 -0
  96. data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/header.erb +1 -0
  97. data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/method_details_list.erb +6 -0
  98. data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/note.erb +6 -0
  99. data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/overview.erb +6 -0
  100. data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/setup.rb +15 -0
  101. data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/source.erb +12 -0
  102. data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/summary.erb +4 -0
  103. data/lib/openvox-strings/yard/templates/default/puppet_data_type/html/todo.erb +6 -0
  104. data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/alias_of.erb +10 -0
  105. data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/box_info.erb +10 -0
  106. data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/deprecated.erb +6 -0
  107. data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/header.erb +1 -0
  108. data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/note.erb +6 -0
  109. data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/overview.erb +6 -0
  110. data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/setup.rb +19 -0
  111. data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/source.erb +12 -0
  112. data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/summary.erb +4 -0
  113. data/lib/openvox-strings/yard/templates/default/puppet_data_type_alias/html/todo.erb +6 -0
  114. data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/box_info.erb +10 -0
  115. data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/deprecated.erb +6 -0
  116. data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/header.erb +1 -0
  117. data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/note.erb +6 -0
  118. data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/overview.erb +6 -0
  119. data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/setup.rb +7 -0
  120. data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/source.erb +12 -0
  121. data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/summary.erb +4 -0
  122. data/lib/openvox-strings/yard/templates/default/puppet_defined_type/html/todo.erb +6 -0
  123. data/lib/openvox-strings/yard/templates/default/puppet_function/html/box_info.erb +14 -0
  124. data/lib/openvox-strings/yard/templates/default/puppet_function/html/deprecated.erb +6 -0
  125. data/lib/openvox-strings/yard/templates/default/puppet_function/html/header.erb +1 -0
  126. data/lib/openvox-strings/yard/templates/default/puppet_function/html/note.erb +6 -0
  127. data/lib/openvox-strings/yard/templates/default/puppet_function/html/overview.erb +18 -0
  128. data/lib/openvox-strings/yard/templates/default/puppet_function/html/setup.rb +7 -0
  129. data/lib/openvox-strings/yard/templates/default/puppet_function/html/source.erb +12 -0
  130. data/lib/openvox-strings/yard/templates/default/puppet_function/html/summary.erb +4 -0
  131. data/lib/openvox-strings/yard/templates/default/puppet_function/html/todo.erb +6 -0
  132. data/lib/openvox-strings/yard/templates/default/puppet_plan/html/box_info.erb +10 -0
  133. data/lib/openvox-strings/yard/templates/default/puppet_plan/html/deprecated.erb +6 -0
  134. data/lib/openvox-strings/yard/templates/default/puppet_plan/html/header.erb +1 -0
  135. data/lib/openvox-strings/yard/templates/default/puppet_plan/html/note.erb +6 -0
  136. data/lib/openvox-strings/yard/templates/default/puppet_plan/html/overview.erb +6 -0
  137. data/lib/openvox-strings/yard/templates/default/puppet_plan/html/setup.rb +13 -0
  138. data/lib/openvox-strings/yard/templates/default/puppet_plan/html/source.erb +12 -0
  139. data/lib/openvox-strings/yard/templates/default/puppet_plan/html/summary.erb +4 -0
  140. data/lib/openvox-strings/yard/templates/default/puppet_plan/html/todo.erb +6 -0
  141. data/lib/openvox-strings/yard/templates/default/puppet_provider/html/box_info.erb +14 -0
  142. data/lib/openvox-strings/yard/templates/default/puppet_provider/html/collection.erb +17 -0
  143. data/lib/openvox-strings/yard/templates/default/puppet_provider/html/features.erb +12 -0
  144. data/lib/openvox-strings/yard/templates/default/puppet_provider/html/header.erb +1 -0
  145. data/lib/openvox-strings/yard/templates/default/puppet_provider/html/overview.erb +6 -0
  146. data/lib/openvox-strings/yard/templates/default/puppet_provider/html/setup.rb +31 -0
  147. data/lib/openvox-strings/yard/templates/default/puppet_provider/html/summary.erb +4 -0
  148. data/lib/openvox-strings/yard/templates/default/puppet_task/html/box_info.erb +9 -0
  149. data/lib/openvox-strings/yard/templates/default/puppet_task/html/header.erb +1 -0
  150. data/lib/openvox-strings/yard/templates/default/puppet_task/html/input.erb +5 -0
  151. data/lib/openvox-strings/yard/templates/default/puppet_task/html/overview.erb +6 -0
  152. data/lib/openvox-strings/yard/templates/default/puppet_task/html/parameters.erb +16 -0
  153. data/lib/openvox-strings/yard/templates/default/puppet_task/html/setup.rb +24 -0
  154. data/lib/openvox-strings/yard/templates/default/puppet_task/html/supports_noop.erb +3 -0
  155. data/lib/openvox-strings/yard/templates/default/puppet_type/html/box_info.erb +20 -0
  156. data/lib/openvox-strings/yard/templates/default/puppet_type/html/deprecated.erb +6 -0
  157. data/lib/openvox-strings/yard/templates/default/puppet_type/html/features.erb +13 -0
  158. data/lib/openvox-strings/yard/templates/default/puppet_type/html/header.erb +1 -0
  159. data/lib/openvox-strings/yard/templates/default/puppet_type/html/note.erb +6 -0
  160. data/lib/openvox-strings/yard/templates/default/puppet_type/html/overview.erb +6 -0
  161. data/lib/openvox-strings/yard/templates/default/puppet_type/html/parameters.erb +35 -0
  162. data/lib/openvox-strings/yard/templates/default/puppet_type/html/setup.rb +36 -0
  163. data/lib/openvox-strings/yard/templates/default/puppet_type/html/summary.erb +4 -0
  164. data/lib/openvox-strings/yard/templates/default/puppet_type/html/todo.erb +6 -0
  165. data/lib/openvox-strings/yard/templates/default/tags/html/enum.erb +17 -0
  166. data/lib/openvox-strings/yard/templates/default/tags/html/puppet_overload.erb +12 -0
  167. data/lib/openvox-strings/yard/templates/default/tags/setup.rb +20 -0
  168. data/lib/openvox-strings/yard/util.rb +87 -0
  169. data/lib/openvox-strings/yard.rb +132 -0
  170. data/lib/openvox-strings.rb +88 -0
  171. data/lib/puppet/application/strings.rb +7 -0
  172. data/lib/puppet/face/strings.rb +185 -0
  173. data/lib/puppet/feature/rgen.rb +5 -0
  174. data/lib/puppet/feature/yard.rb +5 -0
  175. metadata +263 -0
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openvox-strings/yard/handlers/helpers'
4
+ require 'openvox-strings/yard/handlers/puppet/base'
5
+ require 'openvox-strings/yard/parsers'
6
+ require 'openvox-strings/yard/code_objects'
7
+
8
+ # Implements the handler for Puppet classes.
9
+ class OpenvoxStrings::Yard::Handlers::Puppet::ClassHandler < OpenvoxStrings::Yard::Handlers::Puppet::Base
10
+ handles OpenvoxStrings::Yard::Parsers::Puppet::ClassStatement
11
+
12
+ process do
13
+ # Register the object
14
+ object = OpenvoxStrings::Yard::CodeObjects::Class.new(statement)
15
+ register object
16
+
17
+ # Log a warning if missing documentation
18
+ log.warn "Missing documentation for Puppet class '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? && object.tags.empty?
19
+
20
+ # Set the parameter types
21
+ set_parameter_types(object)
22
+
23
+ # Mark the class as public if it doesn't already have an api tag
24
+ object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api
25
+
26
+ # Warn if a summary longer than 140 characters was provided
27
+ OpenvoxStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openvox-strings/yard/handlers/helpers'
4
+ require 'openvox-strings/yard/handlers/puppet/base'
5
+ require 'openvox-strings/yard/parsers'
6
+ require 'openvox-strings/yard/code_objects'
7
+
8
+ # Implements the handler for Puppet Data Type Alias.
9
+ class OpenvoxStrings::Yard::Handlers::Puppet::DataTypeAliasHandler < OpenvoxStrings::Yard::Handlers::Puppet::Base
10
+ handles OpenvoxStrings::Yard::Parsers::Puppet::DataTypeAliasStatement
11
+
12
+ process do
13
+ # Register the object
14
+ object = OpenvoxStrings::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
+ OpenvoxStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openvox-strings/yard/handlers/helpers'
4
+ require 'openvox-strings/yard/handlers/puppet/base'
5
+ require 'openvox-strings/yard/parsers'
6
+ require 'openvox-strings/yard/code_objects'
7
+
8
+ # Implements the handler for Puppet defined types.
9
+ class OpenvoxStrings::Yard::Handlers::Puppet::DefinedTypeHandler < OpenvoxStrings::Yard::Handlers::Puppet::Base
10
+ handles OpenvoxStrings::Yard::Parsers::Puppet::DefinedTypeStatement
11
+
12
+ process do
13
+ # Register the object
14
+ object = OpenvoxStrings::Yard::CodeObjects::DefinedType.new(statement)
15
+ register object
16
+
17
+ # Log a warning if missing documentation
18
+ log.warn "Missing documentation for Puppet defined type '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? && object.tags.empty?
19
+
20
+ # Set the parameter types
21
+ set_parameter_types(object)
22
+
23
+ # Mark the defined type as public if it doesn't already have an api tag
24
+ object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api
25
+
26
+ # Warn if a summary longer than 140 characters was provided
27
+ OpenvoxStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary
28
+ end
29
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openvox-strings/yard/handlers/helpers'
4
+ require 'openvox-strings/yard/handlers/puppet/base'
5
+ require 'openvox-strings/yard/parsers'
6
+ require 'openvox-strings/yard/code_objects'
7
+
8
+ # Implements the handler for Puppet classes.
9
+ class OpenvoxStrings::Yard::Handlers::Puppet::FunctionHandler < OpenvoxStrings::Yard::Handlers::Puppet::Base
10
+ handles OpenvoxStrings::Yard::Parsers::Puppet::FunctionStatement
11
+
12
+ process do
13
+ # Register the object
14
+ object = OpenvoxStrings::Yard::CodeObjects::Function.new(statement.name, OpenvoxStrings::Yard::CodeObjects::Function::PUPPET)
15
+ object.source = statement.source
16
+ object.source_type = parser.parser_type
17
+ register object
18
+
19
+ # Log a warning if missing documentation
20
+ log.warn "Missing documentation for Puppet function '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? && object.tags.empty?
21
+
22
+ # Set the parameter tag types
23
+ set_parameter_types(object)
24
+
25
+ # Add a return tag
26
+ add_return_tag(object, statement.type)
27
+
28
+ # Set the parameters on the object
29
+ object.parameters = statement.parameters.map { |p| [p.name, p.value] }
30
+
31
+ # Mark the class as public if it doesn't already have an api tag
32
+ object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api
33
+
34
+ # Warn if a summary longer than 140 characters was provided
35
+ OpenvoxStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary
36
+ end
37
+
38
+ private
39
+
40
+ def add_return_tag(object, type = nil)
41
+ tag = object.tag(:return)
42
+ if tag
43
+ if (type && tag.types && tag.types.first) && (type != tag.types.first)
44
+ log.warn "Documented return type does not match return type in function definition near #{statement.file}:#{statement.line}."
45
+ end
46
+
47
+ tag.types = type ? [type] : tag.types || ['Any']
48
+ return
49
+ end
50
+ log.warn "Missing @return tag near #{statement.file}:#{statement.line}."
51
+ type ||= 'Any'
52
+ object.add_tag YARD::Tags::Tag.new(:return, '', type)
53
+ end
54
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openvox-strings/yard/handlers/helpers'
4
+ require 'openvox-strings/yard/handlers/puppet/base'
5
+ require 'openvox-strings/yard/parsers'
6
+ require 'openvox-strings/yard/code_objects'
7
+
8
+ # Implements the handler for Puppet classes.
9
+ class OpenvoxStrings::Yard::Handlers::Puppet::PlanHandler < OpenvoxStrings::Yard::Handlers::Puppet::Base
10
+ handles OpenvoxStrings::Yard::Parsers::Puppet::PlanStatement
11
+
12
+ process do
13
+ # Register the object
14
+ object = OpenvoxStrings::Yard::CodeObjects::Plan.new(statement)
15
+ register object
16
+
17
+ # Log a warning if missing documentation
18
+ log.warn "Missing documentation for Puppet plan '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? && object.tags.empty?
19
+
20
+ # Set the parameter types
21
+ set_parameter_types(object)
22
+
23
+ # Mark the class as public if it doesn't already have an api tag
24
+ object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api
25
+
26
+ # Warn if a summary longer than 140 characters was provided
27
+ OpenvoxStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary
28
+ end
29
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ripper'
4
+
5
+ # Implements the base handler for Ruby language handlers.
6
+ class OpenvoxStrings::Yard::Handlers::Ruby::Base < YARD::Handlers::Ruby::Base
7
+ # A regular expression for detecting the start of a Ruby heredoc.
8
+ # Note: the first character of the heredoc start may have been cut off by YARD.
9
+ HEREDOC_START = /^<?<[-~]?['"]?(\w+)['"]?[^\n]*\n?/
10
+
11
+ protected
12
+
13
+ # Converts the given Ruby AST node to a string representation.
14
+ # @param node The Ruby AST node to convert.
15
+ # @return [String] Returns a string representation of the node or nil if a string representation was not possible.
16
+ def node_as_string(node)
17
+ return nil unless node
18
+
19
+ case node.type
20
+ when :symbol, :symbol_literal
21
+ node.source[1..]
22
+ when :label
23
+ node.source[0..-2]
24
+ when :dyna_symbol
25
+ content = node.jump(:tstring_content)
26
+ content.nil? ? node.source : content.source
27
+ when :string_literal
28
+ content = node.jump(:tstring_content)
29
+ return content.source if content != node
30
+
31
+ # This attempts to work around a bug in YARD (https://github.com/lsegal/yard/issues/779)
32
+ # Check to see if the string source appears to have a heredoc open tag (or "most" of one)
33
+ # If so, remove the first line and the last line (if the latter contains the heredoc tag)
34
+ source = node.source
35
+ if source =~ HEREDOC_START
36
+ lines = source.split("\n")
37
+ source = lines[1..(lines.last.include?(Regexp.last_match(1)[0..-2]) ? -2 : -1)].join("\n") if lines.size > 1
38
+ end
39
+
40
+ source
41
+ when :regexp_literal
42
+ node.source
43
+ end
44
+ end
45
+
46
+ def get_name(statementobject, statementtype)
47
+ parameters = statementobject.parameters(false)
48
+ raise YARD::Parser::UndocumentableError, "Expected at least one parameter to #{statementtype} at #{statementobject.file}:#{statementobject.line}." if parameters.empty?
49
+
50
+ name = node_as_string(parameters.first)
51
+ 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
52
+
53
+ name
54
+ end
55
+ end
@@ -0,0 +1,411 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openvox-strings/yard/handlers/helpers'
4
+ require 'openvox-strings/yard/handlers/ruby/base'
5
+ require 'openvox-strings/yard/code_objects'
6
+ require 'openvox-strings/yard/util'
7
+
8
+ # Implements the handler for Puppet Data Types written in Ruby.
9
+ class OpenvoxStrings::Yard::Handlers::Ruby::DataTypeHandler < OpenvoxStrings::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
+ OpenvoxStrings::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 = OpenvoxStrings::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
+ 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
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
+ # TODO: Fix the rubocop violations in this file between the following rubocop:disable/enable lines
147
+ # rubocop:disable Naming/MethodName
148
+ # ----- The following methods are different/additions from the original Literal_evaluator
149
+ def literal_Object(o)
150
+ # Ignore any other object types
151
+ end
152
+
153
+ def literal_AccessExpression(o)
154
+ # Extract the raw text of the Access Expression
155
+ OpenvoxStrings::Yard::Util.ast_to_text(o)
156
+ end
157
+
158
+ def literal_QualifiedReference(o)
159
+ # Extract the raw text of the Qualified Reference
160
+ OpenvoxStrings::Yard::Util.ast_to_text(o)
161
+ end
162
+
163
+ # ----- The following methods are the same as the original Literal_evaluator
164
+ def literal_Factory(o)
165
+ literal(o.model)
166
+ end
167
+
168
+ def literal_Program(o)
169
+ literal(o.body)
170
+ end
171
+
172
+ def literal_LiteralString(o)
173
+ o.value
174
+ end
175
+
176
+ def literal_QualifiedName(o)
177
+ o.value
178
+ end
179
+
180
+ def literal_LiteralNumber(o)
181
+ o.value
182
+ end
183
+
184
+ def literal_UnaryMinusExpression(o)
185
+ -1 * literal(o.expr)
186
+ end
187
+
188
+ def literal_LiteralBoolean(o)
189
+ o.value
190
+ end
191
+
192
+ def literal_LiteralUndef(_o)
193
+ nil
194
+ end
195
+
196
+ def literal_LiteralDefault(_o)
197
+ :default
198
+ end
199
+
200
+ def literal_LiteralRegularExpression(o)
201
+ o.value
202
+ end
203
+
204
+ def literal_ConcatenatedString(o)
205
+ # use double quoted string value if there is no interpolation
206
+ throw :not_literal unless o.segments.size == 1 && o.segments[0].is_a?(Model::LiteralString)
207
+ o.segments[0].value
208
+ end
209
+
210
+ def literal_LiteralList(o)
211
+ o.values.map { |v| literal(v) }
212
+ end
213
+
214
+ def literal_LiteralHash(o)
215
+ o.entries.each_with_object({}) do |entry, result|
216
+ result[literal(entry.key)] = literal(entry.value)
217
+ end
218
+ end
219
+ # rubocop:enable Naming/MethodName
220
+ end
221
+
222
+ # Extracts the datatype attributes from a Puppet Data Type interface hash.
223
+ # Returns a Hash with a :types key (Array of data types for the parameter) and :default key (The default value of the parameter)
224
+ # @return Hash[Symbol => Hash] The Datatype Attributes as a hash
225
+ def extract_params(hash)
226
+ params_hash = {}
227
+ # Exit early if there are no entries in the hash
228
+ return params_hash if hash.nil? || hash['attributes'].nil? || hash['attributes'].empty?
229
+
230
+ hash['attributes'].each do |key, value|
231
+ data_type = nil
232
+ default = nil
233
+ if value.is_a?(String)
234
+ data_type = value
235
+ elsif value.is_a?(Hash)
236
+ data_type = value['type'] unless value['type'].nil?
237
+ default = value['value'] unless value['value'].nil?
238
+ end
239
+ data_type = [data_type] unless data_type.nil? || data_type.is_a?(Array)
240
+ params_hash[key] = { types: data_type, default: default }
241
+ end
242
+
243
+ params_hash
244
+ end
245
+
246
+ # Extracts the datatype functions from a Puppet Data Type interface hash.
247
+ # Returns a Hash with a :param_types key (Array of types for each parameter) and :return_type key (The return type of the function)
248
+ # @return Hash[Symbol => Hash] The Datatype Attributes as a hash
249
+ def extract_functions(object, hash)
250
+ funcs_hash = {}
251
+ # Exit early if there are no entries in the hash
252
+ return funcs_hash if hash.nil? || hash['functions'].nil? || hash['functions'].empty?
253
+
254
+ hash['functions'].each do |key, func_type|
255
+ func_hash = { param_types: [], return_type: nil }
256
+ begin
257
+ callable_type = Puppet::Pops::Types::TypeParser.singleton.parse(func_type)
258
+ if callable_type.is_a?(Puppet::Pops::Types::PCallableType)
259
+ func_hash[:param_types] = callable_type.param_types.map(&:to_s)
260
+ func_hash[:return_type] = callable_type.return_type.to_s
261
+ else
262
+ log.warn "The function definition for '#{key}' near #{object.file}:#{object.line} is not a Callable type"
263
+ end
264
+ rescue Puppet::ParseError => e
265
+ log.warn "Unable to parse the function definition for '#{key}' near #{object.file}:#{object.line}. #{e}"
266
+ end
267
+ funcs_hash[key] = func_hash
268
+ end
269
+ funcs_hash
270
+ end
271
+
272
+ # Validates and automatically fixes yard @param tags for the data type
273
+ def validate_param_tags!(object, actual_params_hash)
274
+ actual_param_names = actual_params_hash.keys
275
+ tagged_param_names = object.tags(:param).map(&:name)
276
+ # Log any errors
277
+ # Find attributes which are not documented
278
+ (actual_param_names - tagged_param_names).each do |item|
279
+ log.warn "Missing @param tag for attribute '#{item}' near #{object.file}:#{object.line}."
280
+ end
281
+ # Find param tags with no matching attribute
282
+ (tagged_param_names - actual_param_names).each do |item|
283
+ log.warn "The @param tag for '#{item}' has no matching attribute near #{object.file}:#{object.line}."
284
+ end
285
+ # Find param tags with a type that is different from the actual definition
286
+ object.tags(:param).reject { |tag| tag.types.nil? }.each do |tag|
287
+ next if actual_params_hash[tag.name].nil?
288
+
289
+ actual_data_type = actual_params_hash[tag.name][:types]
290
+ next if actual_data_type.nil?
291
+
292
+ 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
293
+ end
294
+
295
+ # Automatically fix missing @param tags
296
+ (actual_param_names - tagged_param_names).each do |name|
297
+ object.add_parameter(name, actual_params_hash[name][:types], actual_params_hash[name][:default])
298
+ end
299
+ # Remove extra param tags
300
+ object.docstring.delete_tag_if { |item| item.tag_name == 'param' && !actual_param_names.include?(item.name) }
301
+
302
+ # Set the type in the param tag
303
+ object.tags(:param).each do |tag|
304
+ next if actual_params_hash[tag.name].nil?
305
+
306
+ tag.types = actual_params_hash[tag.name][:types]
307
+ end
308
+ end
309
+
310
+ # Validates and automatically fixes yard @method! tags for the data type
311
+ def validate_methods!(object, actual_functions_hash)
312
+ actual_func_names = actual_functions_hash.keys
313
+ tagged_func_names = object.meths.map { |meth| meth.name.to_s }
314
+
315
+ # Log any errors
316
+ # Find functions which are not documented
317
+ (actual_func_names - tagged_func_names).each do |item|
318
+ log.warn "Missing @!method tag for function '#{item}' near #{object.file}:#{object.line}."
319
+ end
320
+ # Find functions which are not defined
321
+ (tagged_func_names - actual_func_names).each do |item|
322
+ log.warn "The @!method tag for '#{item}' has no matching function definition near #{object.file}:#{object.line}."
323
+ end
324
+ # Functions with the wrong return type
325
+ object.meths.each do |meth|
326
+ next unless actual_func_names.include?(meth.name.to_s)
327
+
328
+ return_tag = meth.docstring.tag(:return)
329
+ next if return_tag.nil?
330
+
331
+ actual_return_types = [actual_functions_hash[meth.name.to_s][:return_type]]
332
+ next if return_tag.types == actual_return_types
333
+
334
+ 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}"
335
+ return_tag.types = actual_return_types
336
+ end
337
+
338
+ # Automatically fix missing methods
339
+ (actual_func_names - tagged_func_names).each do |name|
340
+ object.add_function(name, actual_functions_hash[name][:return_type], actual_functions_hash[name][:param_types])
341
+ end
342
+ # Remove extra methods. Can't use `meths` as that's a derived property
343
+ object.children.reject! { |child| child.is_a?(YARD::CodeObjects::MethodObject) && !actual_func_names.include?(child.name.to_s) }
344
+
345
+ # Add the return type for the methods if missing
346
+ object.meths.each do |meth|
347
+ next unless meth.docstring.tag(:return).nil?
348
+
349
+ meth.docstring.add_tag(YARD::Tags::Tag.new(:return, '', actual_functions_hash[meth.name.to_s][:return_type]))
350
+ end
351
+
352
+ # Sync the method properties and add the return type for the methods if missing
353
+ object.meths.each do |meth|
354
+ validate_function_method!(object, meth, actual_functions_hash[meth.name.to_s])
355
+ next unless meth.docstring.tag(:return).nil?
356
+
357
+ meth.docstring.add_tag(YARD::Tags::Tag.new(:return, '', actual_functions_hash[meth.name.to_s][:return_type]))
358
+ end
359
+
360
+ # The default meth.signature assumes ruby invocation (e.g. def meth(...)) but this doesn't make sense for a
361
+ # Puppet Data Type function invocation. So instead we derive a signature from the method definition.
362
+ object.meths.each do |meth|
363
+ params = ''
364
+ params += "(#{meth.docstring.tags(:param).map(&:name).join(', ')})" unless meth.docstring.tags(:param).empty?
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 " \
382
+ "'#{meth.name}' that is defined near #{object.file}:#{object.line}. " \
383
+ "Expected only #{actual_function[:param_types].count} parameter/s"
384
+ true
385
+ else
386
+ false
387
+ end
388
+ else
389
+ false
390
+ end
391
+ end
392
+ end
393
+
394
+ # Add missing params
395
+ if meth.docstring.tags(:param).count < actual_function[:param_types].count
396
+ start = meth.docstring.tags(:param).count + 1
397
+ (start..actual_function[:param_types].count).each do |param_type_index| # Using 1-based index here instead of usual zero
398
+ meth.add_tag(YARD::Tags::Tag.new(:param, '', actual_function[:param_types][param_type_index - 1], "param#{param_type_index}"))
399
+ end
400
+ end
401
+
402
+ # Ensure the parameter types are correct
403
+ meth.docstring.tags(:param).each_with_index do |tag, actual_type_index|
404
+ actual_types = [actual_function[:param_types][actual_type_index]]
405
+ if tag.types != actual_types
406
+ 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}"
407
+ tag.types = actual_types
408
+ end
409
+ end
410
+ end
411
+ end