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.



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

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

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



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

def args
  @args
end

#blockObject (readonly)

Returns the value of attribute block.



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

def block
  @block
end

#nameObject (readonly)

Returns the value of attribute name.



136
137
138
# File 'lib/querly/pattern/expr.rb', line 136

def name
  @name
end

#receiverObject (readonly)

Returns the value of attribute receiver.



137
138
139
# File 'lib/querly/pattern/expr.rb', line 137

def receiver
  @receiver
end

Instance Method Details

#=~(pair) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/querly/pattern/expr.rb', line 148

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



250
251
252
253
254
255
256
257
258
259
# File 'lib/querly/pattern/expr.rb', line 250

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



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
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/querly/pattern/expr.rb', line 198

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

  case args
  when Argument::AnySeq
    case args.tail
    when Argument::KeyValue
      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
    when Argument::Expr
      nodes.size.times.any? do |i|
        test_args(nodes.drop(i), 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



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/querly/pattern/expr.rb', line 261

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_name(node) ⇒ Object



161
162
163
164
165
166
167
168
169
170
# File 'lib/querly/pattern/expr.rb', line 161

def test_name(node)
  name.map do |n|
    case n
    when String
      n.to_sym
    else
      n
    end
  end.any? {|n| n === node.children[1] }
end

#test_node(node) ⇒ Object



172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/querly/pattern/expr.rb', line 172

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 test_name(node)
    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



187
188
189
190
191
192
193
194
195
196
# File 'lib/querly/pattern/expr.rb', line 187

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