require 'reek/source/sexp_node' module Reek module Source module SexpExtensions # Base module for utility methods for argument nodes. module ArgNodeBase def name children.first end # Other is a symbol? def ==(other) name == other end def marked_unused? plain_name.start_with?('_') end def plain_name name.to_s end def block? false end def optional_argument? false end def anonymous_splat? false end end # Utility methods for :arg nodes. module ArgNode include ArgNodeBase end # Utility methods for :kwarg nodes. module KwargNode include ArgNodeBase end # Utility methods for :optarg nodes. module OptargNode include ArgNodeBase def optional_argument? true end end # Utility methods for :kwoptarg nodes. module KwoptargNode include ArgNodeBase def optional_argument? true end end # Utility methods for :blockarg nodes. module BlockargNode include ArgNodeBase def block? true end end # Utility methods for :restarg nodes. module RestargNode include ArgNodeBase def anonymous_splat? !name end end # Utility methods for :kwrestarg nodes. module KwrestargNode include ArgNodeBase def anonymous_splat? !name end end # Base module for utility methods for :and and :or nodes. module LogicOperatorBase def condition() self[1] end def body_nodes(type, ignoring = []) self[2].find_nodes type, ignoring end end module AndNode include LogicOperatorBase end # Utility methods for :or nodes module OrNode include LogicOperatorBase end # Utility methods for :attrasgn nodes module AttrasgnNode def args() self[3] end end # Utility methods for :case nodes module CaseNode def condition() self[1] end def body_nodes(type, ignoring = []) children[1..-1].compact.flat_map { |child| child.find_nodes(type, ignoring) } end def else_body children.last end end # Utility methods for :when nodes module WhenNode def condition_list children[0..-2] end def body children.last end end # Utility methods for :send nodes module SendNode def receiver() self[1] end def method_name() self[2] end def args() self[3..-1] end def participants ([receiver] + args).compact end def arg_names args.map { |arg| arg[1] } end end # Base module for utility methods for nodes representing variables. module VariableBase def name() self[1] end end # Utility methods for :cvar nodes. module CvarNode include VariableBase end CvasgnNode = CvarNode CvdeclNode = CvarNode # Utility methods for :ivar nodes. module IvarNode include VariableBase end # Utility methods for :ivasgn nodes. module IvasgnNode include VariableBase end module LvarNode def var_name() self[1] end end # Base module for utility methods for :def and :defs nodes. module MethodNodeBase def arguments parameters.reject(&:block?) end def arg_names arguments.map(&:name) end def parameters argslist.children end def parameter_names parameters.map(&:name) end def name_without_bang name.to_s.chop end def ends_with_bang? name[-1] == '!' end def body_nodes(types, ignoring = []) if body body.find_nodes(types, ignoring) else [] end end end # Utility methods for :def nodes. module DefNode def name() self[1] end def argslist() self[2] end def body self[3] end include MethodNodeBase def full_name(outer) prefix = outer == '' ? '' : "#{outer}#" "#{prefix}#{name}" end end module DefsNode def receiver() self[1] end def name() self[2] end def argslist() self[3] end def body self[4] end include MethodNodeBase def full_name(outer) prefix = outer == '' ? '' : "#{outer}#" "#{prefix}#{SexpNode.format(receiver)}.#{name}" end end # Utility methods for :if nodes module IfNode def condition() self[1] end def body_nodes(type, ignoring = []) children[1..-1].compact.flat_map { |child| child.find_nodes(type, ignoring) } end end # Utility methods for :block nodes. module BlockNode def call() self[1] end def args() self[2] end def block() self[3] end def parameters() self[2] || [] end def parameter_names parameters[1..-1].to_a end end module LitNode def value() self[1] end end # Utility methods for :const nodes. module ConstNode def simple_name children.last end end # Utility methods for :module nodes. module ModuleNode def name() self[1] end def simple_name name.is_a?(AST::Node) ? name.simple_name : name end def full_name(outer) prefix = outer == '' ? '' : "#{outer}::" "#{prefix}#{text_name}" end def text_name SexpNode.format(name) end end module ClassNode include ModuleNode def superclass() self[2] end end module YieldNode def args() self[1..-1] end def arg_names args.map { |arg| arg[1] } end end module ZsuperNode def method_name :super end end end end end