class GraphQL::Upgrader::ResolveProcToMethodTransform

def apply(input_text)

def apply(input_text)
  if input_text =~ /resolve\(? ?->/
    # - Find the proc literal
    # - Get the three argument names (obj, arg, ctx)
    # - Get the proc body
    # - Find and replace:
    #  - The ctx argument becomes `context`
    #  - The obj argument becomes `object`
    # - Args is trickier:
    #   - If it's not used, remove it
    #   - If it's used, abandon ship and make it `**args`
    #   - Convert string args access to symbol access, since it's a Ruby **splat
    #   - Convert camelized arg names to underscored arg names
    #   - (It would be nice to correctly become Ruby kwargs, but that might be too hard)
    #   - Add a `# TODO` comment to the method source?
    # - Rebuild the method:
    #   - use the field name as the method name
    #   - handle args as described above
    #   - put the modified proc body as the method body
    input_text.match(/(?<field_type>input_field|field|connection|argument) :(?<name>[a-zA-Z_0-9_]*)/)
    field_name = $~[:name]
    processor = apply_processor(input_text, ResolveProcProcessor.new)
    processor.resolve_proc_sections.reverse.each do |resolve_proc_section|
      proc_body = input_text[resolve_proc_section.proc_start..resolve_proc_section.proc_end]
      obj_arg_name, args_arg_name, ctx_arg_name = resolve_proc_section.proc_arg_names
      # This is not good, it will hit false positives
      # Should use AST to make this substitution
      if obj_arg_name != "_"
        proc_body.gsub!(/([^\w:.]|^)#{obj_arg_name}([^\w:]|$)/, '\1object\2')
      end
      if ctx_arg_name != "_"
        proc_body.gsub!(/([^\w:.]|^)#{ctx_arg_name}([^\w:]|$)/, '\1context\2')
      end
      method_def_indent = " " * (resolve_proc_section.resolve_indent - 2)
      # Turn the proc body into a method body
      method_body = reindent_lines(proc_body, from_indent: resolve_proc_section.resolve_indent + 2, to_indent: resolve_proc_section.resolve_indent)
      # Add `def... end`
      method_def = if input_text.include?("argument ")
        # This field has arguments
        "def #{field_name}(**#{args_arg_name})"
      else
        # No field arguments, so, no method arguments
        "def #{field_name}"
      end
      # Wrap the body in def ... end
      method_body = "\n#{method_def_indent}#{method_def}\n#{method_body}\n#{method_def_indent}end\n"
      # Update Argument access to be underscore and symbols
      # Update `args[...]` and `args.key?`
      method_body = method_body.gsub(/#{args_arg_name}(?<method_begin>\.key\?\(?|\[)["':](?<arg_name>[a-zA-Z0-9_]+)["']?(?<method_end>\]|\))?/) do
        method_begin = $~[:method_begin]
        arg_name = underscorize($~[:arg_name])
        method_end = $~[:method_end]
        "#{args_arg_name}#{method_begin}:#{arg_name}#{method_end}"
      end
      # Replace the resolve proc with the method
      input_text[resolve_proc_section.resolve_start..resolve_proc_section.resolve_end] = ""
      # The replacement above might have left some preceeding whitespace,
      # so remove it by deleting all whitespace chars before `resolve`:
      preceeding_whitespace = resolve_proc_section.resolve_start - 1
      while input_text[preceeding_whitespace] == " " && preceeding_whitespace > 0
        input_text[preceeding_whitespace] = ""
        preceeding_whitespace -= 1
      end
      input_text += method_body
      input_text
    end
  end
  input_text
end