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