From c1217912ddab51265b98b38fd445e9b7045dfbf9 Mon Sep 17 00:00:00 2001 From: Charlie Sharpsteen Date: Thu, 5 Jun 2014 21:40:17 -0700 Subject: [PATCH] Add custom YARD handler for parser functions This handler triggers on all occurrences of `newfunction` and parses the parameters passed to that method in order to generate documentation. The implementation is a good experiment in extracting documentation without evaluating Ruby code. However, the generality of this approach may ultimately be doomed by the use of metaprogramming in custom Types and Providers. --- lib/puppetx/yardoc/yard/handlers.rb | 1 + .../yard/handlers/parser_function_handler.rb | 97 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 lib/puppetx/yardoc/yard/handlers/parser_function_handler.rb diff --git a/lib/puppetx/yardoc/yard/handlers.rb b/lib/puppetx/yardoc/yard/handlers.rb index fe3737c..0870f17 100644 --- a/lib/puppetx/yardoc/yard/handlers.rb +++ b/lib/puppetx/yardoc/yard/handlers.rb @@ -1,3 +1,4 @@ require_relative 'handlers/base' require_relative 'handlers/defined_type_handler' require_relative 'handlers/host_class_handler' +require_relative 'handlers/parser_function_handler' diff --git a/lib/puppetx/yardoc/yard/handlers/parser_function_handler.rb b/lib/puppetx/yardoc/yard/handlers/parser_function_handler.rb new file mode 100644 index 0000000..39ca715 --- /dev/null +++ b/lib/puppetx/yardoc/yard/handlers/parser_function_handler.rb @@ -0,0 +1,97 @@ +# This utility library contains some tools for working with Puppet docstrings. +require 'puppet/util/docs' + +require_relative 'base' + +module Puppetx::Yardoc::YARD::Handlers + class ParserFunctionHandler < YARD::Handlers::Ruby::Base + handles method_call(:newfunction) + + process do + name, options = process_parameters + + obj = MethodObject.new(:root, name) + + register obj + if options['doc'] + register_docstring(obj, options['doc'], nil) + end + + # This has to be done _after_ register_docstring as all tags on the + # object are overwritten by tags parsed out of the docstring. + return_type = options['type'] + return_type ||= 'statement' # Default for newfunction + obj.add_tag YARD::Tags::Tag.new(:return, '', return_type) + end + + private + + # NOTE: The following methods duplicate functionality from + # Puppet::Util::Reference and Puppet::Parser::Functions.functiondocs + # + # However, implementing this natively in YARD is a good test for the + # feasibility of extracting custom Ruby documentation. In the end, the + # existing approach taken by Puppet::Util::Reference may be the best due to + # the heavy use of metaprogramming in Types and Providers. + + # Extracts the Puppet function name and options hash from the parsed + # definition. + # + # @return [(String, Hash{String => String})] + def process_parameters + # Passing `false` to prameters excludes the block param from the returned + # list. + name, opts = statement.parameters(false).compact + + name = process_element(name) + + opts = opts.map do |tuple| + # Jump down into the S-Expression that represents a hashrocket, `=>`, + # and the values on either side of it. + tuple.jump(:assoc).map{|e| process_element(e)} + end + + [name, Hash[opts]] + end + + # Sometimes the YARD parser returns Heredoc strings that start with `<-` + # instead of `<<-`. + HEREDOC_START = /^