From 66af766dba16b37a6ca40cc8f10ccad1b81f9611 Mon Sep 17 00:00:00 2001 From: Charlie Sharpsteen Date: Thu, 22 May 2014 22:44:15 -0700 Subject: [PATCH] Add YARDStatement class The `YARDStatement` class is an adaptor that composes a `Pops::Model` instance along with applicable `Pops::Adapter` and presents a familiar interface for `YARD::Handler` objects to work with. --- lib/puppet/face/yardoc.rb | 2 +- lib/puppetx/yardoc/pops/yard_statement.rb | 67 +++++++++++++++++++++ lib/puppetx/yardoc/pops/yard_transformer.rb | 37 +++--------- 3 files changed, 76 insertions(+), 30 deletions(-) create mode 100644 lib/puppetx/yardoc/pops/yard_statement.rb diff --git a/lib/puppet/face/yardoc.rb b/lib/puppet/face/yardoc.rb index 40e812b..b48a4ef 100644 --- a/lib/puppet/face/yardoc.rb +++ b/lib/puppet/face/yardoc.rb @@ -21,7 +21,7 @@ Puppet::Face.define(:yardoc, '0.0.1') do parser = Puppetx::Yardoc::YARD::PuppetParser.new(File.read(manifest), manifest) parser.parse - return parser.enumerator + return parser.enumerator.map {|s| s.comments} end end end diff --git a/lib/puppetx/yardoc/pops/yard_statement.rb b/lib/puppetx/yardoc/pops/yard_statement.rb new file mode 100644 index 0000000..cf50070 --- /dev/null +++ b/lib/puppetx/yardoc/pops/yard_statement.rb @@ -0,0 +1,67 @@ +require 'puppetx/yardoc' + +require 'puppet/pops' + +module Puppetx::Yardoc::Pops + # An adapter class that conforms a Pops model instance + adapters to the + # interface expected by YARD handlers. + class YARDStatement + attr_reader :pops_obj, :comments + + def initialize(pops_obj) + unless pops_obj.is_a? Puppet::Pops::Model::PopsObject + raise ArgumentError, "A YARDStatement can only be initialized from a PopsObject. Got a: #{pops_obj.class}" + end + + @pops_obj = pops_obj + @pos_adapter = Puppet::Pops::Adapters::SourcePosAdapter.adapt(@pops_obj) + # FIXME: Perhaps this should be a seperate adapter? + @comments = extract_comments + end + + def type + pops_obj.class + end + + def line + @line ||= @pos_adapter.line + end + + def source + @source ||= @pos_adapter.extract_text + end + + # FIXME: I don't know quite what these are supposed to do, but they show up + # quite often in the YARD handler code. Figure out whether they are + # necessary. + alias_method :show, :source + def comments_hash_flag; nil end + def comments_range; nil end + + private + # TODO: This stuff should probably be part of a separate class/adapter. + COMMENT_PATTERN = /^\s*#.*\n/ + + def extract_comments + comments = [] + program = pops_obj.eAllContainers.find {|c| c.is_a?(Puppet::Pops::Model::Program) } + # FIXME: Horribly inefficient. Multiple copies. Generator pattern would + # be much better. + source_text = program.source_text.lines.to_a + + source_text.slice(0, line-1).reverse.each do |line| + if COMMENT_PATTERN.match(line) + comments.unshift line + else + # No comment found on this line. We must be done piecing together a + # comment block. + break + end + end + + # Stick everything back together. + comments.join + end + + end +end diff --git a/lib/puppetx/yardoc/pops/yard_transformer.rb b/lib/puppetx/yardoc/pops/yard_transformer.rb index 783be9d..af32e39 100644 --- a/lib/puppetx/yardoc/pops/yard_transformer.rb +++ b/lib/puppetx/yardoc/pops/yard_transformer.rb @@ -2,10 +2,15 @@ require 'puppetx/yardoc' require 'puppet/pops' +require_relative 'yard_statement' + module Puppetx::Yardoc::Pops # Loosely based on the TreeDumper classes in Pops::Model. The responsibility of # this class is to walk a Pops::Model and output objects that can be consumed # by YARD handlers. + # + # @note Currently, this class only extracts node, host class and type + # definitions. class YARDTransformer def initialize @transform_visitor = Puppet::Pops::Visitor.new(self, 'transform') @@ -22,41 +27,15 @@ module Puppetx::Yardoc::Pops end def transform_Program(o) - # FIXME: Uuuuuughhhhhhhhh.... This should be extracted some other way. - # Perhaps using a SourcePosAdapter? - @source_text = o.source_text.lines.to_a - @locator = o.locator - o.definitions.map{|d| transform(d)} end # Extract comments from "Definition" objects. That is: nodes definitions, - # type definitions and class definitions. + # type definitions and class definitions. Wrap them into YARDStatement + # objects that provide an interface for YARD handlers. def transform_Definition(o) - line = @locator.line_for_offset(o.offset) - comments_before(line) + YARDStatement.new(o) end - # TODO: This stuff should probably be part of a separate class/adapter. - COMMENT_PATTERN = /^\s*#.*\n/ - - def comments_before(line) - comments = [] - - # FIXME: Horribly inefficient. Multiple copies. Generator pattern would - # be much better. - @source_text.slice(0, line-1).reverse.each do |line| - if COMMENT_PATTERN.match(line) - comments.unshift line - else - # No comment found on this line. We must be done piecing together a - # comment block. - break - end - end - - # Stick everything back together. - comments.join - end end end