lib/duck_testing/yard/method_object.rb
require "duck_testing/yard/code_object"
module DuckTesting
module YARD
# Encapsulate `YARD::CodeObjects::MethodObject`.
class MethodObject < CodeObject
# @!attribute [r] name
# Returns the name of the object.
#
# @return [String]
# @!attribute [r] scope
# Returns the scope of the object.
#
# @return [Symbol]
def_delegators :@yard_object, "name", "scope"
# @return [String]
def signature
"#{name}(#{parameters_signature})"
end
# @return [Array<DuckTesting::YARD::MethodParameter>]
def method_parameters
@method_parameters ||= begin
if yard_object.parameters.any?
yard_object.parameters.map do |name, default|
MethodParameter.new(self, name, default, get_parameter_tag(name))
end
elsif parameter_tags.any?
# Maybe the method is defined using a DSL and its signature is
# declared with "@!method" directive.
parameter_tags.map do |tag|
MethodParameter.new(self, tag.name, nil, tag)
end
else
# The method does not take any arguments.
[]
end
end
end
# @return [Array<DuckTesting::YARD::MethodParameter>]
def keyword_parameters
method_parameters.select(&:keyword?)
end
# @return [YARD::Tags::Tag]
def return_tag
@return_tag ||= yard_object.tags.find { |tag| tag.tag_name == "return" }
end
# @return [Array<DuckTesting::Type::Base>]
def expected_return_types
return_tag ? DuckTesting::YARD.expected_types(return_tag.types) : []
end
# @return [Boolean]
def public_instance_method?
yard_object.scope == :instance
end
# @return [Boolean]
def public_class_method?
yard_object.scope == :class
end
private
# @return [String]
def parameters_signature
method_parameters.map(&:to_s).join(", ")
end
# @return [YARD::Tags::Tag]
def get_parameter_tag(name)
parameter_tags.find do |tag|
name == (name.end_with?(":") ? "#{tag.name}:" : tag.name)
end
end
# @return [Array<YARD::Tags::Tag>]
def parameter_tags
@parameter_tags ||= yard_object.tags.select { |tag| tag.tag_name == "param" }
end
end
end
end