Merge pull request #126 from whopper/PDOC-136/3x_function_return
(PDOC-136) Detect return type syntax in Puppet Language functions
This commit is contained in:
commit
bf68ae0022
|
@ -27,6 +27,7 @@ env:
|
|||
- PUPPET_GEM_VERSION="~> 4.5.0" CHECK=spec
|
||||
- PUPPET_GEM_VERSION="~> 4.6.0" CHECK=spec
|
||||
- PUPPET_GEM_VERSION="~> 4.7.0" CHECK=spec
|
||||
- PUPPET_GEM_VERSION="~> 4.8.0" CHECK=spec
|
||||
- PUPPET_GEM_VERSION="~> 4" CHECK=spec
|
||||
- PUPPET_GEM_VERSION="~> 4" CHECK=rubocop
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ class PuppetStrings::Yard::Handlers::Puppet::FunctionHandler < PuppetStrings::Ya
|
|||
set_parameter_types(object)
|
||||
|
||||
# Add a return tag
|
||||
add_return_tag(object)
|
||||
add_return_tag(object, statement.type)
|
||||
|
||||
# Set the parameters on the object
|
||||
object.parameters = statement.parameters.map { |p| [p.name, p.value] }
|
||||
|
@ -30,13 +30,18 @@ class PuppetStrings::Yard::Handlers::Puppet::FunctionHandler < PuppetStrings::Ya
|
|||
end
|
||||
|
||||
private
|
||||
def add_return_tag(object)
|
||||
def add_return_tag(object, type=nil)
|
||||
tag = object.tag(:return)
|
||||
if tag
|
||||
tag.types = ['Any'] unless tag.types
|
||||
if (type && tag.types) && (type != tag.types)
|
||||
log.warn "Documented return type does not match return type in function definition near #{statement.file}:#{statement.line}."
|
||||
end
|
||||
|
||||
tag.types = type ? [type] : tag.types || ['Any']
|
||||
return
|
||||
end
|
||||
log.warn "Missing @return tag near #{statement.file}:#{statement.line}."
|
||||
object.add_tag YARD::Tags::Tag.new(:return, '', 'Any')
|
||||
type = type || 'Any'
|
||||
object.add_tag YARD::Tags::Tag.new(:return, '', type)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -134,6 +134,7 @@ module PuppetStrings::Yard::Parsers::Puppet
|
|||
# Implements the Puppet function statement.
|
||||
class FunctionStatement < ParameterizedStatement
|
||||
attr_reader :name
|
||||
attr_reader :type
|
||||
|
||||
# Initializes the Puppet function statement.
|
||||
# @param [Puppet::Pops::Model::FunctionDefinition] object The model object for the function statement.
|
||||
|
@ -141,6 +142,13 @@ module PuppetStrings::Yard::Parsers::Puppet
|
|||
def initialize(object, file)
|
||||
super(object, file)
|
||||
@name = object.name
|
||||
if object.respond_to? :return_type
|
||||
type = object.return_type
|
||||
if type
|
||||
adapter = ::Puppet::Pops::Adapters::SourcePosAdapter.adapt(type)
|
||||
@type = adapter.extract_text.gsub('>> ', '')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,6 +10,9 @@ PuppetStrings::Yard.setup!
|
|||
# Enable testing of Puppet functions if running against 4.1+
|
||||
TEST_PUPPET_FUNCTIONS = Gem::Dependency.new('', '>= 4.1.0').match?('', Puppet::PUPPETVERSION)
|
||||
|
||||
# Enable testing of Puppet language functions declared with return type if running against 4.8+
|
||||
TEST_FUNCTION_RETURN_TYPE = Gem::Dependency.new('', '>= 4.8.0').match?('', Puppet::PUPPETVERSION)
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.mock_with :mocha
|
||||
|
||||
|
|
|
@ -68,6 +68,11 @@ SOURCE
|
|||
expect(tags[2].name).to eq('param3')
|
||||
expect(tags[2].text).to eq('Third param.')
|
||||
expect(tags[2].types).to eq(['String'])
|
||||
tags = object.docstring.tags(:return)
|
||||
expect(tags.size).to eq(1)
|
||||
expect(tags[0].tag_name).to eq('return')
|
||||
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')
|
||||
|
@ -166,4 +171,71 @@ SOURCE
|
|||
expect{ subject }.to output(/\[warn\]: Missing @return tag near \(stdin\):5\./).to_stdout_from_any_process
|
||||
end
|
||||
end
|
||||
|
||||
describe 'parsing a function with a missing @return tag and return type specified in the function definition', if: TEST_FUNCTION_RETURN_TYPE do
|
||||
let(:source) { <<-SOURCE
|
||||
# A simple foo function.
|
||||
function foo() >> String {
|
||||
notice 'hello world'
|
||||
}
|
||||
SOURCE
|
||||
}
|
||||
|
||||
it 'should register a function object with the correct return type' do
|
||||
expect{ subject }.to output(/\[warn\]: Missing @return tag near \(stdin\):2\./).to_stdout_from_any_process
|
||||
expect(subject.size).to eq(1)
|
||||
object = subject.first
|
||||
expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Function)
|
||||
tags = object.docstring.tags(:return)
|
||||
expect(tags.size).to eq(1)
|
||||
expect(tags[0].tag_name).to eq('return')
|
||||
expect(tags[0].text).to eq('')
|
||||
expect(tags[0].types).to eq(['String'])
|
||||
end
|
||||
end
|
||||
|
||||
describe 'parsing a function with a conflicting return tag and type in function definition', if: TEST_FUNCTION_RETURN_TYPE do
|
||||
let(:source) { <<-SOURCE
|
||||
# A simple foo function.
|
||||
# @return [Integer] this is a lie.
|
||||
function foo() >> Struct[{'a' => Integer[1, 10]}] {
|
||||
notice 'hello world'
|
||||
}
|
||||
SOURCE
|
||||
}
|
||||
|
||||
it 'should prefer the return type from the function definition' do
|
||||
expect{ subject }.to output(/\[warn\]: Documented return type does not match return type in function definition near \(stdin\):3\./).to_stdout_from_any_process
|
||||
expect(subject.size).to eq(1)
|
||||
object = subject.first
|
||||
expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Function)
|
||||
tags = object.docstring.tags(:return)
|
||||
expect(tags.size).to eq(1)
|
||||
expect(tags[0].tag_name).to eq('return')
|
||||
expect(tags[0].text).to eq('this is a lie.')
|
||||
expect(tags[0].types).to eq(["Struct[{'a' => Integer[1, 10]}]"])
|
||||
end
|
||||
end
|
||||
|
||||
describe 'parsing a function without a return tag or return type in the function definition' do
|
||||
let(:source) { <<-SOURCE
|
||||
# A simple foo function.
|
||||
function foo() {
|
||||
notice 'hello world'
|
||||
}
|
||||
SOURCE
|
||||
}
|
||||
|
||||
it 'should add a return tag with a default type value of Any' do
|
||||
expect{ subject }.to output(/\[warn\]: Missing @return tag near \(stdin\):2\./).to_stdout_from_any_process
|
||||
expect(subject.size).to eq(1)
|
||||
object = subject.first
|
||||
expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Function)
|
||||
tags = object.docstring.tags(:return)
|
||||
expect(tags.size).to eq(1)
|
||||
expect(tags[0].tag_name).to eq('return')
|
||||
expect(tags[0].text).to eq('')
|
||||
expect(tags[0].types).to eq(['Any'])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -168,4 +168,42 @@ SOURCE
|
|||
expect(statement.parameters[2].value).to eq('hi')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'parsing puppet functions with return type in defintion', if: TEST_FUNCTION_RETURN_TYPE do
|
||||
let(:source) { <<SOURCE
|
||||
# A simple foo function.
|
||||
# @return Returns a string
|
||||
function foo() >> String {
|
||||
notice world
|
||||
}
|
||||
SOURCE
|
||||
}
|
||||
|
||||
it 'should parse the puppet function statement' do
|
||||
subject.parse
|
||||
expect(subject.enumerator.size).to eq(1)
|
||||
statement = subject.enumerator.first
|
||||
expect(statement).to be_a(PuppetStrings::Yard::Parsers::Puppet::FunctionStatement)
|
||||
expect(statement.type).to eq('String')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'parsing puppet functions with complex return types in defintion', if: TEST_FUNCTION_RETURN_TYPE do
|
||||
let(:source) { <<SOURCE
|
||||
# A simple foo function.
|
||||
# @return Returns a struct with a hash including one key which must be an integer between 1 and 10.
|
||||
function foo() >> Struct[{'a' => Integer[1, 10]}] {
|
||||
notice world
|
||||
}
|
||||
SOURCE
|
||||
}
|
||||
|
||||
it 'should parse the puppet function statement' do
|
||||
subject.parse
|
||||
expect(subject.enumerator.size).to eq(1)
|
||||
statement = subject.enumerator.first
|
||||
expect(statement).to be_a(PuppetStrings::Yard::Parsers::Puppet::FunctionStatement)
|
||||
expect(statement.type).to eq("Struct\[{'a' => Integer[1, 10]}\]")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue