class Rubocop::DefinitionValidator::Method
a method
Attributes
name[R]
Public Class Methods
new(definition)
click to toggle source
@param [String] definition
Definition Example:
def f(a, b, c, m = 1, n = 1, *rest, x, y, z, k: 1, **kwrest, &blk)
AST Example:
[:program, [[:def, [:@ident, "f", [1, 4]], [:paren, [:params, [[:@ident, "a", [1, 6]], [:@ident, "b", [1, 9]], [:@ident, "c", [1, 12]]], [[[:@ident, "m", [1, 15]], [:@int, "1", [1, 19]]], [[:@ident, "n", [1, 22]], [:@int, "1", [1, 26]]]], [:rest_param, [:@ident, "rest", [1, 30]]], [[:@ident, "x", [1, 36]], [:@ident, "y", [1, 39]], [:@ident, "z", [1, 42]]], [[[:@label, "k:", [1, 45]], [:@int, "1", [1, 48]]]], [:@ident, "kwrest", [1, 53]], [:blockarg, [:@ident, "blk", [1, 62]]]]], [:bodystmt, [[:void_stmt]], nil, nil, nil]]]]
# File lib/rubocop/definition_validator/method.rb, line 30 def initialize(definition) code = "#{definition}; end" ast = Ripper.sexp(code) begin params = ast[1][0][2] name = ast[1][0][1][1] rescue NoMethodError => ex raise InvalidAST, "Can't parse AST. \nCode: #{code}\nError: #{ex}" end if params[0] == :paren params = params[1] end @params = params[1..-1] @name = name end
Public Instance Methods
callable?(name, args)
click to toggle source
@param [Array<RuboCop::Node>] args @return [Boolean] callable @return [Object] cause
# File lib/rubocop/definition_validator/method.rb, line 52 def callable?(name, args) return false, :method_name unless name == @name args = args.dup # 通常の引数分shift normal_params_size = (normal_params || []).size received_normal_params_size = args.shift(normal_params_size).size unless received_normal_params_size == normal_params_size return false, :not_enough_norml_arguments, received_normal_params_size, normal_params_size end if has_required_keyword_params? decide_with_required_keyword_params(args) elsif has_keyword_params? decide_with_keyword_params(args) else decide_rest_args(args) end end
Private Instance Methods
decide_rest_args(args)
click to toggle source
decide default_value_params, rest_params, normal_params_after_rest @param [Array<RuboCop::Node>] args @return [Boolean]
# File lib/rubocop/definition_validator/method.rb, line 96 def decide_rest_args(args) normal_params_after_rest_size = (normal_params_after_rest || []).size given_normal_params_after_rest_size = args.pop(normal_params_after_rest_size).size unless given_normal_params_after_rest_size == normal_params_after_rest_size return false, :not_enough_normal_after_rest_arguments, given_normal_params_after_rest_size, normal_params_after_rest_size end # rest引数があれば全て呑み込むためtrue return true if rest_params # デフォルト値付き引数の数だけは呑み込める if default_value_params return true if args.size <= default_value_params.size # XXX: optimize message. return false, :too_many_arguments end return true if args.empty? return false, :too_many_arguments end
decide_with_keyword_params(args)
click to toggle source
# File lib/rubocop/definition_validator/method.rb, line 123 def decide_with_keyword_params(args) ok, *_ = decide_rest_args(args.dup) return true if ok return decide_with_required_keyword_params(args) end
decide_with_required_keyword_params(args)
click to toggle source
# File lib/rubocop/definition_validator/method.rb, line 115 def decide_with_required_keyword_params(args) kwparam = args.pop(1) usable, *reason = usable_as_keyword_param?(kwparam[0]) return false, *reason unless usable return decide_rest_args(args) end
has_keyword_params?()
click to toggle source
# File lib/rubocop/definition_validator/method.rb, line 131 def has_keyword_params? !!((keyword_params && !keyword_params.empty?) || keyword_rest_params) end
has_required_keyword_params?()
click to toggle source
# File lib/rubocop/definition_validator/method.rb, line 136 def has_required_keyword_params? (keyword_params && !keyword_params.empty?) && keyword_params.any?{|p| p[1] == false} end
usable_as_keyword_param?(arg)
click to toggle source
@param [RuboCop::Node] arg
# File lib/rubocop/definition_validator/method.rb, line 143 def usable_as_keyword_param?(arg) # should be hash return false, :kwparam_required unless arg return false, :kwparam_should_be_hash, arg.loc.expression.source unless arg.hash_type? || !arg.literal? # should have specified keyword return true unless arg.hash_type? required_keyword_names = keyword_params .select{|x| x[1] == false} .map{|x| x[0][1]} .map{|x| x.chop.to_sym} received_keyword_names = arg .children .map(&:children) .map{|x| x.first} .map(&:children) .map{|x| x.first} not_fould_requireds = required_keyword_names.select do |name| not received_keyword_names.include?(name) end unless not_fould_requireds.empty? return false, :kwparam_not_found, not_fould_requireds.join(', ') end return true if keyword_rest_params allowed_keyword_names = keyword_params .map{|x| x[0][1]} .map{|x| x.chop.to_sym} unexpected_keywords = received_keyword_names.select do |name| not allowed_keyword_names.include?(name) end unless unexpected_keywords.empty? return false, :unexpected_kwparam, unexpected_keywords end return true end