1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
|
# frozen_string_literal: true
module RuboCop
module AST
# Common predicates for nodes that reference method identifiers:
# `send`, `csend`, `def`, `defs`, `super`, `zsuper`
#
# @note this mixin expects `#method_name` and `#receiver` to be implemented
module MethodIdentifierPredicates # rubocop:disable Metrics/ModuleLength
ENUMERATOR_METHODS = %i[collect collect_concat detect downto each
find find_all find_index inject loop map!
map reduce reject reject! reverse_each select
select! times upto].to_set.freeze
ENUMERABLE_METHODS = (Enumerable.instance_methods + [:each]).to_set.freeze
# http://phrogz.net/programmingruby/language.html#table_18.4
OPERATOR_METHODS = %i[| ^ & <=> == === =~ > >= < <= << >> + - * /
% ** ~ +@ -@ !@ ~@ [] []= ! != !~ `].to_set.freeze
NONMUTATING_BINARY_OPERATOR_METHODS = %i[* / % + - == === != < > <= >= <=>].to_set.freeze
NONMUTATING_UNARY_OPERATOR_METHODS = %i[+@ -@ ~ !].to_set.freeze
NONMUTATING_OPERATOR_METHODS = (NONMUTATING_BINARY_OPERATOR_METHODS +
NONMUTATING_UNARY_OPERATOR_METHODS).freeze
NONMUTATING_ARRAY_METHODS = %i[
all? any? assoc at bsearch bsearch_index collect
combination compact count cycle deconstruct difference
dig drop drop_while each each_index empty? eql?
fetch filter find_index first flatten hash
include? index inspect intersection join
last length map max min minmax none? one? pack
permutation product rassoc reject
repeated_combination repeated_permutation reverse
reverse_each rindex rotate sample select shuffle
size slice sort sum take take_while
to_a to_ary to_h to_s transpose union uniq
values_at zip |
].to_set.freeze
NONMUTATING_HASH_METHODS = %i[
any? assoc compact dig each each_key each_pair
each_value empty? eql? fetch fetch_values filter
flatten has_key? has_value? hash include? inspect
invert key key? keys? length member? merge rassoc
rehash reject select size slice to_a to_h to_hash
to_proc to_s transform_keys transform_values value?
values values_at
].to_set.freeze
NONMUTATING_STRING_METHODS = %i[
ascii_only? b bytes bytesize byteslice capitalize
casecmp casecmp? center chars chomp chop chr codepoints
count crypt delete delete_prefix delete_suffix
downcase dump each_byte each_char each_codepoint
each_grapheme_cluster each_line empty? encode encoding
end_with? eql? getbyte grapheme_clusters gsub hash
hex include index inspect intern length lines ljust lstrip
match match? next oct ord partition reverse rindex rjust
rpartition rstrip scan scrub size slice squeeze start_with?
strip sub succ sum swapcase to_a to_c to_f to_i to_r to_s
to_str to_sym tr tr_s unicode_normalize unicode_normalized?
unpack unpack1 upcase upto valid_encoding?
].to_set.freeze
# Checks whether the method name matches the argument.
#
# @param [Symbol, String] name the method name to check for
# @return [Boolean] whether the method name matches the argument
def method?(name)
method_name == name.to_sym
end
# Checks whether the method is an operator method.
#
# @return [Boolean] whether the method is an operator
def operator_method?
OPERATOR_METHODS.include?(method_name)
end
# Checks whether the method is a nonmutating binary operator method.
#
# @return [Boolean] whether the method is a nonmutating binary operator method
def nonmutating_binary_operator_method?
NONMUTATING_BINARY_OPERATOR_METHODS.include?(method_name)
end
# Checks whether the method is a nonmutating unary operator method.
#
# @return [Boolean] whether the method is a nonmutating unary operator method
def nonmutating_unary_operator_method?
NONMUTATING_UNARY_OPERATOR_METHODS.include?(method_name)
end
# Checks whether the method is a nonmutating operator method.
#
# @return [Boolean] whether the method is a nonmutating operator method
def nonmutating_operator_method?
NONMUTATING_OPERATOR_METHODS.include?(method_name)
end
# Checks whether the method is a nonmutating Array method.
#
# @return [Boolean] whether the method is a nonmutating Array method
def nonmutating_array_method?
NONMUTATING_ARRAY_METHODS.include?(method_name)
end
# Checks whether the method is a nonmutating Hash method.
#
# @return [Boolean] whether the method is a nonmutating Hash method
def nonmutating_hash_method?
NONMUTATING_HASH_METHODS.include?(method_name)
end
# Checks whether the method is a nonmutating String method.
#
# @return [Boolean] whether the method is a nonmutating String method
def nonmutating_string_method?
NONMUTATING_STRING_METHODS.include?(method_name)
end
# Checks whether the method is a comparison method.
#
# @return [Boolean] whether the method is a comparison
def comparison_method?
Node::COMPARISON_OPERATORS.include?(method_name)
end
# Checks whether the method is an assignment method.
#
# @return [Boolean] whether the method is an assignment
def assignment_method?
!comparison_method? && method_name.to_s.end_with?('=')
end
# Checks whether the method is an enumerator method.
#
# @return [Boolean] whether the method is an enumerator
def enumerator_method?
ENUMERATOR_METHODS.include?(method_name) ||
method_name.to_s.start_with?('each_')
end
# Checks whether the method is an Enumerable method.
#
# @return [Boolean] whether the method is an Enumerable method
def enumerable_method?
ENUMERABLE_METHODS.include?(method_name)
end
# Checks whether the method is a predicate method.
#
# @return [Boolean] whether the method is a predicate method
def predicate_method?
method_name.to_s.end_with?('?')
end
# Checks whether the method is a bang method.
#
# @return [Boolean] whether the method is a bang method
def bang_method?
method_name.to_s.end_with?('!')
end
# Checks whether the method is a camel case method,
# e.g. `Integer()`.
#
# @return [Boolean] whether the method is a camel case method
def camel_case_method?
method_name.to_s =~ /\A[A-Z]/
end
# Checks whether the *explicit* receiver of this node is `self`.
#
# @return [Boolean] whether the receiver of this node is `self`
def self_receiver?
receiver&.self_type?
end
# Checks whether the *explicit* receiver of node is a `const` node.
#
# @return [Boolean] whether the receiver of this node is a `const` node
def const_receiver?
receiver&.const_type?
end
# Checks whether this is a negation method, i.e. `!` or keyword `not`.
#
# @return [Boolean] whether this method is a negation method
def negation_method?
receiver && method_name == :!
end
# Checks whether this is a prefix not method, e.g. `not foo`.
#
# @return [Boolean] whether this method is a prefix not
def prefix_not?
negation_method? && loc.selector.is?('not')
end
# Checks whether this is a prefix bang method, e.g. `!foo`.
#
# @return [Boolean] whether this method is a prefix bang
def prefix_bang?
negation_method? && loc.selector.is?('!')
end
end
end
end
|