Class: GraphqlMigrateExecution::ResolverMethod

Inherits:
Object
  • Object
show all
Defined in:
lib/graphql_migrate_execution/resolver_method.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, node) ⇒ ResolverMethod

Returns a new instance of ResolverMethod.



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 4

def initialize(name, node)
  @name = name
  @node = node
  @parameter_names = if node.parameters
    node.parameters.keywords.map(&:name)
  else
    []
  end
  @self_sends = Set.new
  @calls_object = false
  @calls_context = false
  @calls_class = false
  @calls_dataloader = false
  @dataloader_call = false
  @uses_current_path = false
  @dataload_association = nil
  @dataload_record = nil
  @dataload_record_using = nil
  @dataload_record_find_by = nil
  @return_expressions = nil
end

Instance Attribute Details

#calls_classObject

Returns the value of attribute calls_class.



30
31
32
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 30

def calls_class
  @calls_class
end

#calls_contextObject

Returns the value of attribute calls_context.



30
31
32
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 30

def calls_context
  @calls_context
end

#calls_dataloaderObject

Returns the value of attribute calls_dataloader.



30
31
32
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 30

def calls_dataloader
  @calls_dataloader
end

#calls_objectObject

Returns the value of attribute calls_object.



30
31
32
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 30

def calls_object
  @calls_object
end

#dataload_associationObject (readonly)

Returns the value of attribute dataload_association.



28
29
30
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 28

def dataload_association
  @dataload_association
end

#dataload_recordObject (readonly)

Returns the value of attribute dataload_record.



28
29
30
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 28

def dataload_record
  @dataload_record
end

#dataload_record_find_byObject (readonly)

Returns the value of attribute dataload_record_find_by.



28
29
30
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 28

def dataload_record_find_by
  @dataload_record_find_by
end

#dataload_record_usingObject (readonly)

Returns the value of attribute dataload_record_using.



28
29
30
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 28

def dataload_record_using
  @dataload_record_using
end

#dataloader_callObject

Returns the value of attribute dataloader_call.



32
33
34
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 32

def dataloader_call
  @dataloader_call
end

#load_arg_nodeObject (readonly)

Returns the value of attribute load_arg_node.



28
29
30
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 28

def load_arg_node
  @load_arg_node
end

#nameObject (readonly)

Returns the value of attribute name.



26
27
28
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 26

def name
  @name
end

#nodeObject (readonly)

Returns the value of attribute node.



26
27
28
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 26

def node
  @node
end

#parameter_namesObject (readonly)

Returns the value of attribute parameter_names.



26
27
28
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 26

def parameter_names
  @parameter_names
end

#self_sendsObject (readonly)

Returns the value of attribute self_sends.



26
27
28
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 26

def self_sends
  @self_sends
end

#source_arg_nodesObject (readonly)

Returns the value of attribute source_arg_nodes.



28
29
30
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 28

def source_arg_nodes
  @source_arg_nodes
end

#source_class_nodeObject (readonly)

Returns the value of attribute source_class_node.



28
29
30
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 28

def source_class_node
  @source_class_node
end

#uses_current_pathObject

Returns the value of attribute uses_current_path.



30
31
32
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 30

def uses_current_path
  @uses_current_path
end

Instance Method Details

#migration_strategyObject



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
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 38

def migration_strategy
  calls_to_self = self_sends.to_a
  if @calls_context
    calls_to_self.delete(:context)
  end
  if @calls_object
    calls_to_self.delete(:object)
  end

  calls_to_self.delete(:dataloader)
  calls_to_self.delete(:dataload_association)
  calls_to_self.delete(:dataload_record)
  calls_to_self.delete(:dataload)
  calls_to_self.delete(:dataload_all)

  # Global-ish methods:
  calls_to_self.delete(:raise)

  # Locals:
  calls_to_self -= @parameter_names

  if calls_to_self.empty?
    if calls_dataloader
      if !dataloader_call
        return DataloaderManual
      end

      call_node = node.body.body.first
      case call_node.name
      when :dataload
        @source_class_node = call_node.arguments.arguments.first
        @source_arg_nodes = call_node.arguments.arguments[1...-1]
        @load_arg_node = call_node.arguments.arguments.last
      when :dataload_association
        if (assoc_args = call_node.arguments.arguments).size == 1 &&
            ((assoc_arg = assoc_args.first).is_a?(Prism::SymbolNode))
          assoc_sym = assoc_arg.unescaped.to_sym
          @dataload_association = assoc_sym == name ? true : assoc_sym
        end
      when :dataload_record
        if (record_args = call_node.arguments.arguments) &&
            (record_arg = record_args.first) &&
            (record_arg.is_a?(Prism::ConstantReadNode) || record_arg.is_a?(Prism::ConstantPathNode)) &&
            (using_arg = record_args[1]) &&
            # Must be `object.{something}`
            (using_arg.is_a?(Prism::CallNode)) &&
            (using_arg.receiver.is_a?(Prism::CallNode) && using_arg.receiver.name == :object)
          @dataload_record = record_arg.full_name
          @dataload_record_using = using_arg.name

          if (kwargs = record_args.last).is_a?(Prism::KeywordHashNode) && (find_by_kwarg = kwargs.elements.find { |el| el.key.is_a?(Prism::SymbolNode) && el.key.unescaped == "find_by" })
            find_by_node = find_by_kwarg.value
            @dataload_record_find_by = find_by_node.unescaped.to_sym # Assumes a SymbolNode
          end
        end
      else
        if (source_call = call_node.receiver) # eg dataloader.with(...).load(...)
          @source_class_node = source_call.arguments.arguments.first
          @source_arg_nodes = source_call.arguments.arguments[1..-1]
          @load_arg_node = call_node.arguments.arguments.last
        end
      end

      input_is_object = @load_arg_node.is_a?(Prism::CallNode) && @load_arg_node.name == :object
      # Guess whether these args are free of runtime context:
      shortcutable_source_args = @source_arg_nodes && (@source_arg_nodes.empty? || (@source_arg_nodes.all? { |a| Visitor.constant_node?(a) }))
      source_ref_is_constant = @source_class_node.is_a?(Prism::ConstantPathNode) || @source_class_node.is_a?(Prism::ConstantReadNode)
      if source_ref_is_constant && shortcutable_source_args && input_is_object
        DataloaderShorthand
      else
        case call_node.name
        when :load, :request, :dataload
          DataloaderAll
        when :load_all, :request_all, :dataload_all
          DataloaderBatch
        when :dataload_association, :dataload_record
          DataloaderShorthand
        else
          DataloaderManual
        end
      end
    elsif calls_object
      ResolveEach
    else
      ResolveStatic
    end
  else
    NotImplemented
  end
end

#return_expressionsObject



133
134
135
136
137
138
139
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 133

def return_expressions
  if @return_expressions.nil?
    @return_expressions = []
    find_return_expressions(@node)
  end
  @return_expressions
end

#returns_hash?Boolean

Returns:

  • (Boolean)


129
130
131
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 129

def returns_hash?
  return_expressions.all? { |exp_node| exp_node.is_a?(Prism::HashNode) || (exp_node.is_a?(Prism::CallNode) && exp_node.name == :new && exp_node.receiver.is_a?(Prism::ConstantReadNode) && exp_node.receiver.name == :Hash) }
end

#returns_string_hash?Boolean

Returns:

  • (Boolean)


141
142
143
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 141

def returns_string_hash?
  return_expressions.any? { |exp_node| exp_node.is_a?(Prism::HashNode) && exp_node.elements.size > 0 && exp_node.elements.all? { |el| el.key.is_a?(Prism::StringNode) } }
end

#sourceObject



34
35
36
# File 'lib/graphql_migrate_execution/resolver_method.rb', line 34

def source
  node.location.slice_lines
end