Class: GraphQL::Upgrader::ResolveProcToMethodTransform
- Defined in:
- lib/graphql/upgrader/member.rb
Defined Under Namespace
Classes: ResolveProcProcessor
Instance Method Summary collapse
Methods inherited from Transform
#apply_processor, #normalize_type_expression, #reindent_lines, #trim_lines, #underscorize
Instance Method Details
#apply(input_text) ⇒ Object
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 |
# File 'lib/graphql/upgrader/member.rb', line 513 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 |