module GraphQL::StaticValidation::RequiredInputObjectAttributesArePresent

def get_parent_type(context, parent)

def get_parent_type(context, parent)
  # If argument_definition is defined we're at nested object
  # and need to refer to the containing input object type rather
  # than the field_definition.
  # h/t @rmosolgo
  arg_defn = context.argument_definition
  # Double checking that arg_defn is an input object as nested
  # scalars, namely JSON, can make it to this branch
  defn = if arg_defn && arg_defn.type.unwrap.kind.input_object?
    arg_defn.type.unwrap
  else
    context.directive_definition || context.field_definition
  end
  parent_type = context.warden.get_argument(defn, parent_name(parent, defn))
  parent_type ? parent_type.type.unwrap : nil
end

def on_input_object(node, parent)

def on_input_object(node, parent)
  if parent.is_a? GraphQL::Language::Nodes::Argument
    validate_input_object(node, context, parent)
  end
  super
end

def validate_input_object(ast_node, context, parent)

def validate_input_object(ast_node, context, parent)
  parent_type = get_parent_type(context, parent)
  return unless parent_type && parent_type.kind.input_object?
  required_fields = context.warden.arguments(parent_type)
    .select{|arg| arg.type.kind.non_null?}
    .map(&:graphql_name)
  present_fields = ast_node.arguments.map(&:name)
  missing_fields = required_fields - present_fields
  missing_fields.each do |missing_field|
    path = [*context.path, missing_field]
    missing_field_type = context.warden.get_argument(parent_type, missing_field).type
    add_error(RequiredInputObjectAttributesArePresentError.new(
      "Argument '#{missing_field}' on InputObject '#{parent_type.to_type_signature}' is required. Expected type #{missing_field_type.to_type_signature}",
      argument_name: missing_field,
      argument_type: missing_field_type.to_type_signature,
      input_object_type: parent_type.to_type_signature,
      path: path,
      nodes: ast_node,
    ))
  end
end