Method: Lazydoc::Utils.scan_args

Defined in:
lib/lazydoc/utils.rb

.scan_args(str) ⇒ Object

Parses an argument string (anything following the method name in a standard method definition, including parenthesis, comments, default values, etc) into an array of strings.

Utils.parse_args("(a, b='default', *c, &block)")  
# => ["a", "b='default'", "*c", "&block"]

Note the %-syntax for strings and arrays is not fully supported, ie %w, %Q, %q, etc. may not parse correctly. The same is true for multiline argument strings.

Accepts a String or a StringScanner.



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/lazydoc/utils.rb', line 78

def scan_args(str)
  scanner = convert_to_scanner(str)
  str = scanner.string
  
  # skip whitespace and leading LPAREN
  scanner.skip(/\s*\(?\s*/) 
  
  args = []
  brakets = braces = parens = 0
  start = scanner.pos
  broke = false
  while scanner.skip(/.*?['"#,\(\)\{\}\[\]]/)
    pos = scanner.pos - 1
    
    case str[pos]
    when ?,,nil
      # skip if in brakets, braces, or parenthesis
      next if parens > 0 || brakets > 0 || braces > 0
      
      # ok, found an arg
      args << str[start, pos-start].strip
      start = pos + 1
    
    when ?# then broke = true; break        # break on a comment
    when ?' then skip_quote(scanner, /'/)   # parse over quoted strings
    when ?" then skip_quote(scanner, /"/)   # parse over double-quoted string
      
    when ?( then parens += 1                # for brakets, braces, and parenthesis
    when ?)                                 # simply track the nesting EXCEPT for
      if parens == 0                        # RPAREN.  If the closing parenthesis
        broke = true; break
      end
      parens -= 1                           # is found, break.
    when ?[ then braces += 1
    when ?] then braces -= 1
    when ?{ then brakets += 1
    when ?} then brakets -= 1
    end
  end
  
  # parse out the final arg.  if the loop broke (ie 
  # a comment or the closing parenthesis was found) 
  # then the end position is determined by the 
  # scanner, otherwise take all that remains
  pos = broke ? scanner.pos-1 : str.length
  args << str[start, pos-start].strip unless pos == start

  args
end