<commit_before># frozen_string_literal: true

module GraphQL
  module Upgrader
    class Member
      def initialize(member)
        @member = member
      end

      def transform
        transformable = member.dup
        transformable = transform_to_class transformable
        transformable = transform_or_remove_name transformable
        transformable = put_the_field_name_and_return_type_and_description_on_one_line_for_easy_processing transformable
        transformable = move_the_type_from_the_block_to_the_field transformable

        transformable.scan(/(?:field|connection|argument) .*$/).each do |field|
          field_regex = /(?<field_type>field|connection|argument) :(?<name>[a-zA-Z_0-9]*)?, (?<return_type>.*?)(?<thing>,|$|\})(?<remainder>.*)/

          if (matches = field_regex.match(field))
            name = matches[:name]
            return_type = matches[:return_type]
            remainder = matches[:remainder]
            thing = matches[:thing]
            field_type = matches[:field_type]

            # Someone that knows regular expressions probably would do this in the regex, I don't
            doable = remainder.gsub!(/\ do$/, '') || return_type.gsub!(/\ do$/, '')

            # Remove the old null type indicator
            nullable = return_type.gsub! '!', ''

            # Remove the types
            return_type.gsub! 'types.', ''
            return_type.gsub! 'types[', '['

            nullable_as_keyword = nullable ? ', null: true' : ''
            connection_as_keyword = field_type == 'connection' ? ', connection: true' : ''
            field_type = field_type == 'argument' ? 'argument' : 'field'

            transformable.sub!(field) do
              "#{field_type} :#{name}, #{return_type}#{thing}#{remainder}#{nullable_as_keyword}#{connection_as_keyword}#{doable ? ' do' : ''}"
            end
          end
        end

        transformable
      end

      def transformable?
        return false if member.include? '< GraphQL::Schema::'
        return false if member.include? '< BaseObject'
        return false if member.include? '< BaseInterface'
        return false if member.include? '< BaseEnum'

        true
      end

      private

      def move_the_type_from_the_block_to_the_field(transformable)
        transformable.gsub(
          /(?<field>(?:field|connection|argument) :(?:[a-zA-Z_0-9]*)) do(?<block_contents>.*?)[ ]*type (?<return_type>.*?)\n/m
        ) do
          field = $~[:field]
          block_contents = $~[:block_contents]
          return_type = $~[:return_type]

          "#{field}, #{return_type} do#{block_contents}"
        end
      end

      def put_the_field_name_and_return_type_and_description_on_one_line_for_easy_processing(transformable)
        transformable.gsub(/(?<field>(?:field|connection|argument).*?),\n(\s*)(?<next_line>"(.*))/) do
          field = $~[:field].chomp<commit_msg>Cleaning up comments<commit_after># frozen_string_literal: true

module GraphQL
  module Upgrader
    class Member
      def initialize(member)
        @member = member
      end

      def transform
        transformable = member.dup
        transformable = transform_to_class transformable
        transformable = transform_or_remove_name transformable
        transformable = simplify_field_definition_for_easier_processing transformable
        transformable = move_the_type_from_the_block_to_the_field transformable

        transformable.scan(/(?:field|connection|argument) .*$/).each do |field|
          field_regex = /(?<field_type>field|connection|argument) :(?<name>[a-zA-Z_0-9]*)?, (?<return_type>.*?)(?<thing>,|$|\})(?<remainder>.*)/

          if (matches = field_regex.match(field))
            name = matches[:name]
            return_type = matches[:return_type]
            remainder = matches[:remainder]
            thing = matches[:thing]
            field_type = matches[:field_type]

            # This is a small bug in the regex. Ideally the `do` part would only be in the remainder.
            with_block = remainder.gsub!(/\ do$/, '') || return_type.gsub!(/\ do$/, '')

            nullable = return_type.gsub! '!', ''
            return_type.gsub! 'types.', ''
            return_type.gsub! 'types[', '['

            nullable_as_keyword = nullable ? ', null: true' : ''
            connection_as_keyword = field_type == 'connection' ? ', connection: true' : ''
            field_type = field_type == 'argument' ? 'argument' : 'field'

            transformable.sub!(field) do
              "#{field_type} :#{name}, #{return_type}#{thing}#{remainder}#{nullable_as_keyword}#{connection_as_keyword}#{with_block ? ' do' : ''}"
            end
          end
        end

        transformable
      end

      def transformable?
        return false if member.include? '< GraphQL::Schema::'
        return false if member.include? '< BaseObject'
        return false if member.include? '< BaseInterface'
        return false if member.include? '< BaseEnum'

        true
      end

      private

      def move_the_type_from_the_block_to_the_field(transformable)
        transformable.gsub(
          /(?<field>(?:field|connection|argument) :(?:[a-zA-Z_0-9]*)) do(?<block_contents>.*?)[ ]*type (?<return_type>.*?)\n/m
        ) do
          field = $~[:field]
          block_contents = $~[:block_contents]
          return_type = $~[:return_type]

          "#{field}, #{return_type} do#{block_contents}"
        end
      end

      def simplify_field_definition_for_easier_processing(transformable)
        transformable.gsub(/(?<field>(?:field|connection|argument).*?),\n(\s*)(?<next_line>"(.*))/) do
          field = $~[:field].chomp
{'fraction_non_alphanumeric': 0.1352878841398799, 'fraction_numerical': 0.001412928293889085, 'mean_word_length': 2.6185303514376996, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 23, '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': '4901928', 'n_tokens_mistral': 1702, 'n_tokens_neox': 1670, 'n_words': 318}