From ca98890cddd6ae4c5238d463f5e717f550ab173d Mon Sep 17 00:00:00 2001 From: Will Hopper Date: Mon, 10 Oct 2016 14:46:43 -0700 Subject: [PATCH] (PDOC-122) Properly parse `newfunction` calls with newlines When `newfunction` is separated from the Puppet::Parser::Functions module name by a newline, YARD ignores the namespace and uses `newfunction` as the source of the first statement. Prior to this commit, strings didn't recognize this case, and 3.x functions written in this way were not parsed as functions. This commit updates the ruby function handler to identify and properly parse 3.x functions that include a newline between the Puppet::Parser::Function namespace and the newfunction method call. --- .../yard/handlers/ruby/function_handler.rb | 7 ++- .../handlers/ruby/function_handler_spec.rb | 44 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/lib/puppet-strings/yard/handlers/ruby/function_handler.rb b/lib/puppet-strings/yard/handlers/ruby/function_handler.rb index 65c1420..e515b5a 100644 --- a/lib/puppet-strings/yard/handlers/ruby/function_handler.rb +++ b/lib/puppet-strings/yard/handlers/ruby/function_handler.rb @@ -23,12 +23,15 @@ class PuppetStrings::Yard::Handlers::Ruby::FunctionHandler < PuppetStrings::Yard process do # Only accept calls to Puppet::Functions (4.x) or Puppet::Parser::Functions (3.x) + # When `newfunction` is separated from the Puppet::Parser::Functions module name by a + # newline, YARD ignores the namespace and uses `newfunction` as the source of the + # first statement. return unless statement.count > 1 module_name = statement[0].source - return unless module_name == 'Puppet::Functions' || module_name == 'Puppet::Parser::Functions' + return unless module_name == 'Puppet::Functions' || module_name == 'Puppet::Parser::Functions' || module_name == 'newfunction' # Create and register the function object - is_3x = module_name == 'Puppet::Parser::Functions' + is_3x = module_name == 'Puppet::Parser::Functions' || module_name == 'newfunction' object = PuppetStrings::Yard::CodeObjects::Function.new( get_name, is_3x ? PuppetStrings::Yard::CodeObjects::Function::RUBY_3X : PuppetStrings::Yard::CodeObjects::Function::RUBY_4X diff --git a/spec/unit/puppet-strings/yard/handlers/ruby/function_handler_spec.rb b/spec/unit/puppet-strings/yard/handlers/ruby/function_handler_spec.rb index d80e5a0..7a1027b 100644 --- a/spec/unit/puppet-strings/yard/handlers/ruby/function_handler_spec.rb +++ b/spec/unit/puppet-strings/yard/handlers/ruby/function_handler_spec.rb @@ -70,6 +70,50 @@ SOURCE end end + describe 'parsing a function with a doc parameter which has a newline between the namespace and the newfunction call' do + let(:source) { <<-SOURCE +module Puppet::Parser::Functions + newfunction(:foo, doc: <<-DOC +An example 3.x function. +@param [String] first The first parameter. +@param second The second parameter. +@return [Undef] Returns nothing. +DOC +) do |*args| + end +end +SOURCE + } + + it 'should register a function object' do + expect(subject.size).to eq(1) + object = subject.first + expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Function) + expect(object.namespace).to eq(PuppetStrings::Yard::CodeObjects::Functions.instance(PuppetStrings::Yard::CodeObjects::Function::RUBY_3X)) + expect(object.name).to eq(:foo) + expect(object.signature).to eq('foo(String $first, Any $second)') + expect(object.parameters).to eq([['first', nil], ['second', nil]]) + expect(object.docstring).to eq('An example 3.x function.') + expect(object.docstring.tags.size).to eq(4) + tags = object.docstring.tags(:param) + expect(tags.size).to eq(2) + expect(tags[0].name).to eq('first') + expect(tags[0].text).to eq('The first parameter.') + expect(tags[0].types).to eq(['String']) + expect(tags[1].name).to eq('second') + expect(tags[1].text).to eq('The second parameter.') + expect(tags[1].types).to eq(['Any']) + tags = object.docstring.tags(:return) + expect(tags.size).to eq(1) + expect(tags[0].name).to be_nil + expect(tags[0].text).to eq('Returns nothing.') + expect(tags[0].types).to eq(['Undef']) + tags = object.docstring.tags(:api) + expect(tags.size).to eq(1) + expect(tags[0].text).to eq('public') + end + end + describe 'parsing a function with a missing @return tag' do let(:source) { <<-SOURCE Puppet::Parser::Functions.newfunction(:foo, doc: <<-DOC) do |*args|