# encoding: utf-8moduleRuboCopmoduleCopmoduleStyle# This cop checks for redundant uses of `self`.## `self` is only needed when:## * Sending a message to same object with zero arguments in# presence of a method name clash with an argument or a local# variable.## Note, with using explicit self you can only send messages# with public or protected scope, you cannot send private# messages this way.## Example:## def bar# :baz# end## def foo(bar)# self.bar # resolves name clash with argument# end## def foo2# bar = 1# self.bar # resolves name clash with local variable# end## * Calling an attribute writer to prevent an local variable assignment## attr_writer :bar## def foo# self.bar= 1 # Make sure above attr writer is called# end## Special cases:## We allow uses of `self` with operators because it would be awkward# otherwise.classRedundantSelf<CopMSG='Redundant `self` detected.'definitialize(config=nil,options=nil)super@allowed_send_nodes=[]@local_variables=[]end# Assignment of self.xdefon_or_asgn(node)lhs,_rhs=*nodeallow_self(lhs)endalias_method:on_and_asgn,:on_or_asgndefon_op_asgn(node)lhs,_op,_rhs=*nodeallow_self(lhs)end# Using self.x to distinguish from local variable xdefon_def(_node)@local_variables=[]enddefon_defs(_node)@local_variables=[]enddefon_args(node)node.children.each{|arg|on_argument(arg)}enddefon_blockarg(node)on_argument(node)enddefon_lvasgn(node)lhs,_rhs=*node@local_variables<<lhsend# Detect offensesdefon_send(node)receiver,method_name,*_args=*nodereturnunlessreceiver&&receiver.type==:selfreturnifoperator?(method_name)||keyword?(method_name)||constant_name?(method_name)||@allowed_send_nodes.include?(node)||@local_variables.include?(method_name)add_offense(node,:expression)enddefautocorrect(node)receiver,_method_name,*_args=*nodelambdado|corrector|corrector.remove(receiver.loc.expression)corrector.remove(node.loc.dot)endendprivatedefon_argument(node)name,=*node@local_variables<<nameenddefoperator?(method_name)method_name.to_s=~/\W/enddefkeyword?(method_name)[:alias,:and,:begin,:break,:case,:class,:def,:defined,:do,:else,:elsif,:end,:ensure,:false,:for,:if,:in,:module,:next,:nil,:not,:or,:redo,:rescue,:retry,:return,:self,:super,:then,:true,:undef,:unless,:until,:when,:while,:yield].include?(method_name)enddefconstant_name?(method_name)method_name.match(/^[A-Z]/)enddefallow_self(node)returnunlessnode.type==:sendreceiver,_method_name,*_args=*node@allowed_send_nodes<<nodeifreceiver&&receiver.type==:selfendendendendend