File: method_identifier_predicates.rb

package info (click to toggle)
ruby-rubocop-ast 0.3.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 892 kB
  • sloc: ruby: 10,886; makefile: 4
file content (210 lines) | stat: -rw-r--r-- 7,935 bytes parent folder | download
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