Class: Claret::Rewriters::MethodDefRewriter

Inherits:
RubyNext::Language::Rewriters::Text
  • Object
show all
Includes:
Utils::Logging
Defined in:
lib/claret/rewriters/1_method_def_rewriter.rb

Constant Summary collapse

NAME =
"claret-positional-arg-type"
SYNTAX_PROBE =
"def foo(String a, (Integer | String) b, customType c, ivarType @ivar)"
MIN_SUPPORTED_VERSION =
Gem::Version.new(RubyNext::NEXT_VERSION)

Instance Method Summary collapse

Methods included from Utils::Logging

#debug, #logger, #say

Instance Method Details

#safe_rewrite(source) ⇒ Object

[View source]

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/claret/rewriters/1_method_def_rewriter.rb', line 15

def safe_rewrite(source)
  modified_source = source.dup

  source.scan(/(def\s+[\w_]+)(.*)$/).each do |method_def_match|
    debug "> Method def match: #{method_def_match.inspect}"
    matched_def = method_def_match.join
    scanner = StringScanner.new matched_def
    stack = Claret::Parsing::Parens.new(scanner).parse

    # TODO: we still need to handle return values
    if stack.size < 2
      add_sig_comment(modified_source, method_def_match, [])
      next
    end

    debug "> Parsed arguments:"
    debug stack.inspect

    types = stack.last.map do |arg_def|
      debug "> Arg def: #{arg_def}"

      to_replace, type, arg = if arg_def.is_a?(String) && arg_def.match?(/[\w_]+\s+[\w_@=]+\s*/)
        optional = arg_def.include?("=")
        arg_def = arg_def.split("=").first
        debug "> Arg def simple: #{arg_def}"

        type, arg = arg_def.squeeze(" ").strip.split(" ")
        type_for_sig = optional ? "?(#{type})" : type
        [arg_def, type_for_sig, arg]
      elsif arg_def.is_a?(Array)
        # TODO: handle nested parens in type
        type = arg_def.first.first
        arg = arg_def[1]
        optional = arg.include?("=")
        type_for_sig = optional ? "?(#{type})" : type
        [/\(\s*#{Regexp.escape(type)}\s*\)\s*#{Regexp.escape(arg)}/, type_for_sig, arg]
      else
        raise "Unexpected arg def: #{arg_def}"
      end

      debug "> Replace: #{to_replace} -- (Type: #{type}, Arg: #{arg})"

      modified_source.gsub!(to_replace, arg)
      type
    end

    # Mark file dirty
    context.track! self

    # TODO: handle return type
    add_sig_comment(modified_source, method_def_match, types)
  end

  modified_source
end