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