Module: GraphQL::StaticValidation::ArgumentLiteralsAreCompatible

Defined in:
lib/graphql/static_validation/rules/argument_literals_are_compatible.rb

Instance Method Summary collapse

Instance Method Details

#on_argument(node, parent) ⇒ Object

TODO dedup with ArgumentsAreDefined



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
# File 'lib/graphql/static_validation/rules/argument_literals_are_compatible.rb', line 6

def on_argument(node, parent)
  parent_defn = case parent
  when GraphQL::Language::Nodes::InputObject
    arg_defn = context.argument_definition
    if arg_defn.nil?
      nil
    else
      arg_ret_type = arg_defn.type.unwrap
      if !arg_ret_type.kind.input_object?
        nil
      else
        arg_ret_type
      end
    end
  when GraphQL::Language::Nodes::Directive
    context.schema.directives[parent.name]
  when GraphQL::Language::Nodes::Field
    context.field_definition
  else
    raise "Unexpected argument parent: #{parent.class} (##{parent})"
  end

  if parent_defn && !node.value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
    arg_defn = parent_defn.arguments[node.name]
    if arg_defn
      begin
        valid = context.valid_literal?(node.value, arg_defn.type)
      rescue GraphQL::CoercionError => err
        context.schema.error_bubbling
        if !context.schema.error_bubbling && !arg_defn.type.unwrap.kind.scalar?
          # if error bubbling is disabled and the arg that caused this error isn't a scalar then
          # short-circuit here so we avoid bubbling this up to whatever input_object / array contains us
          return super
        end
        error = GraphQL::StaticValidation::ArgumentLiteralsAreCompatibleError.new(err.message, nodes: parent, type: "CoercionError", extensions: err.extensions)
      rescue GraphQL::LiteralValidationError => err
        # check to see if the ast node that caused the error to be raised is
        # the same as the node we were checking here.
        arg_type = arg_defn.type
        if arg_type.kind.non_null?
          arg_type = arg_type.of_type
        end

        matched = if arg_type.kind.list?
          # for a list we claim an error if the node is contained in our list
          Array(node.value).include?(err.ast_value)
        elsif arg_type.kind.input_object? && node.value.is_a?(GraphQL::Language::Nodes::InputObject)
          # for an input object we check the arguments
          node.value.arguments.include?(err.ast_value)
        else
          # otherwise we just check equality
          node.value == err.ast_value
        end
        if !matched
          # This node isn't the node that caused the error,
          # So halt this visit but continue visiting the rest of the tree
          return super
        end
      end

      if !valid
        error ||= begin
          kind_of_node = node_type(parent)
          error_arg_name = parent_name(parent, parent_defn)
          string_value = if node.value == Float::INFINITY
            ""
          else
            " (#{GraphQL::Language::Printer.new.print(node.value)})"
          end

          GraphQL::StaticValidation::ArgumentLiteralsAreCompatibleError.new(
            "Argument '#{node.name}' on #{kind_of_node} '#{error_arg_name}' has an invalid value#{string_value}. Expected type '#{arg_defn.type.to_type_signature}'.",
            nodes: parent,
            type: kind_of_node,
            argument: node.name
          )
        end
        add_error(error)
      end
    end
  end

  super
end