From f025efe557746cee57343239d9be563ac4990982 Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Sun, 11 Sep 2016 11:54:55 -0700 Subject: [PATCH] (PDOC-63) Implement a Puppet function YARD handler. This commit implements a YARD handler for Puppet functions and the associated code object and templates. --- lib/puppet-strings/yard.rb | 6 + lib/puppet-strings/yard/code_objects.rb | 1 + .../yard/code_objects/function.rb | 75 ++++ lib/puppet-strings/yard/handlers.rb | 2 + .../yard/handlers/puppet/function_handler.rb | 42 +++ .../yard/handlers/ruby/function_handler.rb | 357 ++++++++++++++++++ lib/puppet-strings/yard/tags.rb | 1 + lib/puppet-strings/yard/tags/overload_tag.rb | 94 +++++ .../html/full_list_puppet_function.erb | 10 + .../templates/default/fulldoc/html/setup.rb | 9 + .../templates/default/layout/html/objects.erb | 2 + .../templates/default/layout/html/setup.rb | 19 +- .../default/puppet_function/html/box_info.erb | 14 + .../default/puppet_function/html/header.erb | 1 + .../default/puppet_function/html/overview.erb | 18 + .../default/puppet_function/html/setup.rb | 5 + .../default/puppet_function/html/source.erb | 12 + .../default/tags/html/puppet_overload.erb | 12 + .../yard/templates/default/tags/setup.rb | 9 +- 19 files changed, 687 insertions(+), 2 deletions(-) create mode 100644 lib/puppet-strings/yard/code_objects/function.rb create mode 100644 lib/puppet-strings/yard/handlers/puppet/function_handler.rb create mode 100644 lib/puppet-strings/yard/handlers/ruby/function_handler.rb create mode 100644 lib/puppet-strings/yard/tags/overload_tag.rb create mode 100644 lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_function.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_function/html/box_info.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_function/html/header.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_function/html/overview.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_function/html/setup.rb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_function/html/source.erb create mode 100644 lib/puppet-strings/yard/templates/default/tags/html/puppet_overload.erb diff --git a/lib/puppet-strings/yard.rb b/lib/puppet-strings/yard.rb index ce3106b..7e61cde 100644 --- a/lib/puppet-strings/yard.rb +++ b/lib/puppet-strings/yard.rb @@ -26,6 +26,7 @@ module PuppetStrings::Yard # Ignore documentation on Puppet DSL calls # This prevents the YARD DSL parser from emitting warnings for Puppet's Ruby DSL + YARD::Handlers::Ruby::DSLHandlerMethods::IGNORE_METHODS['create_function'] = true YARD::Handlers::Ruby::DSLHandlerMethods::IGNORE_METHODS['newtype'] = true end end @@ -42,6 +43,7 @@ class YARD::CLI::Yardoc :puppet_defined_type, :puppet_type, :puppet_provider, + :puppet_function, ) end end @@ -66,6 +68,10 @@ class YARD::CLI::Stats output 'Puppet Providers', *type_statistics_all(:puppet_provider) end + def stats_for_puppet_functions + output 'Puppet Functions', *type_statistics_all(:puppet_function) + end + def output(name, data, undoc = nil) # Monkey patch output to accommodate our larger header widths @total += data if data.is_a?(Integer) && undoc diff --git a/lib/puppet-strings/yard/code_objects.rb b/lib/puppet-strings/yard/code_objects.rb index d2c60db..076eb90 100644 --- a/lib/puppet-strings/yard/code_objects.rb +++ b/lib/puppet-strings/yard/code_objects.rb @@ -4,4 +4,5 @@ module PuppetStrings::Yard::CodeObjects require 'puppet-strings/yard/code_objects/defined_type' require 'puppet-strings/yard/code_objects/type' require 'puppet-strings/yard/code_objects/provider' + require 'puppet-strings/yard/code_objects/function' end diff --git a/lib/puppet-strings/yard/code_objects/function.rb b/lib/puppet-strings/yard/code_objects/function.rb new file mode 100644 index 0000000..695b4aa --- /dev/null +++ b/lib/puppet-strings/yard/code_objects/function.rb @@ -0,0 +1,75 @@ +require 'puppet-strings/yard/code_objects/group' + +# Implements the group for Puppet functions. +class PuppetStrings::Yard::CodeObjects::Functions < PuppetStrings::Yard::CodeObjects::Group + # Gets the singleton instance of the group. + # @param [Symbol] type The function type to get the group for. + # @return Returns the singleton instance of the group. + def self.instance(type) + super("puppet_functions_#{type}".intern) + end + + # Gets the display name of the group. + # @param [Boolean] prefix whether to show a prefix. Ignored for Puppet group namespaces. + # @return [String] Returns the display name of the group. + def name(prefix = false) + 'Puppet Functions' + end +end + +# Implements the Puppet function code object. +class PuppetStrings::Yard::CodeObjects::Function < PuppetStrings::Yard::CodeObjects::Base + # Identifier for 3.x Ruby API functions + RUBY_3X = :ruby3x + # Identifier for 4.x Ruby API functions + RUBY_4X = :ruby4x + # Identifier for Puppet language functions + PUPPET = :puppet + + attr_accessor :parameters + + # Initializes a Puppet function code object. + # @param [String] name The name of the function. + # @param [Symbol] function_type The type of function (e.g. :ruby3x, :ruby4x, :puppet) + # @return [void] + def initialize(name, function_type) + super(PuppetStrings::Yard::CodeObjects::Functions.instance(function_type), name) + @parameters = [] + @function_type = function_type + end + + # Gets the type of the code object. + # @return Returns the type of the code object. + def type + :puppet_function + end + + # Gets the function type display string. + # @return Returns the function type display string. + def function_type + case @function_type + when RUBY_3X + 'Ruby 3.x API' + when RUBY_4X + 'Ruby 4.x API' + else + 'Puppet Language' + end + end + + # Gets the Puppet signature of the function. + # @return [String] Returns the Puppet signature of the function. + def signature + tags = self.tags(:param) + args = @parameters.map do |parameter| + name, default = parameter + tag = tags.find { |tag| tag.name == name } if tags + type = tag && tag.types ? "#{tag.type} " : 'Any ' + prefix = "#{name[0]}" if name.start_with?('*', '&') + name = name[1..-1] if prefix + default = " = #{default}" if default + "#{type}#{prefix}$#{name}#{default}" + end.join(', ') + @name.to_s + '(' + args + ')' + end +end diff --git a/lib/puppet-strings/yard/handlers.rb b/lib/puppet-strings/yard/handlers.rb index 655e309..8168343 100644 --- a/lib/puppet-strings/yard/handlers.rb +++ b/lib/puppet-strings/yard/handlers.rb @@ -4,11 +4,13 @@ module PuppetStrings::Yard::Handlers module Ruby require 'puppet-strings/yard/handlers/ruby/type_handler' require 'puppet-strings/yard/handlers/ruby/provider_handler' + require 'puppet-strings/yard/handlers/ruby/function_handler' end # The module for custom Puppet YARD handlers. module Puppet require 'puppet-strings/yard/handlers/puppet/class_handler' require 'puppet-strings/yard/handlers/puppet/defined_type_handler' + require 'puppet-strings/yard/handlers/puppet/function_handler' end end diff --git a/lib/puppet-strings/yard/handlers/puppet/function_handler.rb b/lib/puppet-strings/yard/handlers/puppet/function_handler.rb new file mode 100644 index 0000000..fbb9f56 --- /dev/null +++ b/lib/puppet-strings/yard/handlers/puppet/function_handler.rb @@ -0,0 +1,42 @@ +require 'puppet-strings/yard/handlers/puppet/base' +require 'puppet-strings/yard/parsers' +require 'puppet-strings/yard/code_objects' + +# Implements the handler for Puppet classes. +class PuppetStrings::Yard::Handlers::Puppet::FunctionHandler < PuppetStrings::Yard::Handlers::Puppet::Base + handles PuppetStrings::Yard::Parsers::Puppet::FunctionStatement + + process do + # Register the object + object = PuppetStrings::Yard::CodeObjects::Function.new(statement.name, PuppetStrings::Yard::CodeObjects::Function::PUPPET) + object.source = statement.source + object.source_type = parser.parser_type + register object + + # Log a warning if missing documentation + log.warn "Missing documentation for Puppet function '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? + + # Set the parameter tag types + set_parameter_types(object) + + # Add a return tag + add_return_tag(object) + + # Set the parameters on the object + object.parameters = statement.parameters.map { |p| [p.name, p.value] } + + # Mark the class as public if it doesn't already have an api tag + object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api + end + + private + def add_return_tag(object) + tag = object.tag(:return) + if tag + tag.types = ['Any'] unless tag.types + return + end + log.warn "Missing @return tag near #{statement.file}:#{statement.line}." + object.add_tag YARD::Tags::Tag.new(:return, '', 'Any') + end +end diff --git a/lib/puppet-strings/yard/handlers/ruby/function_handler.rb b/lib/puppet-strings/yard/handlers/ruby/function_handler.rb new file mode 100644 index 0000000..65c1420 --- /dev/null +++ b/lib/puppet-strings/yard/handlers/ruby/function_handler.rb @@ -0,0 +1,357 @@ +require 'puppet-strings/yard/handlers/ruby/base' +require 'puppet-strings/yard/code_objects' +require 'puppet/util/docs' + +# Implements the handler for Puppet functions written in Ruby. +class PuppetStrings::Yard::Handlers::Ruby::FunctionHandler < PuppetStrings::Yard::Handlers::Ruby::Base + # Represents the list of Puppet 4.x function API methods to support. + DISPATCH_METHOD_NAMES = %w( + param + required_param + optional_param + repeated_param + optional_repeated_param + required_repeated_param + block_param + required_block_param + optional_block_param + ).freeze + + namespace_only + handles method_call(:create_function) + handles method_call(:newfunction) + + process do + # Only accept calls to Puppet::Functions (4.x) or Puppet::Parser::Functions (3.x) + return unless statement.count > 1 + module_name = statement[0].source + return unless module_name == 'Puppet::Functions' || module_name == 'Puppet::Parser::Functions' + + # Create and register the function object + is_3x = module_name == 'Puppet::Parser::Functions' + object = PuppetStrings::Yard::CodeObjects::Function.new( + get_name, + is_3x ? PuppetStrings::Yard::CodeObjects::Function::RUBY_3X : PuppetStrings::Yard::CodeObjects::Function::RUBY_4X + ) + object.source = statement + register object + + # For 3x, parse the doc parameter for the docstring + # This must be done after the `register` call above because `register` always uses the statement's docstring + if is_3x + docstring = get_3x_docstring(object.name) + register_docstring(object, docstring, nil) if docstring + + # Default any typeless param tag to 'Any' + object.tags(:param).each do |tag| + tag.types = ['Any'] unless tag.types && !tag.types.empty? + end + + # Populate the parameters and the return tag + object.parameters = object.tags(:param).map{ |p| [p.name, nil] } + add_return_tag(object, statement.file, statement.line) + else + # For 4x, auto generate tags based on dispatch docstrings + add_tags(object) + end + + # Mark the function as public if it doesn't already have an api tag + object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api + end + + private + def get_name + parameters = statement.parameters(false) + raise YARD::Parser::UndocumentableError, "Expected at least one parameter to Puppet::Functions.create_function at #{statement.file}:#{statement.line}." if parameters.empty? + name = node_as_string(parameters.first) + 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 + name + end + + def add_tags(object) + log.warn "Missing documentation for Puppet function '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? + log.warn "The docstring for Puppet 4.x function '#{object.name}' contains @param tags near #{object.file}:#{object.line}: parameter documentation should be made on the dispatch call." unless object.tags(:param).empty? + log.warn "The docstring for Puppet 4.x function '#{object.name}' contains @return tags near #{object.file}:#{object.line}: return value documentation should be made on the dispatch call." unless object.tags(:return).empty? + log.warn "The docstring for Puppet 4.x function '#{object.name}' contains @overload tags near #{object.file}:#{object.line}: overload tags are automatically generated from the dispatch calls." unless object.tags(:overload).empty? + + # Delete any existing param/return/overload tags + object.docstring.delete_tags(:param) + object.docstring.delete_tags(:return) + object.docstring.delete_tags(:overload) + + block = statement.block + return unless block && block.count >= 2 + + # Get the unqualified name of the Puppet function + unqualified_name = object.name.to_s.split('::').last + + # Walk the block statements looking for dispatch calls and methods with the same name as the Puppet function + default = nil + block[1].children.each do |node| + if node.is_a?(YARD::Parser::Ruby::MethodCallNode) + add_overload_tag(object, node) + elsif node.is_a?(YARD::Parser::Ruby::MethodDefinitionNode) + default = node if node.method_name && node.method_name.source == unqualified_name + end + end + + # Create an overload for the default method if there is one + overloads = object.tags(:overload) + if overloads.empty? && default + add_method_overload(object, default) + overloads = object.tags(:overload) + end + + # If there's only one overload, move the tags to the object itself + if overloads.count == 1 + overload = overloads.first + object.parameters = overload.parameters + object.add_tag(*overload.tags) + object.docstring.delete_tags(:overload) + end + end + + def add_overload_tag(object, node) + # Look for a call to a dispatch method with a block + return unless node.is_a?(YARD::Parser::Ruby::MethodCallNode) && + node.method_name && + node.method_name.source == 'dispatch' && + node.parameters(false).count == 1 && + node.block && + node.block.count >= 2 + + overload_tag = PuppetStrings::Yard::Tags::OverloadTag.new(object.name, node.docstring || '') + param_tags = overload_tag.tags(:param) + + block = nil + node.block[1].children.each do |child| + next unless child.is_a?(YARD::Parser::Ruby::MethodCallNode) && child.method_name + + method_name = child.method_name.source + next unless DISPATCH_METHOD_NAMES.include?(method_name) + + # Check for block + if method_name.include?('block') + if block + log.warn "A duplicate block parameter was found for Puppet function '#{object.name}' at #{child.file}:#{child.line}." + next + end + + # Store the block; needs to be appended last + block = child + next + end + + # Ensure two parameters to parameter definition + parameters = child.parameters(false) + unless parameters.count == 2 + log.warn "Expected 2 arguments to '#{method_name}' call at #{child.file}:#{child.line}: parameter information may not be correct." + next + end + + add_param_tag( + overload_tag, + param_tags, + node_as_string(parameters[1]), + child.file, + child.line, + node_as_string(parameters[0]), + nil, # TODO: determine default from corresponding Ruby method signature? + method_name.include?('optional'), + method_name.include?('repeated') + ) + end + + # Handle the block parameter after others so it appears last in the list + if block + parameters = block.parameters(false) + if parameters.empty? + name = 'block' + type = 'Callable' + elsif parameters.count == 1 + name = node_as_string(parameters[0]) + type = 'Callable' + elsif parameters.count == 2 + type = node_as_string(parameters[0]) + name = node_as_string(parameters[1]) + else + log.warn "Unexpected number of arguments to block definition at #{block.file}:#{block.line}." + end + + if name && type + add_param_tag( + overload_tag, + param_tags, + name, + block.file, + block.line, + type, + nil, # TODO: determine default from corresponding Ruby method signature? + block.method_name.source.include?('optional'), + false, # Not repeated + true # Is block + ) + end + end + + # Add a return tag if missing + add_return_tag(overload_tag, node.file, node.line) + + # Validate that tags have parameters + validate_overload(overload_tag, node.file, node.line) + + object.add_tag overload_tag + end + + def add_method_overload(object, node) + overload_tag = PuppetStrings::Yard::Tags::OverloadTag.new(object.name, node.docstring || '') + param_tags = overload_tag.tags(:param) + + parameters = node.parameters + + # Populate the required parameters + params = parameters.unnamed_required_params + if params + params.each do |parameter| + add_param_tag( + overload_tag, + param_tags, + parameter.source, + parameter.file, + parameter.line + ) + end + end + + # Populate the optional parameters + params = parameters.unnamed_optional_params + if params + params.each do |parameter| + add_param_tag( + overload_tag, + param_tags, + parameter[0].source, + parameter.file, + parameter.line, + nil, + parameter[1].source, + true + ) + end + end + + # Populate the splat parameter + param = parameters.splat_param + if param + add_param_tag( + overload_tag, + param_tags, + param.source, + param.file, + param.line, + nil, + nil, + false, + true + ) + end + + # Populate the block parameter + param = parameters.block_param + if param + add_param_tag( + overload_tag, + param_tags, + param.source, + param.file, + param.line, + nil, + nil, + false, + false, + true + ) + end + + # Add a return tag if missing + add_return_tag(overload_tag, node.file, node.line) + + # Validate that tags have parameters + validate_overload(overload_tag, node.file, node.line) + + object.add_tag overload_tag + end + + def add_param_tag(object, tags, name, file, line, type = nil, default = nil, optional = false, repeated = false, block = false) + tag = tags.find { |tag| tag.name == name } if tags + log.warn "Missing @param tag for parameter '#{name}' near #{file}:#{line}." unless tag || object.docstring.all.empty? + log.warn "The @param tag for parameter '#{name}' should not contain a type specification near #{file}:#{line}: ignoring in favor of dispatch type information." if type && tag && tag.types && !tag.types.empty? + + if repeated + name = '*' + name + elsif block + name = '&' + name + end + + unless type + type = tag && tag.types ? tag.type : 'Any' + end + type = optional ? "Optional[#{type}]" : type + + object.parameters << [name, to_puppet_literal(default)] + + if tag + tag.name = name + tag.types = [type] + else + object.add_tag YARD::Tags::Tag.new(:param, '', type, name) + end + end + + def add_return_tag(object, file, line) + tag = object.tag(:return) + if tag + tag.types = ['Any'] unless tag.types + return + end + log.warn "Missing @return tag near #{file}:#{line}." + object.add_tag YARD::Tags::Tag.new(:return, '', 'Any') + end + + def validate_overload(overload, file, line) + # Validate that tags have matching parameters + overload.tags(:param).each do |tag| + next if overload.parameters.find { |p| tag.name == p[0] } + log.warn "The @param tag for parameter '#{tag.name}' has no matching parameter at #{file}:#{line}." + end + end + + def get_3x_docstring(name) + parameters = statement.parameters(false) + if parameters.count >= 2 + parameters[1].each do |kvp| + next unless kvp.count == 2 + next unless node_as_string(kvp[0]) == 'doc' + docstring = node_as_string(kvp[1]) + + log.error "Failed to parse docstring for 3.x Puppet function '#{name}' near #{statement.file}:#{statement.line}." and return nil unless docstring + return Puppet::Util::Docs.scrub(docstring) + end + end + + # Log a warning for missing docstring + log.warn "Missing documentation for Puppet function '#{name}' at #{statement.file}:#{statement.line}." + nil + end + + def to_puppet_literal(literal) + case literal + when 'nil' + 'undef' + when ':default' + 'default' + else + literal + end + end +end diff --git a/lib/puppet-strings/yard/tags.rb b/lib/puppet-strings/yard/tags.rb index ed0ffa9..dd46c76 100644 --- a/lib/puppet-strings/yard/tags.rb +++ b/lib/puppet-strings/yard/tags.rb @@ -2,4 +2,5 @@ module PuppetStrings::Yard::Tags require 'puppet-strings/yard/tags/parameter_directive' require 'puppet-strings/yard/tags/property_directive' + require 'puppet-strings/yard/tags/overload_tag' end diff --git a/lib/puppet-strings/yard/tags/overload_tag.rb b/lib/puppet-strings/yard/tags/overload_tag.rb new file mode 100644 index 0000000..50a505e --- /dev/null +++ b/lib/puppet-strings/yard/tags/overload_tag.rb @@ -0,0 +1,94 @@ +# Implements an overload tag for Puppet functions +# +# This differs from Yard's overload tag in that the signatures are formatted according to Puppet language rules. +class PuppetStrings::Yard::Tags::OverloadTag < YARD::Tags::Tag + attr_reader :parameters, :docstring + + # Initializes the overload tag. + # @param [String, Symbol] name The name of the function being overloaded. + # @param [String] docstring The docstring for the overload. + # @return [void] + def initialize(name, docstring) + super(:overload, nil) + @name = name.to_s + @parameters = [] + @docstring = YARD::Docstring.new(docstring) + end + + # Gets the signature of the overload. + # @return [String] Returns the signature of the overload. + def signature + tags = self.tags(:param) + args = @parameters.map do |parameter| + name, default = parameter + tag = tags.find { |tag| tag.name == name } if tags + type = tag && tag.types ? "#{tag.type} " : 'Any ' + prefix = "#{name[0]}" if name.start_with?('*', '&') + name = name[1..-1] if prefix + default = " = #{default}" if default + "#{type}#{prefix}$#{name}#{default}" + end.join(', ') + @name + '(' + args + ')' + end + + # Adds a tag to the overload's docstring. + # @param [YARD::Tag] tag The tag to add to the overload's docstring. + # @return [void] + def add_tag(tag) + @docstring.add_tag(tag) + end + + # Gets the first tag of the given name. + # @param [String, Symbol] name The name of the tag. + # @return [YARD::Tag] Returns the first tag if found or nil if not found. + def tag(name) + @docstring.tag(name) + end + + # Gets all tags or tags of a given name. + # @param [String, Symbol] name The name of the tag to get or nil for all tags. + # @return [Array] Returns an array of tags. + def tags(name = nil) + @docstring.tags(name) + end + + # Determines if a tag with the given name is present. + # @param [String, Symbol] name The tag name. + # @return [Boolean] Returns true if there is at least one tag with the given name or false if not. + def has_tag?(name) + @docstring.has_tag?(name) + end + + # Sets the object associated with this tag. + # @param [Object] value The object to associate with this tag. + # @return [void] + def object=(value) + super(value) + @docstring.object = value + @docstring.tags.each {|tag| tag.object = value } + end + + # Responsible for forwarding method calls to the associated object. + # @param [Symbol] method_name The method being invoked. + # @param [Array] args The args passed to the method. + # @param block The block passed to the method. + # @return Returns what the method call on the object would return. + def method_missing(method_name, *args, &block) + return object.send(method_name, *args, &block) if object.respond_to? method_name + super + end + + # Determines if the associated object responds to the give missing method name. + # @param [Symbol, String] method_name The name of the method to check. + # @param [Boolean] include_all True to include all methods in the check or false for only public methods. + # @return [Boolean] Returns true if the object responds to the method or false if not. + def respond_to_missing?(method_name, include_all = false) + object.respond_to?(method_name, include_all) || super + end + + # Gets the type of the object associated with this tag. + # @return [Symbol] Returns the type of the object associated with this tag. + def type + object.type + end +end diff --git a/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_function.erb b/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_function.erb new file mode 100644 index 0000000..237a747 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_function.erb @@ -0,0 +1,10 @@ +<% even = false %> +<% @items.each do |item| %> +
  • +
    + <%= linkify item, h(item.name(false)) %> + <%= item.function_type %> +
    +
  • + <% even = !even %> +<% end %> diff --git a/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb b/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb index cdc18c5..a71e117 100644 --- a/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb +++ b/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb @@ -34,6 +34,15 @@ def generate_puppet_provider_list generate_list_contents end +# Generates the searchable Puppet function list. +# @return [void] +def generate_puppet_function_list + @items = Registry.all(:puppet_function).sort_by {|f| f.name.to_s } + @list_title = 'Puppet Function List' + @list_type = 'puppet_function' + generate_list_contents +end + # Generates the searchable Ruby method list. # @return [void] def generate_method_list diff --git a/lib/puppet-strings/yard/templates/default/layout/html/objects.erb b/lib/puppet-strings/yard/templates/default/layout/html/objects.erb index ac5c815..afc6356 100644 --- a/lib/puppet-strings/yard/templates/default/layout/html/objects.erb +++ b/lib/puppet-strings/yard/templates/default/layout/html/objects.erb @@ -21,6 +21,8 @@ (<%= obj.namespace.path %>) <% elsif obj.type == :puppet_provider %> (Resource type: <%= obj.type_name %>) + <% elsif obj.type == :puppet_function %> + (<%= obj.function_type %>) <% end %> <% end %> diff --git a/lib/puppet-strings/yard/templates/default/layout/html/setup.rb b/lib/puppet-strings/yard/templates/default/layout/html/setup.rb index 91a79ac..703d2f5 100644 --- a/lib/puppet-strings/yard/templates/default/layout/html/setup.rb +++ b/lib/puppet-strings/yard/templates/default/layout/html/setup.rb @@ -4,7 +4,7 @@ def init case object when '_index.html' @page_title = options.title - sections :layout, [:index, [:listing, [:classes, :defined_types, :types, :providers, :files, :objects]]] + sections :layout, [:index, [:listing, [:classes, :defined_types, :types, :providers, :functions, :files, :objects]]] else super end @@ -42,6 +42,10 @@ def layout @nav_url = url_for_list('puppet_provider') @page_title = "Provider: #{object.name}" @path = object.path + when PuppetStrings::Yard::CodeObjects::Function + @nav_url = url_for_list('puppet_function') + @page_title = "Puppet Function: #{object.name} (#{object.function_type})" + @path = object.path else @path = object.path end @@ -73,6 +77,11 @@ def create_menu_lists title: 'Providers', search_title: 'Providers' }, + { + type: 'puppet_function', + title: 'Puppet Functions', + search_title: 'Puppet Functions' + }, { type: 'class', title: 'Ruby Classes', @@ -146,6 +155,14 @@ def providers erb(:objects) end +# Renders the functions section. +# @return [String] Returns the rendered section. +def functions + @title = 'Puppet Function Listing A-Z' + @objects_by_letter = objects_by_letter(:puppet_function) + erb(:objects) +end + # Renders the objects section. # @return [String] Returns the rendered section. def objects diff --git a/lib/puppet-strings/yard/templates/default/puppet_function/html/box_info.erb b/lib/puppet-strings/yard/templates/default/puppet_function/html/box_info.erb new file mode 100644 index 0000000..3f1bd40 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_function/html/box_info.erb @@ -0,0 +1,14 @@ +
    +
    +
    Defined in:
    +
    + <%= object.file %><% if object.files.size > 1 %>,
    + <%= object.files[1..-1].map {|f| f.first }.join(",
    ") %>
    + <% end %> + + +
    +
    Function type:
    +
    <%= object.function_type %>
    +
    + diff --git a/lib/puppet-strings/yard/templates/default/puppet_function/html/header.erb b/lib/puppet-strings/yard/templates/default/puppet_function/html/header.erb new file mode 100644 index 0000000..db96389 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_function/html/header.erb @@ -0,0 +1 @@ +

    Puppet Function: <%= object.name %>

    diff --git a/lib/puppet-strings/yard/templates/default/puppet_function/html/overview.erb b/lib/puppet-strings/yard/templates/default/puppet_function/html/overview.erb new file mode 100644 index 0000000..8cd6ca4 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_function/html/overview.erb @@ -0,0 +1,18 @@ +

    Overview

    +
    + <% unless object.has_tag? :overload %> +
    + + + <%= "#{h(object.signature)} ⇒ #{signature_types(object, false)}" %> + + +
    + <% end %> +
    +
    + <%= htmlify(object.docstring) %> +
    +
    + <%= yieldall %> +
    diff --git a/lib/puppet-strings/yard/templates/default/puppet_function/html/setup.rb b/lib/puppet-strings/yard/templates/default/puppet_function/html/setup.rb new file mode 100644 index 0000000..d20b4b6 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_function/html/setup.rb @@ -0,0 +1,5 @@ +# Initializes the template. +# @return [void] +def init + sections :header, :box_info, :overview, [T('tags'), :source] +end diff --git a/lib/puppet-strings/yard/templates/default/puppet_function/html/source.erb b/lib/puppet-strings/yard/templates/default/puppet_function/html/source.erb new file mode 100644 index 0000000..0fd3c5e --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_function/html/source.erb @@ -0,0 +1,12 @@ +
    + + + + + +
    +
    <%= "\n\n\n" %><%= h format_lines(object) %>
    +
    +
    # File '<%= h object.file %>'<% if object.line %>, line <%= object.line %><% end %><%= "\n\n" %><%= html_syntax_highlight object.source %>
    +
    +
    diff --git a/lib/puppet-strings/yard/templates/default/tags/html/puppet_overload.erb b/lib/puppet-strings/yard/templates/default/tags/html/puppet_overload.erb new file mode 100644 index 0000000..3d12d59 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/tags/html/puppet_overload.erb @@ -0,0 +1,12 @@ +<% if object.has_tag?(:overload) && object.tags(:overload).any? {|o| !o.docstring.blank? } %> +

    Overloads:

    + +<% end %> diff --git a/lib/puppet-strings/yard/templates/default/tags/setup.rb b/lib/puppet-strings/yard/templates/default/tags/setup.rb index 2166fdf..888d05a 100644 --- a/lib/puppet-strings/yard/templates/default/tags/setup.rb +++ b/lib/puppet-strings/yard/templates/default/tags/setup.rb @@ -4,5 +4,12 @@ def param tag(:param) if object.type == :method || object.type == :puppet_class || - object.type == :puppet_defined_type + object.type == :puppet_defined_type || + object.type == :puppet_function +end + +# Renders the overload section. +# @return [String] Returns the rendered section. +def overload + erb(if object.type == :puppet_function then :puppet_overload else :overload end) end