Class: Querly::Pattern::Expr::Send

Inherits:
Base
  • Object
show all
Defined in:
lib/querly/pattern/expr.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#==, #attributes

Constructor Details

#initialize(receiver:, name:, block:, args: Argument::AnySeq.new) ⇒ Send

Returns a new instance of Send.



144
145
146
147
148
149
# File 'lib/querly/pattern/expr.rb', line 144

def initialize(receiver:, name:, block:, args: Argument::AnySeq.new)
  @name = name
  @receiver = receiver
  @args = args
  @block = block
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



141
142
143
# File 'lib/querly/pattern/expr.rb', line 141

def args
  @args
end

#blockObject (readonly)

Returns the value of attribute block.



142
143
144
# File 'lib/querly/pattern/expr.rb', line 142

def block
  @block
end

#nameObject (readonly)

Returns the value of attribute name.



139
140
141
# File 'lib/querly/pattern/expr.rb', line 139

def name
  @name
end

#receiverObject (readonly)

Returns the value of attribute receiver.



140
141
142
# File 'lib/querly/pattern/expr.rb', line 140

def receiver
  @receiver
end

Instance Method Details

#=~(pair) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/querly/pattern/expr.rb', line 151

def =~(pair)
  # Skip send node with block
  if pair.node.type == :send && pair.parent
    if pair.parent.node.type == :block
      if pair.parent.node.children.first.equal? pair.node
        return false
      end
    end
  end

  test_node pair.node
end

#hash_node_to_hash(node) ⇒ Object



237
238
239
240
241
242
243
244
245
246
# File 'lib/querly/pattern/expr.rb', line 237

def hash_node_to_hash(node)
  node.children.each.with_object({}) do |pair, h|
    key = pair.children[0]
    value = pair.children[1]

    if key.type == :sym
      h[key.children[0]] = value
    end
  end
end

#test_args(nodes, args) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/querly/pattern/expr.rb', line 190

def test_args(nodes, args)
  first_node = nodes.first

  case args
  when Argument::AnySeq
    if args.tail
      if first_node
        case
        when nodes.last.type == :kwsplat
          true
        when nodes.last.type == :hash && args.tail.is_a?(Argument::KeyValue)
          hash = hash_node_to_hash(nodes.last)
          test_hash_args(hash, args.tail)
        else
          test_hash_args({}, args.tail)
        end
      else
        test_hash_args({}, args.tail)
      end
    else
      true
    end
  when Argument::Expr
    if first_node
      args.expr.test_node(nodes.first) && test_args(nodes.drop(1), args.tail)
    end
  when Argument::KeyValue
    if first_node
      types = nodes.map(&:type)
      if types == [:hash]
        hash = hash_node_to_hash(nodes.first)
        test_hash_args(hash, args)
      elsif types == [:hash, :kwsplat]
        true
      else
        args.negated
      end
    else
      test_hash_args({}, args)
    end
  when Argument::BlockPass
    first_node&.type == :block_pass && args.expr.test_node(first_node.children.first)
  when nil
    nodes.empty?
  end
end

#test_hash_args(hash, args) ⇒ Object



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/querly/pattern/expr.rb', line 248

def test_hash_args(hash, args)
  while args
    if args.is_a?(Argument::KeyValue)
      node = hash[args.key]

      if !args.negated == !!(node && args.value.test_node(node))
        hash.delete args.key
      else
        return false
      end
    else
      break
    end

    args = args.tail
  end

  args.is_a?(Argument::AnySeq) || hash.empty?
end

#test_node(node) ⇒ Object



164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/querly/pattern/expr.rb', line 164

def test_node(node)
  return false if block == true && node.type != :block
  return false if block == false && node.type == :block

  node = node.children.first if node&.type == :block

  case node&.type
  when :send
    return false unless name == node.children[1]
    return false unless test_receiver(node.children[0])
    return false unless test_args(node.children.drop(2), args)
    true
  end
end

#test_receiver(node) ⇒ Object



179
180
181
182
183
184
185
186
187
188
# File 'lib/querly/pattern/expr.rb', line 179

def test_receiver(node)
  case receiver
  when Self
    !node || receiver.test_node(node)
  when nil
    true
  else
    receiver.test_node(node)
  end
end