module GraphQL::StaticValidation::VariableUsagesAreAllowed
Constants
- FragmentVariableUsage
-
A variable in a fragment. Itβs checked after the visit, against each operation which uses the fragment.
list_depthis the number of list literals around the variable.
Public Class Methods
Source
# File lib/graphql/static_validation/rules/variable_usages_are_allowed.rb, line 12 def initialize(*) super # holds { name => ast_node } pairs @declared_variables = {} @operation_declared_variables = {}.compare_by_identity #: Hash[GraphQL::Language::Nodes::OperationDefinition, Hash[String, GraphQL::Language::Nodes::VariableDefinition]] @variable_usages_fragment_definition = nil @fragment_variable_usages = nil #: Hash[GraphQL::Language::Nodes::FragmentDefinition, Array[FragmentVariableUsage]]? @reported_fragment_variable_errors = nil #: Hash[GraphQL::Language::Nodes::Argument, Hash[String, bool]]? @allow_legacy_invalid_variable_usages = @schema.allow_legacy_invalid_variable_usages # The arguments and variables which have an error from the legacy check @legacy_errors = nil #: Hash[GraphQL::Language::Nodes::Argument, Hash[String, bool]]? end
Calls superclass method
Public Instance Methods
Source
# File lib/graphql/static_validation/rules/variable_usages_are_allowed.rb, line 73 def on_argument(node, parent) variables = variables_in_value(node.value, 0, nil) if variables argument_owner = case parent when GraphQL::Language::Nodes::Field context.field_definition when GraphQL::Language::Nodes::Directive context.directive_definition when GraphQL::Language::Nodes::InputObject arg_type = context.argument_definition.type.unwrap if arg_type.kind.input_object? arg_type else # This is some kind of error nil end else raise("Unexpected argument parent: #{parent}") end if (fragment_definition = @variable_usages_fragment_definition) if argument_owner usages = ((@fragment_variable_usages ||= {}.compare_by_identity)[fragment_definition] ||= []) path = context.path variables.each do |(variable, list_depth)| usages << FragmentVariableUsage.new(argument_owner, node, variable.name, list_depth, path) # Previous versions checked a fragment against the last operation before it if @allow_legacy_invalid_variable_usages != false && (var_defn_ast = @declared_variables[variable.name]) add_legacy_error(argument_owner, node, var_defn_ast, list_depth) end end end elsif argument_owner variables.each do |(variable, list_depth)| var_defn_ast = @declared_variables[variable.name] # Might be undefined :( # VariablesAreUsedAndDefined can't finalize its search until the end of the document. next if var_defn_ast.nil? legacy_reported = false if @allow_legacy_invalid_variable_usages != false # The legacy check is the same, except for a `= null` default or a variable in a nested or mixed list if var_defn_ast.default_value.is_a?(GraphQL::Language::Nodes::NullValue) || list_depth > 1 || (list_depth == 1 && depth_of_array(node.value) != 1) add_legacy_error(argument_owner, node, var_defn_ast, list_depth) else legacy_reported = true end end validate_usage(argument_owner, node, var_defn_ast, list_depth, legacy_reported: legacy_reported) end end end super end
Calls superclass method
Source
# File lib/graphql/static_validation/rules/variable_usages_are_allowed.rb, line 37 def on_document(node, parent) super # A fragment can come before the operations which use it, and many operations can use it. # So, check its variable usages after the visit, against each operation which uses it. fragment_usages = @fragment_variable_usages return if fragment_usages.nil? dependencies = context.dependencies @operation_declared_variables.each do |definition, declared_variables| next if declared_variables.empty? variable_types = {} #: Hash[String, untyped] checked_fragments = {}.compare_by_identity dependencies[definition].each do |fragment_definition| next if checked_fragments.key?(fragment_definition) checked_fragments[fragment_definition] = true usages = fragment_usages[fragment_definition] next if usages.nil? usages.each do |usage| var_defn_ast = declared_variables[usage.variable_name] # If it's undefined, VariablesAreUsedAndDefined adds an error next if var_defn_ast.nil? var_type = variable_types.fetch(usage.variable_name) { variable_types[usage.variable_name] = usage_variable_type(var_defn_ast) } next if var_type.nil? # The result depends only on the usage and the variable type, so check each pair once. # (`type_from_ast` returns the same object for the same type.) checked = (usage.checked_variable_types ||= {}.compare_by_identity) next if checked.key?(var_type) checked[var_type] = true validate_usage(usage.argument_owner, usage.arg_node, var_defn_ast, usage.list_depth, path: usage.path, var_type: var_type) end end end end
Calls superclass method
# File lib/graphql/static_validation/rules/variable_usages_are_allowed.rb, line 31 def on_fragment_definition(node, parent) @variable_usages_fragment_definition = node super @variable_usages_fragment_definition = nil end
Calls superclass method
# File lib/graphql/static_validation/rules/variable_usages_are_allowed.rb, line 25 def on_operation_definition(node, parent) @declared_variables = node.variables.each_with_object({}) { |var, memo| memo[var.name] = var } @operation_declared_variables[node] = @declared_variables super end
Calls superclass method