From 5f60c99bfdfdf237d9b3076858d9d7ff6d231f69 Mon Sep 17 00:00:00 2001 From: Hailee Kenney Date: Thu, 8 Jan 2015 14:58:21 -0800 Subject: [PATCH 1/5] (PDOC-24) Add custom header for puppet functions Prior to this commit, all the HTML for puppet functions was just generated by YARD as if it were a regular method. Since we ultimately want to have our own custom templates, lay out the groundwork for customizing the templates for functions and update the page headers to be more readable. At the moment the code is functional but contains a lot of duplication which needs to be cleaned up. --- .../default/puppetnamespace/html/box_info.erb | 11 ++ .../puppetnamespace/html/docstring.erb | 95 ++++++++++++++ .../default/puppetnamespace/html/header.erb | 5 + .../puppetnamespace/html/method_summary.erb | 28 +++++ .../default/puppetnamespace/setup.rb | 119 +++++++++++++++++- 5 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/box_info.erb create mode 100644 lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/docstring.erb create mode 100644 lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/header.erb create mode 100644 lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/method_summary.erb diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/box_info.erb b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/box_info.erb new file mode 100644 index 0000000..1780c32 --- /dev/null +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/box_info.erb @@ -0,0 +1,11 @@ +
+
Defined in:
+
+ <% @source_files.each do |file| %> + <%= file[0] %>: + <%= file[1] %> +
+ <% end %> +
+
+
diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/docstring.erb b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/docstring.erb new file mode 100644 index 0000000..cb5110a --- /dev/null +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/docstring.erb @@ -0,0 +1,95 @@ +<% @class_details.each do |func| %> +

> + <%= func[:name] %> +

+
+
+

<%= htmlify(func[:desc]) %>

+
+
+
+ <% if func[:examples] != {}%> +
+

Examples:

+ <% func[:examples].each do |title, text| %> +

<%= title %>

+
<%= text %>
+ <% end %> +
+ <% end %> + <% if func[:since] %> +

Since:

+ + <% end %> + <% if func[:return] %> +

Returns:

+ + <% end %> + <% if func[:params] != nil %> +

Parameters:

+
+
    + <% func[:params].each do |param| %> +
  • + <% if !param[:exists?] %> + + <% end %> + <%= param[:name] %> + <%# TODO: Linkify defaults that resolve to variable declarations in a different scope. %> + + <% if param[:types] %> + (<% param[:types].each do |type| %> + + <% if param[:types].last != type %> + <%= type %>, + <% else %> + <%= type %> + <% end %> + + <% end %>) + <% else %> + (TBD) + <% end %> + + <% if param[:desc]%> + — +
    +

    <%= param[:desc] %>

    +
    + <% end %> + <% if !param[:exists] %> +
    + <% end %> +
  • + <% end %> +
+
+ <% end %> +
+<% end %> diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/header.erb b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/header.erb new file mode 100644 index 0000000..74b3dba --- /dev/null +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/header.erb @@ -0,0 +1,5 @@ +
+

+ <%= @header_text %> +

+
diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/method_summary.erb b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/method_summary.erb new file mode 100644 index 0000000..6d61392 --- /dev/null +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/method_summary.erb @@ -0,0 +1,28 @@ +

Available Functions

+ diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb index cf37b36..a310566 100644 --- a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb @@ -3,5 +3,122 @@ include T('default/module') def init sections :header, :box_info, :pre_docstring, T('docstring'), :method_summary, [:item_summary], - :method_details_list, [T('method_details')] + :method_details_list, :method_details + + @methods = object.children +end + +def header + if @methods[0]['puppet_4x_function'] + @header_text = "Puppet 4 Functions" + else + @header_text = "Puppet 3 Functions" + end + + erb(:header) +end + +def box_info + @source_files = [] + + @methods.each do |method| + # extract the file name and line number for each method + file_name = method.files[0][0] + line_number = method.files[0][1] + + @source_files.push([method.name, "#{file_name} (#{line_number})"]) + end + + erb(:box_info) +end + +def method_summary + @method_details = [] + + @methods.each do |method| + # If there are multiple sentences in the method description, only + # use the first one for the summary. If the author did not include + # any periods in their summary, include the whole thing + first_sentence = method.docstring.match(/^(.*?)\./) + brief_summary = first_sentence ? first_sentence : method.docstring + + return_tag = method.tags.find { |tag| tag.tag_name == "return"} + return_types = return_tag.nil? ? nil : return_tag.types + + @method_details.push({:name => method.name, :short_desc => brief_summary, :return_types => return_types}) + end + + erb(:method_summary) +end + +def method_details + @class_details = [] + + @methods.each do |object| + examples = Hash.new + example_tags = object.tags.find_all { |tag| tag.tag_name == "example" } + example_tags.each do |example| + examples["#{example.name}"] = example.text + end + + return_tag = object.tags.find { |tag| tag.tag_name == "return"} + return_text = return_tag.nil? ? nil : return_tag.text + return_types = return_tag.nil? ? nil : return_tag.types + return_details = (return_text.nil? && return_types.nil?) ? nil : [return_text, return_types] + + since_tag = object.tags.find { |tag| tag.tag_name == "since"} + since_text = since_tag.nil? ? nil : since_tag.text + + param_details = nil + + if object['puppet_4x_function'] + param_tags = object.tags.find_all{ |tag| tag.tag_name == "param"} + + # Extract the source code + source_code = object.source + # Extract the parameters for the source code + parameters = source_code.match(/(?:def .*)\((.*?)\)/) + # Convert the matched string into an array of strings + params = parameters.nil? ? nil : parameters[1].split(/\s*,\s*/) + + param_details = extract_param_details(params, param_tags) + end + + @class_details.push({:name => object.name, :desc => object.docstring, :examples => examples, :since => since_text, :return => return_details, :params => param_details}) + end + + erb(:docstring) +end + +def extract_param_details(params_array, tags_hash) + if params_array.nil? + return + end + + parameter_info = [] + + # Extract the information for parameters that actually exist + params_array.each do |param| + param_tag = tags_hash.find { |tag| tag.name == param } + + description = param_tag.nil? ? nil : param_tag.text + param_types = param_tag.nil? ? nil : param_tag.types + + parameter_info.push({:name => param, :desc => description, :types => param_types, :exists? => true}) + end + + # Check if there were any comments for parameters that do not exist + tags_hash.each do |tag| + param_exists = false + parameter_info.each do |parameter| + if parameter[:name] == tag.name + param_exists = true + end + end + if !param_exists + parameter_info.push({:name => tag.name, :desc => tag.text, :types => tag.types, :exists? => false}) + end + end + + parameter_info end From 60b2802f0477ec7ffcda302b6e0e6d216d0eda0b Mon Sep 17 00:00:00 2001 From: Hailee Kenney Date: Thu, 22 Jan 2015 15:21:01 -0800 Subject: [PATCH 2/5] (PDOC-24) Clean up code for HTML generation Prior to this commit there was a lot of duplicated code around the generation of HTML for templates. Clean up and simplify code by adding an HTMLHelper class with helper functions which can be used in place of repeated logic. --- .../default/definedtype/html/docstring.erb | 18 +----- .../definedtype/html/parameter_details.erb | 37 +----------- .../templates/default/definedtype/setup.rb | 6 ++ .../yard/templates/default/html_helper.rb | 53 ++++++++++++++++ .../puppetnamespace/html/docstring.erb | 60 +++---------------- .../puppetnamespace/html/method_summary.erb | 12 +--- .../default/puppetnamespace/setup.rb | 9 ++- 7 files changed, 79 insertions(+), 116 deletions(-) create mode 100644 lib/puppetx/puppetlabs/strings/yard/templates/default/html_helper.rb diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/definedtype/html/docstring.erb b/lib/puppetx/puppetlabs/strings/yard/templates/default/definedtype/html/docstring.erb index edebfa0..900985f 100644 --- a/lib/puppetx/puppetlabs/strings/yard/templates/default/definedtype/html/docstring.erb +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/definedtype/html/docstring.erb @@ -27,23 +27,7 @@

Return:

<% end %> diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/definedtype/html/parameter_details.erb b/lib/puppetx/puppetlabs/strings/yard/templates/default/definedtype/html/parameter_details.erb index b55a473..a085ac0 100644 --- a/lib/puppetx/puppetlabs/strings/yard/templates/default/definedtype/html/parameter_details.erb +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/definedtype/html/parameter_details.erb @@ -1,41 +1,6 @@

Parameter Summary

    - <% @param_details.each do |param| %> -
  • - <% if !param[:exists?] %> - - <% end %> - <%= param[:name] %> - <%# TODO: Linkify defaults that resolve to variable declarations in a different scope. %> - - <% if param[:types] %> - (<% param[:types].each do |type| %> - - <% if param[:types].last != type %> - <%= type %>, - <% else %> - <%= type %> - <% end %> - - <% end %>) - <% else %> - (TBD) - <% end %> - - <% unless param[:fq_name].nil? %> - <%= "=> #{param[:fq_name]}" %> - <% end %> - <% if param[:desc]%> - — -
    -

    <%= param[:desc] %>

    -
    - <% end %> - <% if !param[:exists] %> -
    - <% end %> -
  • - <% end %> + <%= @html_helper.generate_parameters(@param_details) %>
diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/definedtype/setup.rb b/lib/puppetx/puppetlabs/strings/yard/templates/default/definedtype/setup.rb index adc2778..8ea5588 100644 --- a/lib/puppetx/puppetlabs/strings/yard/templates/default/definedtype/setup.rb +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/definedtype/setup.rb @@ -1,5 +1,7 @@ include T('default/module') +require File.join(File.dirname(__FILE__),'../html_helper') + def init sections :header, :box_info, :pre_docstring, :docstring, :parameter_details end @@ -7,6 +9,8 @@ end def parameter_details return if object.parameters.empty? + @html_helper = HTMLHelper.new + param_tags = object.tags.find_all{ |tag| tag.tag_name == "param"} params = object.parameters @@ -30,6 +34,8 @@ def header end def docstring + @html_helper = HTMLHelper.new + examples = Hash.new example_tags = object.tags.find_all { |tag| tag.tag_name == "example" } example_tags.each do |example| diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/html_helper.rb b/lib/puppetx/puppetlabs/strings/yard/templates/default/html_helper.rb new file mode 100644 index 0000000..4cb0620 --- /dev/null +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/html_helper.rb @@ -0,0 +1,53 @@ +class HTMLHelper + + def generate_return_types(types, desc = nil) + result = [] + + result << "(" << types.join(", ") << ")" + + if !desc.nil? + result << "-

#{desc}

" + end + + result.join + end + + def generate_parameters(params) + result = [] + + params.each do |param| + result << "
  • " + + if !param[:exists?] + result << "" + end + + result << "#{param[:name]} " + result << "" + + if param[:types] + result << "(" << "" << param[:types].join(", ") << "" << ")" + else + result << "(TBD)" + end + result << "" + + # This is only relevant for manifests, not puppet functions + unless param[:fq_name].nil? + result << " => #{param[:fq_name]}" + end + + if param[:desc] + result << "-

    #{param[:desc]}

    " + end + + if !param[:exists?] + result << "
    " + end + + result << "
  • " + end + + result.join + end +end diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/docstring.erb b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/docstring.erb index cb5110a..8050727 100644 --- a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/docstring.erb +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/docstring.erb @@ -1,6 +1,12 @@ +

    Function Details

    <% @class_details.each do |func| %>

    > - <%= func[:name] %> + + <% if func[:return] %> + <%= @html_helper.generate_return_types(func[:return][1]) %> + <% end %> + <%= func[:name] %> +

    @@ -31,23 +37,7 @@

    Returns:

    • - - <% if !func[:return][1].nil? %> - ( - <% func[:return][1].each do |type| %> - <%= type %> - <% if func[:return][1].last != type %> - , - <% end %> - <% end %> - ) — - <% end %> - - <% if !func[:return][0].nil? %> -
      -

      <%= func[:return][0] %>

      -
      - <% end %> + <%= @html_helper.generate_return_types(func[:return][1], func[:return][0]) %>
    <% end %> @@ -55,39 +45,7 @@

    Parameters:

      - <% func[:params].each do |param| %> -
    • - <% if !param[:exists?] %> - - <% end %> - <%= param[:name] %> - <%# TODO: Linkify defaults that resolve to variable declarations in a different scope. %> - - <% if param[:types] %> - (<% param[:types].each do |type| %> - - <% if param[:types].last != type %> - <%= type %>, - <% else %> - <%= type %> - <% end %> - - <% end %>) - <% else %> - (TBD) - <% end %> - - <% if param[:desc]%> - — -
      -

      <%= param[:desc] %>

      -
      - <% end %> - <% if !param[:exists] %> -
      - <% end %> -
    • - <% end %> + <%= @html_helper.generate_parameters(func[:params]) %>
    <% end %> diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/method_summary.erb b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/method_summary.erb index 6d61392..11ec619 100644 --- a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/method_summary.erb +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/method_summary.erb @@ -4,18 +4,10 @@
  • > - <% if ! method[:return_types].nil? %> - ( - <% method[:return_types].each do |type| %> - <%= type %> - <% if method[:return_types].last != type %> - , - <% end %> - <% end %> - ) — + <%= @html_helper.generate_return_types(method[:return_types]) %> <% end %> - + - <%= method[:name] %>
  • diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb index a310566..84ee82f 100644 --- a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb @@ -1,9 +1,11 @@ include T('default/module') +require File.join(File.dirname(__FILE__),'../html_helper') + def init sections :header, :box_info, :pre_docstring, T('docstring'), :method_summary, [:item_summary], - :method_details_list, :method_details + :method_details_list, [T('method_details')] @methods = object.children end @@ -34,6 +36,7 @@ end def method_summary @method_details = [] + @html_helper = HTMLHelper.new @methods.each do |method| # If there are multiple sentences in the method description, only @@ -51,8 +54,9 @@ def method_summary erb(:method_summary) end -def method_details +def method_details_list @class_details = [] + @html_helper = HTMLHelper.new @methods.each do |object| examples = Hash.new @@ -122,3 +126,4 @@ def extract_param_details(params_array, tags_hash) parameter_info end + From b9da8b164fc8c807ed0faed288fde26dbee9a8c1 Mon Sep 17 00:00:00 2001 From: Hailee Kenney Date: Thu, 22 Jan 2015 22:26:58 -0800 Subject: [PATCH 3/5] (PDOC-24) Create helper class for templates Prior to this commit some of the logic used to extract data from comments for templates was duplicated and a little messy. Create the TemplateHelper class so that can be simplified and cleaned up to make things more readable and efficient. --- .../templates/default/definedtype/setup.rb | 67 ++------------- .../yard/templates/default/html_helper.rb | 4 + ...{docstring.erb => method_details_list.erb} | 0 .../default/puppetnamespace/setup.rb | 58 ++----------- .../yard/templates/default/template_helper.rb | 81 +++++++++++++++++++ 5 files changed, 99 insertions(+), 111 deletions(-) rename lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/{docstring.erb => method_details_list.erb} (100%) create mode 100644 lib/puppetx/puppetlabs/strings/yard/templates/default/template_helper.rb diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/definedtype/setup.rb b/lib/puppetx/puppetlabs/strings/yard/templates/default/definedtype/setup.rb index 8ea5588..39ae076 100644 --- a/lib/puppetx/puppetlabs/strings/yard/templates/default/definedtype/setup.rb +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/definedtype/setup.rb @@ -1,22 +1,24 @@ include T('default/module') require File.join(File.dirname(__FILE__),'../html_helper') +require File.join(File.dirname(__FILE__),'../template_helper') def init sections :header, :box_info, :pre_docstring, :docstring, :parameter_details + + @template_helper = TemplateHelper.new + @html_helper = HTMLHelper.new end def parameter_details return if object.parameters.empty? - @html_helper = HTMLHelper.new - param_tags = object.tags.find_all{ |tag| tag.tag_name == "param"} params = object.parameters @param_details = [] - @param_details = extract_param_details(params, param_tags) + @param_details = @template_helper.extract_param_details(params, param_tags, true) erb(:parameter_details) end @@ -34,65 +36,8 @@ def header end def docstring - @html_helper = HTMLHelper.new - examples = Hash.new - example_tags = object.tags.find_all { |tag| tag.tag_name == "example" } - example_tags.each do |example| - examples["#{example.name}"] = example.text - end - - return_tag = object.tags.find { |tag| tag.tag_name == "return"} - return_text = return_tag.nil? ? nil : return_tag.text - return_types = return_tag.nil? ? nil : return_tag.types - return_details = (return_text.nil? && return_types.nil?) ? nil : [return_text, return_types] - - since_tag = object.tags.find { |tag| tag.tag_name == "since"} - since_text = since_tag.nil? ? nil : since_tag.text - - @class_details = {:name => object.name, :desc => object.docstring, :examples => examples, :since => since_text, :return => return_details} + @class_details = @template_helper.extract_tag_data(object) erb(:docstring) end - -# Given the parameter information and YARD param tags, extracts the -# useful information and returns it as an array of hashes which can -# be printed and formatted in the paramters_details erb file -# -# @param params_hash [Array] parameter details obtained programmatically -# @param tags_hash [Array] parameter details obtained from comments -# -# @return [Hash] The relevant information about each parameter -# @option opts [String] :name The name of the parameter -# @option opts [String] :fq_name The fully qualified parameter name -# @option opts [String] :desc The description provided in the comment -# @options opts [Array] :types The parameter type(s) specified in the comment -# @options opts [Boolean] :exists? True only if the parameter exists in the documented logic and not just in a comment -def extract_param_details(params_hash, tags_hash) - parameter_info = [] - - # Extract the information for parameters that actually exist - params_hash.each do |param| - param_tag = tags_hash.find { |tag| tag.name == param[0] } - - description = param_tag.nil? ? nil : param_tag.text - param_types = param_tag.nil? ? nil : param_tag.types - - parameter_info.push({:name => param[0], :fq_name => param[1], :desc => description, :types => param_types, :exists? => true}) - end - - # Check if there were any comments for parameters that do not exist - tags_hash.each do |tag| - param_exists = false - parameter_info.each do |parameter| - if parameter[:name] == tag.name - param_exists = true - end - end - if !param_exists - parameter_info.push({:name => tag.name, :fq_name => nil, :desc => tag.text, :types => tag.types, :exists? => false}) - end - end - - parameter_info -end diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/html_helper.rb b/lib/puppetx/puppetlabs/strings/yard/templates/default/html_helper.rb index 4cb0620..fed42cf 100644 --- a/lib/puppetx/puppetlabs/strings/yard/templates/default/html_helper.rb +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/html_helper.rb @@ -1,5 +1,8 @@ +# A class containing helper methods to aid the generation of HTML +# given formatted data class HTMLHelper + # Generates the HTML to format the relevant data about return values def generate_return_types(types, desc = nil) result = [] @@ -12,6 +15,7 @@ class HTMLHelper result.join end + # Generates the HTML to format the relevant data about parameters def generate_parameters(params) result = [] diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/docstring.erb b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/method_details_list.erb similarity index 100% rename from lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/docstring.erb rename to lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/html/method_details_list.erb diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb index 84ee82f..66679ab 100644 --- a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb @@ -1,6 +1,7 @@ include T('default/module') require File.join(File.dirname(__FILE__),'../html_helper') +require File.join(File.dirname(__FILE__),'../template_helper') def init sections :header, :box_info, :pre_docstring, T('docstring'), @@ -8,6 +9,7 @@ def init :method_details_list, [T('method_details')] @methods = object.children + @template_helper = TemplateHelper.new end def header @@ -59,20 +61,8 @@ def method_details_list @html_helper = HTMLHelper.new @methods.each do |object| - examples = Hash.new - example_tags = object.tags.find_all { |tag| tag.tag_name == "example" } - example_tags.each do |example| - examples["#{example.name}"] = example.text - end - - return_tag = object.tags.find { |tag| tag.tag_name == "return"} - return_text = return_tag.nil? ? nil : return_tag.text - return_types = return_tag.nil? ? nil : return_tag.types - return_details = (return_text.nil? && return_types.nil?) ? nil : [return_text, return_types] - - since_tag = object.tags.find { |tag| tag.tag_name == "since"} - since_text = since_tag.nil? ? nil : since_tag.text + method_info = @template_helper.extract_tag_data(object) param_details = nil if object['puppet_4x_function'] @@ -85,45 +75,13 @@ def method_details_list # Convert the matched string into an array of strings params = parameters.nil? ? nil : parameters[1].split(/\s*,\s*/) - param_details = extract_param_details(params, param_tags) + param_details = @template_helper.extract_param_details(params, param_tags) unless params.nil? end - @class_details.push({:name => object.name, :desc => object.docstring, :examples => examples, :since => since_text, :return => return_details, :params => param_details}) + method_info[:params] = param_details + + @class_details.push(method_info) end - erb(:docstring) + erb(:method_details_list) end - -def extract_param_details(params_array, tags_hash) - if params_array.nil? - return - end - - parameter_info = [] - - # Extract the information for parameters that actually exist - params_array.each do |param| - param_tag = tags_hash.find { |tag| tag.name == param } - - description = param_tag.nil? ? nil : param_tag.text - param_types = param_tag.nil? ? nil : param_tag.types - - parameter_info.push({:name => param, :desc => description, :types => param_types, :exists? => true}) - end - - # Check if there were any comments for parameters that do not exist - tags_hash.each do |tag| - param_exists = false - parameter_info.each do |parameter| - if parameter[:name] == tag.name - param_exists = true - end - end - if !param_exists - parameter_info.push({:name => tag.name, :desc => tag.text, :types => tag.types, :exists? => false}) - end - end - - parameter_info -end - diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/template_helper.rb b/lib/puppetx/puppetlabs/strings/yard/templates/default/template_helper.rb new file mode 100644 index 0000000..1c1be34 --- /dev/null +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/template_helper.rb @@ -0,0 +1,81 @@ +# A class containing helper methods to aid in the extraction of relevant data +# from comments and YARD tags +class TemplateHelper + + # Extracts data from comments which include the supported YARD tags + def extract_tag_data(object) + examples = Hash.new + example_tags = object.tags.find_all { |tag| tag.tag_name == "example" } + example_tags.each do |example| + examples["#{example.name}"] = example.text + end + + return_tag = object.tags.find { |tag| tag.tag_name == "return"} + return_text = return_tag.nil? ? nil : return_tag.text + return_types = return_tag.nil? ? nil : return_tag.types + return_details = (return_text.nil? && return_types.nil?) ? nil : [return_text, return_types] + + since_tag = object.tags.find { |tag| tag.tag_name == "since"} + since_text = since_tag.nil? ? nil : since_tag.text + + {:name => object.name, :desc => object.docstring, :examples => examples, :since => since_text, :return => return_details} + end + + # Given the parameter information and YARD param tags, extracts the + # useful information and returns it as an array of hashes which can + # be printed and formatted as HTML + # + # @param parameters [Array] parameter details obtained programmatically + # @param tags_hash [Array] parameter details obtained from comments + # @param fq_name [Boolean] does this paramter have a fully qualified name? + # + # @return [Hash] The relevant information about each parameter + # @option opts [String] :name The name of the parameter + # @option opts [String] :fq_name The fully qualified parameter name + # @option opts [String] :desc The description provided in the comment + # @options opts [Array] :types The parameter type(s) specified in the comment + # @options opts [Boolean] :exists? True only if the parameter exists in the documented logic and not just in a comment + def extract_param_details(parameters, tags_hash, fq_name = false) + parameter_info = [] + + + # Extract the information for parameters that actually exist + parameters.each do |param| + + if fq_name + param_name = param[0] + fully_qualified_name = param[1] + else + param_name = param + end + + param_tag = tags_hash.find { |tag| tag.name == param_name } + + description = param_tag.nil? ? nil : param_tag.text + param_types = param_tag.nil? ? nil : param_tag.types + + param_details = {:name => param_name, :desc => description, :types => param_types, :exists? => true} + + if fq_name + param_details[:fq_name] = fully_qualified_name + end + + parameter_info.push(param_details) + end + + # Check if there were any comments for parameters that do not exist + tags_hash.each do |tag| + param_exists = false + parameter_info.each do |parameter| + if parameter[:name] == tag.name + param_exists = true + end + end + if !param_exists + parameter_info.push({:name => tag.name, :desc => tag.text, :types => tag.types, :exists? => false}) + end + end + + parameter_info + end +end From 121bcfd2a784b17d3e49d514df783227e8f008f6 Mon Sep 17 00:00:00 2001 From: Hailee Kenney Date: Wed, 28 Jan 2015 11:39:28 -0800 Subject: [PATCH 4/5] (PDOC-24) Add support for @param in 3x functions Prior to this commit, the @param tag was not supported for 3x functions since we could not derive any information about the parameter from the code itself. Since we would still like users to be able to document parameters if they wish, update the code so that if a parameter is documented in the 3x :doc string it will be displayed in the HTML. --- .../default/puppetnamespace/setup.rb | 5 ++-- .../yard/templates/default/template_helper.rb | 26 ++++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb index 66679ab..3677e4a 100644 --- a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb @@ -64,10 +64,9 @@ def method_details_list method_info = @template_helper.extract_tag_data(object) param_details = nil + param_tags = object.tags.find_all{ |tag| tag.tag_name == "param"} if object['puppet_4x_function'] - param_tags = object.tags.find_all{ |tag| tag.tag_name == "param"} - # Extract the source code source_code = object.source # Extract the parameters for the source code @@ -76,6 +75,8 @@ def method_details_list params = parameters.nil? ? nil : parameters[1].split(/\s*,\s*/) param_details = @template_helper.extract_param_details(params, param_tags) unless params.nil? + else + param_details = @template_helper.comment_only_param_details(param_tags) end method_info[:params] = param_details diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/template_helper.rb b/lib/puppetx/puppetlabs/strings/yard/templates/default/template_helper.rb index 1c1be34..bba88d9 100644 --- a/lib/puppetx/puppetlabs/strings/yard/templates/default/template_helper.rb +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/template_helper.rb @@ -38,7 +38,6 @@ class TemplateHelper def extract_param_details(parameters, tags_hash, fq_name = false) parameter_info = [] - # Extract the information for parameters that actually exist parameters.each do |param| @@ -78,4 +77,29 @@ class TemplateHelper parameter_info end + + # Generates parameter information in situations where the information can only + # come from YARD tags in the comments, not from the code itself. For now the only + # use for this is 3x functions. In this case exists? will always be true since we + # cannot verify if the paramter exists in the code itself. We must trust the user + # to provide information in the comments that is accurate. + # + # @param param_tags [Array] parameter details obtained from comments + # + # @return [Hash] The relevant information about each parameter + # @option opts [String] :name The name of the parameter + # @option opts [String] :desc The description provided in the comment + # @options opts [Array] :types The parameter type(s) specified in the comment + # @options opts [Boolean] :exists? True only if the parameter exists in the documented logic and not just in a comment + def comment_only_param_details(param_tags) + return if param_tags.empty? + + parameter_info = [] + + param_tags.each do |tag| + parameter_info.push({:name => tag.name, :desc => tag.text, :types => tag.types, :exists? => true}) + end + + parameter_info + end end From 26945eacf344146483a36fcb2d2c7b175d320ee8 Mon Sep 17 00:00:00 2001 From: Hailee Kenney Date: Wed, 28 Jan 2015 15:10:28 -0800 Subject: [PATCH 5/5] (PDOC-24) Fix comments and remove unneeded sections Prior to this commit, some of the comments in the code were not as clear as they should have been and in some places comments were not present where they were needed. Clean up existing comments and add some for sections of code that are not very clear. Additionally, some sections of the template for puppet namespaces didn't really make sense to include, especially since we want the source of truth for documentation of 3x functions to be the :doc string which is passed in (not the comment block above the function). Thus, remove some of the unneeded sections from the puppet namespace template. --- .../yard/templates/default/html_helper.rb | 15 ++++++++-- .../default/puppetnamespace/setup.rb | 5 ++-- .../yard/templates/default/template_helper.rb | 30 ++++++++++--------- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/html_helper.rb b/lib/puppetx/puppetlabs/strings/yard/templates/default/html_helper.rb index fed42cf..b9a4a58 100644 --- a/lib/puppetx/puppetlabs/strings/yard/templates/default/html_helper.rb +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/html_helper.rb @@ -22,6 +22,10 @@ class HTMLHelper params.each do |param| result << "
  • " + # Parameters which are documented in the comments but not + # present in the code itself are given the strike through + # styling in order to show the reader that they do not actually + # exist if !param[:exists?] result << "" end @@ -31,12 +35,19 @@ class HTMLHelper if param[:types] result << "(" << "" << param[:types].join(", ") << "" << ")" - else + # Don't bother with TBD since 3x functions will never have type info per parameter. + # However if the user does want to list a type for some reason that is still supported, + # we just don't want to suggest that they need to + elsif !param[:puppet_3_func] result << "(TBD)" end - result << "" + + result << "" # This is only relevant for manifests, not puppet functions + # This is due to the fact that the scope of a parameter (as illustrated by + # by it's fully qualified name) is not relevant for the parameters in puppet + # functions, but may be for components of a manifest (i.e. classes) unless param[:fq_name].nil? result << " => #{param[:fq_name]}" end diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb index 3677e4a..054cee2 100644 --- a/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb @@ -4,7 +4,7 @@ require File.join(File.dirname(__FILE__),'../html_helper') require File.join(File.dirname(__FILE__),'../template_helper') def init - sections :header, :box_info, :pre_docstring, T('docstring'), + sections :header, :box_info, :method_summary, [:item_summary], :method_details_list, [T('method_details')] @@ -13,6 +13,7 @@ def init end def header + # The list is expected to only contain one type of function if @methods[0]['puppet_4x_function'] @header_text = "Puppet 4 Functions" else @@ -26,7 +27,7 @@ def box_info @source_files = [] @methods.each do |method| - # extract the file name and line number for each method + # extract the file name and line number for each method file_name = method.files[0][0] line_number = method.files[0][1] diff --git a/lib/puppetx/puppetlabs/strings/yard/templates/default/template_helper.rb b/lib/puppetx/puppetlabs/strings/yard/templates/default/template_helper.rb index bba88d9..40cf94e 100644 --- a/lib/puppetx/puppetlabs/strings/yard/templates/default/template_helper.rb +++ b/lib/puppetx/puppetlabs/strings/yard/templates/default/template_helper.rb @@ -27,18 +27,19 @@ class TemplateHelper # # @param parameters [Array] parameter details obtained programmatically # @param tags_hash [Array] parameter details obtained from comments - # @param fq_name [Boolean] does this paramter have a fully qualified name? + # @param fq_name [Boolean] does this parameter have a fully qualified name? # - # @return [Hash] The relevant information about each parameter - # @option opts [String] :name The name of the parameter - # @option opts [String] :fq_name The fully qualified parameter name - # @option opts [String] :desc The description provided in the comment - # @options opts [Array] :types The parameter type(s) specified in the comment - # @options opts [Boolean] :exists? True only if the parameter exists in the documented logic and not just in a comment + # @return [Hash] The relevant information about each parameter with the following keys/values: + # {:name => [String] The name of the parameter + # :fq_name => [String] The fully qualified parameter name + # :desc => [String] The description provided in the comment + # :types => [Array] The parameter type(s) specified in the comment + # :exists => [Boolean] True only if the parameter exists in the documented logic and not just in a comment} def extract_param_details(parameters, tags_hash, fq_name = false) parameter_info = [] # Extract the information for parameters that actually exist + # as opposed to parameters that are defined only in the comments parameters.each do |param| if fq_name @@ -81,23 +82,24 @@ class TemplateHelper # Generates parameter information in situations where the information can only # come from YARD tags in the comments, not from the code itself. For now the only # use for this is 3x functions. In this case exists? will always be true since we - # cannot verify if the paramter exists in the code itself. We must trust the user + # cannot verify if the parameter exists in the code itself. We must trust the user # to provide information in the comments that is accurate. # # @param param_tags [Array] parameter details obtained from comments # - # @return [Hash] The relevant information about each parameter - # @option opts [String] :name The name of the parameter - # @option opts [String] :desc The description provided in the comment - # @options opts [Array] :types The parameter type(s) specified in the comment - # @options opts [Boolean] :exists? True only if the parameter exists in the documented logic and not just in a comment + # @return [Hash] The relevant information about each parameter with the following keys/values: + # {:name => [String] The name of the parameter + # :desc => [String] The description provided in the comment + # :types => [Array] The parameter type(s) specified in the comment + # :exists => [Boolean] True only if the parameter exists in the documented logic and not just in a comment + # :puppet_3_func => [Boolean] Are these parameters for a puppet 3 function? (relevant in HTML generation)} def comment_only_param_details(param_tags) return if param_tags.empty? parameter_info = [] param_tags.each do |tag| - parameter_info.push({:name => tag.name, :desc => tag.text, :types => tag.types, :exists? => true}) + parameter_info.push({:name => tag.name, :desc => tag.text, :types => tag.types, :exists? => true, :puppet_3_func => true}) end parameter_info