Merge pull request #33 from iankronquist/dispatch-params/PDOC-37
Dispatch params/pdoc 37
This commit is contained in:
commit
2e3821c2af
|
@ -23,32 +23,100 @@ class Puppet4xFunctionHandler < YARD::Handlers::Ruby::Base
|
|||
|
||||
handles method_call(:create_function)
|
||||
|
||||
# Given a command node which represents code like this:
|
||||
# param 'Optional[Type]', :value_type
|
||||
# Extract the type name and type signature and return them as a array.
|
||||
def extract_type_from_command command
|
||||
return [] if command.children.length < 2 or command.children[1].children.length < 2
|
||||
type_specifier = command.children[1]
|
||||
# the parameter signature is the first child of the specifier and an
|
||||
# identifier. Convert it to a string.
|
||||
param_signature = type_specifier.children[0].source
|
||||
# The parameter name is the second child of the specifier and a symbol.
|
||||
# convert it to a string.
|
||||
param_name_ident = type_specifier.jump :ident
|
||||
return [] if param_name_ident == type_specifier
|
||||
param_name = param_name_ident.source
|
||||
[param_name, param_signature]
|
||||
end
|
||||
|
||||
process do
|
||||
name = process_parameters
|
||||
|
||||
method_arguments = []
|
||||
|
||||
# To attach the method parameters to the new code object, traverse the
|
||||
# ruby AST until a node is found which defines a list of parameters.
|
||||
# ruby AST until a node is found which defines a array of parameters.
|
||||
# Then, traverse the children of the parameters, storing each identifier
|
||||
# in the list of method arguments.
|
||||
# in the array of method arguments.
|
||||
obj = MethodObject.new(function_namespace, name) do |o|
|
||||
end
|
||||
|
||||
# overload_signatures is a array of arrays of tuples or empty:
|
||||
# overload_signatures = [
|
||||
# [ # First function dispatch arguments
|
||||
# # argument name, argument type
|
||||
# ['arg0', 'Variant[String,Array[String]]'
|
||||
# ['arg1', 'Optional[Type]']
|
||||
# ],
|
||||
# [ # Second function dispatch arguments
|
||||
# ['arg0', 'Variant[String,Array[String]]'
|
||||
# ['arg1', 'Optional[Type]']
|
||||
# ['arg2', 'Any']
|
||||
# ]
|
||||
# ]
|
||||
overload_signatures = []
|
||||
statement.traverse do |node|
|
||||
# Find all of the dispatch methods
|
||||
if node.type == :ident and node.source == 'dispatch'
|
||||
command = node.parent
|
||||
do_block = command.jump :do_block
|
||||
# If the command doesn't have a do_block we can't extract type info
|
||||
if do_block == command
|
||||
next
|
||||
end
|
||||
# Iterate through each of the children of the do block and build
|
||||
# tuples of parameter names and parameter type signatures
|
||||
do_block.children.first.children.each do |child|
|
||||
overload_signatures <<= [extract_type_from_command(child)]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# If the overload_signatures array is empty because we couldn't find any
|
||||
# dispatch blocks, then there must be one method named the same as the
|
||||
# name of the function being created.
|
||||
if overload_signatures.length == 0
|
||||
statement.traverse do |node|
|
||||
if node.type == :params
|
||||
node.traverse do |params|
|
||||
if params.type == :ident
|
||||
# FIXME: Replace nil with parameter types
|
||||
method_arguments << [params[0], nil]
|
||||
# Find the function definition with the same name as the puppet
|
||||
# function being created.
|
||||
if (node.type == :def and node.children.first.type == :ident and
|
||||
node.children.first.source == obj.name.to_s)
|
||||
signature = []
|
||||
# Find its parameters. If they don't exist, fine
|
||||
params = node.jump :params
|
||||
break if params == node
|
||||
params.traverse do |param|
|
||||
if param.type == :ident
|
||||
# The parameters of Puppet functions with no defined dispatch are
|
||||
# as though they are Any type.
|
||||
signature << [param[0], 'Any']
|
||||
end
|
||||
end
|
||||
|
||||
overload_signatures <<= signature
|
||||
# Now that the parameters have been found, break out of the traversal
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
obj.parameters = method_arguments
|
||||
# Preserve this type information. We'll need it later when we look
|
||||
# at the docstring.
|
||||
obj.type_info = overload_signatures
|
||||
|
||||
# The yard docstring parser expects a array of arrays, not a array of
|
||||
# arrays of arrays.
|
||||
obj.parameters = overload_signatures.flatten(1)
|
||||
|
||||
obj['puppet_4x_function'] = true
|
||||
|
||||
|
@ -102,7 +170,7 @@ class Puppet4xFunctionHandler < YARD::Handlers::Ruby::Base
|
|||
# @return [(String, Hash{String => String})]
|
||||
def process_parameters
|
||||
# Passing `false` to parameters excludes the block param from the returned
|
||||
# list.
|
||||
# array.
|
||||
name, _ = statement.parameters(false).compact
|
||||
|
||||
name = process_element(name)
|
||||
|
@ -114,7 +182,7 @@ class Puppet4xFunctionHandler < YARD::Handlers::Ruby::Base
|
|||
# instead of `<<-`.
|
||||
HEREDOC_START = /^<?<-/
|
||||
|
||||
# Turns an entry in the method parameter list into a string.
|
||||
# Turns an entry in the method parameter array into a string.
|
||||
#
|
||||
# @param ele [YARD::Parser::Ruby::AstNode]
|
||||
# @return [String]
|
||||
|
|
|
@ -71,4 +71,106 @@ describe PuppetX::PuppetLabs::Strings::YARD::Handlers::Puppet4xFunctionHandler d
|
|||
RUBY
|
||||
}.to output("#{expected_output_not_a_param}\n#{expected_output_also_not_a_param}\n").to_stdout_from_any_process
|
||||
end
|
||||
|
||||
it "should not issue a warning when the parameter names match the docstring" do
|
||||
expect {
|
||||
parse <<-RUBY
|
||||
# @param num_a [Integer] the first number to be compared
|
||||
# @param num_b [Integer] the second number to be compared
|
||||
Puppet::Functions.create_function(:max) do
|
||||
def max(num_a, num_b)
|
||||
num_a >= num_b ? num_a : num_b
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
}.to output("").to_stdout_from_any_process
|
||||
end
|
||||
|
||||
it "should not issue a warning when there are parametarized types and parameter names are the same" do
|
||||
expect {
|
||||
parse <<-RUBY
|
||||
# @param num_a Integer[1,2] the first number to be compared
|
||||
# @param num_b Integer[1,2] the second number to be compared
|
||||
Puppet::Functions.create_function(:max) do
|
||||
def max(num_a, num_b)
|
||||
num_a >= num_b ? num_a : num_b
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
}.to output("").to_stdout_from_any_process
|
||||
end
|
||||
|
||||
it "should issue a warning when there are parametarized types and parameter names differ" do
|
||||
expected_output_not_num_a = "[warn]: @param tag has unknown parameter" +
|
||||
" name: not_num_a \n in file `(stdin)' near line 3"
|
||||
expect {
|
||||
parse <<-RUBY
|
||||
# @param not_num_a Integer[1,2] the first number to be compared
|
||||
# @param num_b Integer[1,2] the second number to be compared
|
||||
Puppet::Functions.create_function(:max) do
|
||||
dispatch max_1 do
|
||||
param 'Integer[1,2]', :num_a
|
||||
param 'Integer[1,2]', :num_b
|
||||
end
|
||||
|
||||
def max_1(num_a, num_b)
|
||||
num_a >= num_b ? num_a : num_b
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
}.to output("#{expected_output_not_num_a}\n").to_stdout_from_any_process
|
||||
end
|
||||
|
||||
|
||||
it "should issue a warning if the parameter names do not match the docstring in dispatch method" do
|
||||
expected_output_not_a_param = "[warn]: @param tag has unknown parameter" +
|
||||
" name: not_a_param \n in file `(stdin)' near line 3"
|
||||
expected_output_also_not_a_param = "[warn]: @param tag has unknown " +
|
||||
"parameter name: also_not_a_param \n in file `(stdin)' near line 3"
|
||||
expect {
|
||||
parse <<-RUBY
|
||||
# @param not_a_param Integer the first number to be compared
|
||||
# @param also_not_a_param Integer the second number to be compared
|
||||
Puppet::Functions.create_function(:max) do
|
||||
dispatch max_1 do
|
||||
param 'Integer[1,2]', :num_a
|
||||
param 'Integer', :num_b
|
||||
end
|
||||
|
||||
dispatch max_2 {
|
||||
param 'String', :num_c
|
||||
param 'String[1,2]', :num_d
|
||||
}
|
||||
|
||||
def max_1(num_a, num_b)
|
||||
num_a >= num_b ? num_a : num_b
|
||||
end
|
||||
|
||||
def max_2(num_a, num_b)
|
||||
num_a >= num_b ? num_a : num_b
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
}.to output("#{expected_output_not_a_param}\n#{expected_output_also_not_a_param}\n").to_stdout_from_any_process
|
||||
end
|
||||
|
||||
it "should not issue a warning if the parameter names do match the " +
|
||||
"docstring in dispatch method" do
|
||||
expect {
|
||||
parse <<-RUBY
|
||||
# @param num_a Integer the first number to be compared
|
||||
# @param num_b Integer the second number to be compared
|
||||
Puppet::Functions.create_function(:max) do
|
||||
dispatch max_1 do
|
||||
param 'Integer', :num_a
|
||||
param 'Integer', :num_b
|
||||
end
|
||||
|
||||
def max_1(num_a, num_b)
|
||||
num_a >= num_b ? num_a : num_b
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
}.to output("").to_stdout_from_any_process
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue