class GraphQL::StaticValidation::VariablesAreUsedAndDefined

def validate(context)

def validate(context)
  variable_usages_for_context = Hash.new {|hash, key| hash[key] = variable_hash }
  spreads_for_context = Hash.new {|hash, key| hash[key] = [] }
  variable_context_stack = []
  # OperationDefinitions and FragmentDefinitions
  # both push themselves onto the context stack (and pop themselves off)
  push_variable_context_stack = ->(node, parent) {
    # initialize the hash of vars for this context:
    variable_usages_for_context[node]
    variable_context_stack.push(node)
  }
  pop_variable_context_stack = ->(node, parent) {
    variable_context_stack.pop
  }
  context.visitor[GraphQL::Language::Nodes::OperationDefinition] << push_variable_context_stack
  context.visitor[GraphQL::Language::Nodes::OperationDefinition] << ->(node, parent) {
    # mark variables as defined:
    var_hash = variable_usages_for_context[node]
    node.variables.each { |var|
      var_usage = var_hash[var.name]
      var_usage.declared_by = node
      var_usage.path = context.path
    }
  }
  context.visitor[GraphQL::Language::Nodes::OperationDefinition].leave << pop_variable_context_stack
  context.visitor[GraphQL::Language::Nodes::FragmentDefinition] << push_variable_context_stack
  context.visitor[GraphQL::Language::Nodes::FragmentDefinition].leave << pop_variable_context_stack
  # For FragmentSpreads:
  #  - find the context on the stack
  #  - mark the context as containing this spread
  context.visitor[GraphQL::Language::Nodes::FragmentSpread] << ->(node, parent) {
    variable_context = variable_context_stack.last
    spreads_for_context[variable_context] << node.name
  }
  # For VariableIdentifiers:
  #  - mark the variable as used
  #  - assign its AST node
  context.visitor[GraphQL::Language::Nodes::VariableIdentifier] << ->(node, parent) {
    usage_context = variable_context_stack.last
    declared_variables = variable_usages_for_context[usage_context]
    usage = declared_variables[node.name]
    usage.used_by = usage_context
    usage.ast_node = node
    usage.path = context.path
  }
  context.visitor[GraphQL::Language::Nodes::Document].leave << ->(node, parent) {
    fragment_definitions = variable_usages_for_context.select { |key, value| key.is_a?(GraphQL::Language::Nodes::FragmentDefinition) }
    operation_definitions = variable_usages_for_context.select { |key, value| key.is_a?(GraphQL::Language::Nodes::OperationDefinition) }
    operation_definitions.each do |node, node_variables|
      follow_spreads(node, node_variables, spreads_for_context, fragment_definitions, [])
      create_errors(node_variables, context)
    end
  }
end