<commit_before>require "graphql/language/nodes"

module GraphQL
  module Language
    module Nodes
      class AbstractNode
        def generate_value(value)
          case value
          when AbstractNode
            value.to_query_string
          when FalseClass, Float, Integer, NilClass, String, TrueClass
            JSON.generate(value, quirks_mode: true)
          when Array
            "[#{value.map { |v| generate_value(v) }.join(", ")}]"
          when Hash
            "{#{value.map { |k, v| "#{k}: #{generate_value(v)}" }.join(", ")}}"
          else
            raise TypeError
          end
        end

        def generate_directives(directives)
          if directives.any?
            directives.map { |d| " #{d.to_query_string}" }.join
          else
            ""
          end
        end

        def generate_selections(selections, indent: "")
          if selections.any?
            out = " {\n"
            selections.each do |selection|
              out << selection.to_query_string(indent: indent + "  ") << "\n"
            end
            out << "#{indent}}"
          else
            ""
          end
        end
      end

      class Argument < AbstractNode
        def to_query_string
          "#{name}: #{generate_value(value)}"
        end
      end

      class Directive < AbstractNode
        def to_query_string
          "@#{name}(#{arguments.map(&:to_query_string).join(", ")})"
        end
      end

      class Document < AbstractNode
        def to_query_string
          definitions.map(&:to_query_string).join("\n")
        end
      end

      class Enum < NameOnlyNode
        def to_query_string
          "#{name}"
        end
      end

      class Field < AbstractNode
        def to_query_string(indent: "")
          out = "#{indent}"
          out << "#{self.alias}: " if self.alias
          out << "#{name}"
          out << "(#{arguments.map(&:to_query_string).join(", ")})" if arguments.any?
          out << generate_directives(directives)
          out << generate_selections(selections, indent: indent)
          out
        end
      end

      class FragmentDefinition < AbstractNode
        def to_query_string(indent: "")
          out = "#{indent}fragment #{name}"
          out << " on #{type}" if type
          out << generate_directives(directives)
          out << generate_selections(selections, indent: indent)
          out
        end
      end

      class FragmentSpread < AbstractNode
        def to_query_string(indent: "")
          out = "#{indent}... #{name}"
          out << generate_directives(directives)
          out
        end
      end

      class InlineFragment < AbstractNode
        def to_query_string(indent: "")
          out = "#{indent}..."
          out << " on #{type}" if type
          out << generate_directives(directives)
          out << generate_selections(selections, indent: indent)
          out
        end
      end

      class InputObject < AbstractNode
        def to_query_string
          generate_value(to_h)
        end
      end

      class ListType < WrapperType
        def to_query_string
          "[#{of_type.to_query_string}]"
        end
      end

      class NonNullType < WrapperType
        def to_query_string
          "#{of_type.to_query_string}!"
        end
      end

      class OperationDefinition < AbstractNode
        def to_query_string(indent: "")
          out = "#{indent}#{operation_type}"
          out << " #{name}" if name
          out << "(#{variables.map(&:to_query_string).join(", ")})" if variables.any?
          out << generate_directives(directives)
          out << generate_selections(selections, indent: indent)
          out
        end
      end

      class TypeName < NameOnlyNode
        def to_query_string
          "#{name}"
        end
      end

      class VariableDefinition < AbstractNode
        def to_query_string
          out = "$#{name}: #{type.to_query_string}"
          out << " = #{generate_value(default_value)}" if default_value
          out
        end
      end

      class VariableIdentifier < NameOnlyNode
        def to_query_string
          "$#{name}"
        end
      end
    end

    module Generation
      def self.generate(node)
        node.to_query_string
      end
    end
  end
end<commit_msg>Move node query string generation into Generation module<commit_after>require "graphql/language/nodes"

module GraphQL
  module Language
    module Nodes
      class Document < AbstractNode
        def to_query_string
          Generation.generate(self)
        end
      end
    end

    module Generation
      def self.generate(node, indent: "")
        case node
        when Nodes::Document
          node.definitions.map { |d| generate(d) }.join("\n")
        when Nodes::Argument
          "#{node.name}: #{generate(node.value)}"
        when Nodes::Directive
          "@#{node.name}(#{node.arguments.map { |a| generate(a) }.join(", ")})"
        when Nodes::Enum
          "#{node.name}"
        when Nodes::Field
          out = "#{indent}"
          out << "#{node.alias}: " if node.alias
          out << "#{node.name}"
          out << "(#{node.arguments.map { |a| generate(a) }.join(", ")})" if node.arguments.any?
          out << generate_directives(node.directives)
          out << generate_selections(node.selections, indent: indent)
          out
        when Nodes::FragmentDefinition
          out = "#{indent}fragment #{node.name}"
          out << " on #{node.type}" if node.type
          out << generate_directives(node.directives)
          out << generate_selections(node.selections, indent: indent)
          out

        when Nodes::FragmentSpread
          out = "#{indent}... #{node.name}"
          out << generate_directives(node.directives)
          out
        when Nodes::InlineFragment
          out = "#{indent}..."
          out << " on #{node.type}" if node.type
          out << generate_directives(node.directives)
          out << generate_selections(node.selections, indent: indent)
          out
        when Nodes::InputObject
          generate(node.to_h)
        when Nodes::ListType
          "[#{generate(node.of_type)}]"
        when Nodes::NonNullType
          "#{generate(node.of_type)}!"
        when Nodes::OperationDefinition
          out = "#{indent}#{node.operation_type}"
          out << " #{node.name}" if node.name
          out << "(#{node.variables.map { |v| generate(v) }.join(", ")})" if node.variables.any?
          out << generate_directives(node.directives)
          out << generate_selections(node.selections, indent: indent)
          out
        when Nodes::TypeName
          "#{node.name}"
        when Nodes::VariableDefinition
          out = "$#{node.name}: #{generate(node.type)}"
          out << " = #{generate(node.default_value)}" if node.default_value
          out
        when Nodes::VariableIdentifier
          "$#{node.name}"
        when Nodes::AbstractNode
          node.to_query_string(indent: indent)
        when FalseClass, Float, Integer, NilClass, String, TrueClass
          JSON.generate(node, quirks_mode: true)
        when Array
          "[#{node.map { |v| generate(v) }.join(", ")}]"
        when Hash
          "{#{node.map { |k, v| "#{k}: #{generate(v)}" }.join(", ")}}"
        else
          raise TypeError
        end
      end

      def self.generate_directives(directives)
        if directives.any?
          directives.map { |d| " #{generate(d)}" }.join
        else
          ""
        end
      end

      def self.generate_selections(selections, indent: "")
        if selections.any?
          out = " {\n"
          selections.each do |selection|
            out << generate(selection, indent: indent + "  ") << "\n"
          end
          out << "#{indent}}"
        else
          ""
        end
      end
    end
  end
end
{'fraction_non_alphanumeric': 0.1190233977619532, 'fraction_numerical': 0.0, 'mean_word_length': 1.8129470672389127, 'pattern_counts': {'":': 0, '<': 99, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4209035', 'n_tokens_mistral': 2198, 'n_tokens_neox': 2207, 'n_words': 511}