Skip to content

Commit 8a802f2

Browse files
committed
(PDOC-226) Add Puppet Data Type Alias documentation
Previously Puppet-Strings could not document Data Type Aliases. This commit: * Updates the puppet parser to interpret TypeAlias statements. * Adds a DataTypeAlias code object and handler to document the Type Alias statement correctly. * Adds tests for puppet parsing to ensure the Yard Code Object is populated correctly * Adds support for JSON, Markdown and HTML rendering. Note that JSON separates Data Types from Data Type Aliases whereas Markdown and HTML rendering lump them together. This is because from a human documentation point of view (i.e Mardown or HTML) they are very similar things. Much like Puppet V3 vs V4 functions. However the JSON output can be used by other systems so it is important to diffentiate them as they are different from a code inspection point of view. * Adds tests for JSON and Markdown rendering
1 parent 7493d88 commit 8a802f2

File tree

29 files changed

+373
-16
lines changed

29 files changed

+373
-16
lines changed

JSON.md

+27-12
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,19 @@ puppet strings generate --format json
99
Document Schema
1010
===============
1111

12-
At the top level, there are eight arrays in the JSON document:
13-
14-
| Document Key | Description |
15-
| ---------------- | ----------------------------------------------------------------------------- |
16-
| puppet_classes | The list of Puppet classes that were parsed. |
17-
| data_types | The list of data types that were parsed. |
18-
| defined_types | The list of defined types that were parsed. |
19-
| resource_types | The list of resource types that were parsed. |
20-
| providers | The list of resource providers that were parsed. |
21-
| puppet_functions | The list of Puppet functions (4.x, 4.x and Puppet language) that were parsed. |
22-
| puppet_tasks | The list of Puppet tasks that were parsed. |
23-
| puppet_plans | The list of Puppet plans that were parsed. |
12+
At the top level, there are nine arrays in the JSON document:
13+
14+
| Document Key | Description |
15+
| ----------------- | ----------------------------------------------------------------------------- |
16+
| puppet_classes | The list of Puppet classes that were parsed. |
17+
| data_types | The list of data types that were parsed. |
18+
| data_type_aliases | | The list of data types that were parsed. |
19+
| defined_types | The list of defined types that were parsed. |
20+
| resource_types | The list of resource types that were parsed. |
21+
| providers | The list of resource providers that were parsed. |
22+
| puppet_functions | The list of Puppet functions (4.x, 4.x and Puppet language) that were parsed. |
23+
| puppet_tasks | The list of Puppet tasks that were parsed. |
24+
| puppet_plans | The list of Puppet plans that were parsed. |
2425

2526
Puppet Classes
2627
--------------
@@ -51,6 +52,20 @@ Each entry in the `data_types` list is an object with the following attributes:
5152
| defaults | The map of parameter names to default values. |
5253
| source | The ruby source code for the data type. (Not Implemented) |
5354

55+
Data Type Aliases
56+
-----------------
57+
58+
Each entry in the `data_type_aliases` list is an object with the following attributes:
59+
60+
| Attribute Key | Description |
61+
| ------------- | ----------------------------------------------------------------- |
62+
| name | The name of the data type. |
63+
| file | The file defining the data type. |
64+
| line | The line where the data type is defined. |
65+
| docstring | The *DocString* object for the data type (see below). |
66+
| alias_of | The actual type this is an alias of. |
67+
| source | The Puppet source code for the data type alias. (Not Implemented) |
68+
5469
Defined Types
5570
-------------
5671

lib/puppet-strings/json.rb

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ def self.render(file = nil)
99
document = {
1010
puppet_classes: YARD::Registry.all(:puppet_class).sort_by!(&:name).map!(&:to_hash),
1111
data_types: YARD::Registry.all(:puppet_data_type).sort_by!(&:name).map!(&:to_hash),
12+
data_type_aliases: YARD::Registry.all(:puppet_data_type_alias).sort_by!(&:name).map!(&:to_hash),
1213
defined_types: YARD::Registry.all(:puppet_defined_type).sort_by!(&:name).map!(&:to_hash),
1314
resource_types: YARD::Registry.all(:puppet_type).sort_by!(&:name).map!(&:to_hash),
1415
providers: YARD::Registry.all(:puppet_provider).sort_by!(&:name).map!(&:to_hash),

lib/puppet-strings/markdown/data_type.rb

+4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
require 'puppet-strings/markdown/base'
22

33
module PuppetStrings::Markdown
4+
# This class encapsualtes ruby data types and puppet type aliases
45
class DataType < Base
6+
attr_reader :alias_of
7+
58
def initialize(registry)
69
@template = 'data_type.erb'
710
super(registry, 'data type')
11+
@alias_of = registry[:alias_of] unless registry[:alias_of].nil?
812
end
913

1014
def render

lib/puppet-strings/markdown/data_types.rb

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ module DataTypes
55

66
# @return [Array] list of data types
77
def self.in_dtypes
8-
arr = YARD::Registry.all(:puppet_data_type).sort_by!(&:name).map!(&:to_hash)
8+
arr = YARD::Registry.all(:puppet_data_type).map!(&:to_hash)
9+
arr.concat(YARD::Registry.all(:puppet_data_type_alias).map!(&:to_hash))
10+
11+
arr.sort! { |a,b| a[:name] <=> b[:name] }
912
arr.map! { |a| PuppetStrings::Markdown::DataType.new(a) }
1013
end
1114

lib/puppet-strings/markdown/templates/data_type.erb

+4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@
4343
```
4444

4545
<% end -%>
46+
<% end -%>
47+
<% if alias_of -%>
48+
Alias of `<%= alias_of %>`
49+
4650
<% end -%>
4751
<% if params -%>
4852
#### Parameters

lib/puppet-strings/yard.rb

+5
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ def all_objects
4747
:class,
4848
:puppet_class,
4949
:puppet_data_type,
50+
:puppet_data_type_alias,
5051
:puppet_defined_type,
5152
:puppet_type,
5253
:puppet_provider,
@@ -69,6 +70,10 @@ def stats_for_puppet_data_types
6970
output 'Puppet Data Types', *type_statistics_all(:puppet_data_type)
7071
end
7172

73+
def stats_for_puppet_data_type_aliases
74+
output 'Puppet Data Type Aliases', *type_statistics_all(:puppet_data_type_alias)
75+
end
76+
7277
def stats_for_puppet_defined_types
7378
output 'Puppet Defined Types', *type_statistics_all(:puppet_defined_type)
7479
end

lib/puppet-strings/yard/code_objects.rb

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
module PuppetStrings::Yard::CodeObjects
33
require 'puppet-strings/yard/code_objects/class'
44
require 'puppet-strings/yard/code_objects/data_type'
5+
require 'puppet-strings/yard/code_objects/data_type_alias'
56
require 'puppet-strings/yard/code_objects/defined_type'
67
require 'puppet-strings/yard/code_objects/type'
78
require 'puppet-strings/yard/code_objects/provider'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
require 'puppet-strings/yard/code_objects/group'
2+
require 'puppet-strings/yard/util'
3+
4+
# Implements the group for Puppet DataTypeAliases.
5+
class PuppetStrings::Yard::CodeObjects::DataTypeAliases < PuppetStrings::Yard::CodeObjects::Group
6+
# Gets the singleton instance of the group.
7+
# @return Returns the singleton instance of the group.
8+
def self.instance
9+
super(:puppet_data_type_aliases)
10+
end
11+
12+
# Gets the display name of the group.
13+
# @param [Boolean] prefix whether to show a prefix. Ignored for Puppet group namespaces.
14+
# @return [String] Returns the display name of the group.
15+
def name(prefix = false)
16+
'Puppet Data Type Aliases'
17+
end
18+
end
19+
20+
# Implements the Puppet DataTypeAlias code object.
21+
class PuppetStrings::Yard::CodeObjects::DataTypeAlias < PuppetStrings::Yard::CodeObjects::Base
22+
attr_reader :statement
23+
attr_accessor :alias_of
24+
25+
# Initializes a Puppet data type alias code object.
26+
# @param [PuppetStrings::Parsers::DataTypeAliasStatement] statement The data type alias statement that was parsed.
27+
# @return [void]
28+
def initialize(statement)
29+
@statement = statement
30+
@alias_of = statement.alias_of
31+
super(PuppetStrings::Yard::CodeObjects::DataTypeAliases.instance, statement.name)
32+
end
33+
34+
# Gets the type of the code object.
35+
# @return Returns the type of the code object.
36+
def type
37+
:puppet_data_type_alias
38+
end
39+
40+
# Gets the source of the code object.
41+
# @return Returns the source of the code object.
42+
def source
43+
# Not implemented, but would be nice!
44+
nil
45+
end
46+
47+
# Converts the code object to a hash representation.
48+
# @return [Hash] Returns a hash representation of the code object.
49+
def to_hash
50+
hash = {}
51+
hash[:name] = name
52+
hash[:file] = file
53+
hash[:line] = line
54+
hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring)
55+
hash[:alias_of] = alias_of
56+
hash
57+
end
58+
end

lib/puppet-strings/yard/handlers.rb

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module JSON
1818
# The module for custom Puppet YARD handlers.
1919
module Puppet
2020
require 'puppet-strings/yard/handlers/puppet/class_handler'
21+
require 'puppet-strings/yard/handlers/puppet/data_type_alias_handler'
2122
require 'puppet-strings/yard/handlers/puppet/defined_type_handler'
2223
require 'puppet-strings/yard/handlers/puppet/function_handler'
2324
require 'puppet-strings/yard/handlers/puppet/plan_handler'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
require 'puppet-strings/yard/handlers/helpers'
2+
require 'puppet-strings/yard/handlers/puppet/base'
3+
require 'puppet-strings/yard/parsers'
4+
require 'puppet-strings/yard/code_objects'
5+
6+
# Implements the handler for Puppet Data Type Alias.
7+
class PuppetStrings::Yard::Handlers::Puppet::DataTypeAliasHandler < PuppetStrings::Yard::Handlers::Puppet::Base
8+
handles PuppetStrings::Yard::Parsers::Puppet::DataTypeAliasStatement
9+
10+
process do
11+
# Register the object
12+
object = PuppetStrings::Yard::CodeObjects::DataTypeAlias.new(statement)
13+
register object
14+
15+
# Log a warning if missing documentation
16+
log.warn "Missing documentation for Puppet type alias '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? && object.tags.empty?
17+
18+
# Mark the class as public if it doesn't already have an api tag
19+
object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api
20+
21+
# Warn if a summary longer than 140 characters was provided
22+
PuppetStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary
23+
end
24+
end

lib/puppet-strings/yard/parsers/puppet/parser.rb

+6
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ def transform_PlanDefinition(o) # rubocop:disable Naming/UncommunicativeMethodPa
7676
statement
7777
end
7878

79+
def transform_TypeAlias(o) # rubocop:disable Naming/UncommunicativeMethodParamName
80+
statement = PuppetStrings::Yard::Parsers::Puppet::DataTypeAliasStatement.new(o, @file)
81+
statement.extract_docstring(@lines)
82+
statement
83+
end
84+
7985
def transform_Object(o) # rubocop:disable Naming/UncommunicativeMethodParamName
8086
# Ignore anything else (will be compacted out of the resulting array)
8187
end

lib/puppet-strings/yard/parsers/puppet/statement.rb

+25
Original file line numberDiff line numberDiff line change
@@ -165,4 +165,29 @@ def initialize(object, file)
165165
end
166166
end
167167

168+
# Implements the Puppet data type alias statement.
169+
class DataTypeAliasStatement < Statement
170+
attr_reader :name
171+
attr_reader :alias_of
172+
173+
# Initializes the Puppet data type alias statement.
174+
# @param [Puppet::Pops::Model::TypeAlias] object The model object for the type statement.
175+
# @param [String] file The file containing the statement.
176+
def initialize(object, file)
177+
super(object, file)
178+
179+
type_expr = object.type_expr
180+
case type_expr
181+
when Puppet::Pops::Model::AccessExpression
182+
# TODO: I don't like rebuilding the source from the AST, but AccessExpressions don't expose the original source
183+
@alias_of = ::Puppet::Pops::Adapters::SourcePosAdapter.adapt(type_expr.left_expr).extract_text + '['
184+
@alias_of << type_expr.keys.map { |key| ::Puppet::Pops::Adapters::SourcePosAdapter.adapt(key).extract_text }.join(', ')
185+
@alias_of << ']'
186+
else
187+
adapter = ::Puppet::Pops::Adapters::SourcePosAdapter.adapt(type_expr)
188+
@alias_of = adapter.extract_text
189+
end
190+
@name = object.name
191+
end
192+
end
168193
end

lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_data_type.erb

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<li id="object_<%=item.path%>" class="<%= even ? 'even' : 'odd' %>">
44
<div class="item">
55
<%= linkify item, h(item.name(false)) %>
6+
<% if item.type == :puppet_data_type_alias %><small>Alias</small><% end %>
67
</div>
78
</li>
89
<% even = !even %>

lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def generate_puppet_class_list
1010
# Generates the searchable Puppet data type list.
1111
# @return [void]
1212
def generate_puppet_data_type_list
13-
@items = Registry.all(:puppet_data_type).sort_by {|dt| dt.name.to_s }
13+
@items = Registry.all(:puppet_data_type, :puppet_data_type_alias).sort_by {|dt| dt.name.to_s }
1414
@list_title = 'Data Type List'
1515
@list_type = 'puppet_data_type'
1616
generate_list_contents

lib/puppet-strings/yard/templates/default/layout/html/objects.erb

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
<small>(Resource type: <%= obj.type_name %>)</small>
2424
<% elsif obj.type == :puppet_function %>
2525
<small>(<%= obj.function_type %>)</small>
26+
<% elsif obj.type == :puppet_data_type_alias %>
27+
<small>(Alias)</small>
2628
<% end %>
2729
</li>
2830
<% end %>

lib/puppet-strings/yard/templates/default/layout/html/setup.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def layout
3030
@nav_url = url_for_list('puppet_class')
3131
@page_title = "Puppet Class: #{object.name}"
3232
@path = object.path
33-
when PuppetStrings::Yard::CodeObjects::DataType
33+
when PuppetStrings::Yard::CodeObjects::DataType, PuppetStrings::Yard::CodeObjects::DataTypeAlias
3434
@nav_url = url_for_list('puppet_data_type')
3535
@page_title = "Data Type: #{object.name}"
3636
@path = object.path
@@ -168,7 +168,7 @@ def classes
168168
# @return [String] Returns the rendered section.
169169
def data_types
170170
@title = 'Data Type Listing A-Z'
171-
@objects_by_letter = objects_by_letter(:puppet_data_type)
171+
@objects_by_letter = objects_by_letter(:puppet_data_type, :puppet_data_type_alias)
172172
erb(:objects)
173173
end
174174

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<% if @alias_of && !@alias_of.empty? %>
2+
<div class="tags">
3+
<p class="tag_title"><%= @tag_title %></p>
4+
<div class="docstring">
5+
<div class="discussion">
6+
<pre class="code"><span class="info"><%= @alias_of %></span></pre>
7+
</div>
8+
</div>
9+
</div>
10+
<% end %>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<div class="box_info">
2+
<dl>
3+
<dt>Defined in:</dt>
4+
<dd>
5+
<%= object.file %><% if object.files.size > 1 %><span class="defines">,<br />
6+
<%= object.files[1..-1].map {|f| f.first }.join(",<br /> ") %></div>
7+
<% end %>
8+
</dd>
9+
</dl>
10+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>Puppet Data Type Alias: <%= object.name %></h1>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<% object.tags(:note).each do |tag| %>
2+
<div class="note notetag">
3+
<strong>Note:</strong>
4+
<%= htmlify_line tag.text %>
5+
</div>
6+
<% end %>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<h2>Overview</h2>
2+
<div class="docstring">
3+
<div class="discussion">
4+
<%= htmlify(object.docstring) %>
5+
</div>
6+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Initializes the template.
2+
# @return [void]
3+
def init
4+
sections :header, :box_info, :summary, :overview, :alias_of, :note, :todo, T('tags'), :source
5+
end
6+
7+
# Renders the alias_of section.
8+
# @return [String] Returns the rendered section.
9+
def alias_of
10+
# Properties are the same thing as parameters (from the documentation standpoint),
11+
# so reuse the same template but with a different title and data source.
12+
#@parameters = object.properties || []
13+
#@parameters.sort_by! { |p| p.name }
14+
@tag_title = 'Alias of'
15+
@alias_of = object.alias_of
16+
erb(:alias_of)
17+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<div class="method_details_list">
2+
<table class="source_code">
3+
<tr>
4+
<td>
5+
<pre class="lines"><%= "\n\n\n" %><%= h format_lines(object) %></pre>
6+
</td>
7+
<td>
8+
<pre class="code"><span class="info file"># File '<%= h object.file %>'<% if object.line %>, line <%= object.line %><% end %></span><%= "\n\n" %><%= html_syntax_highlight object.source %></pre>
9+
</td>
10+
</tr>
11+
</table>
12+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<% if object.docstring.has_tag?(:summary) %>
2+
<h2>Summary</h2>
3+
<%= object.docstring.tag(:summary).text %>
4+
<% end %>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<% object.tags(:todo).each do |tag| %>
2+
<div class="note todo">
3+
<strong>TODO:</strong>
4+
<%= htmlify_line tag.text %>
5+
</div>
6+
<% end %>

0 commit comments

Comments
 (0)