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:, args: Argument::AnySeq.new) ⇒ Send

Returns a new instance of Send.



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

def initialize(receiver:, name:, args: Argument::AnySeq.new)
  @name = name
  @receiver = receiver
  @args = args
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

#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



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

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 == pair.node
        return false
      end
    end
  end

  test_node pair.node
end

#hash_node_to_hash(node) ⇒ Object



214
215
216
217
218
219
220
221
222
223
# File 'lib/querly/pattern/expr.rb', line 214

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



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
211
212
# File 'lib/querly/pattern/expr.rb', line 171

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

  case args
  when Argument::AnySeq
    if args.tail && 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
        true
      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



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/querly/pattern/expr.rb', line 225

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



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

def test_node(node)
  node = node.children.first if node&.type == :block

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