Class: IRB::NestingParser::NestingVisitor
- Defined in:
- lib/irb/nesting_parser.rb
Instance Method Summary collapse
- #close(line, column) ⇒ Object
- #close_closing_loc(node) ⇒ Object
- #close_end_keyword_loc(node) ⇒ Object
- #close_location(location) ⇒ Object
- #close_location_start(location) ⇒ Object
- #heredoc_open(node) ⇒ Object
- #heredoc_string_like(node, type) ⇒ Object
-
#initialize ⇒ NestingVisitor
constructor
A new instance of NestingVisitor.
-
#modifier_node?(node, keyword_loc) ⇒ Boolean
Checks if a node (if, while, etc) is a modifier form that does not need
endclosing. - #nestings ⇒ Object
- #open(line, column, elem) ⇒ Object
- #open_location(location, type, tok) ⇒ Object
- #visit_array_node(node) ⇒ Object
- #visit_begin_node(node) ⇒ Object
- #visit_block_node(node) ⇒ Object
- #visit_block_parameters_node(node) ⇒ Object
- #visit_call_node(node) ⇒ Object
- #visit_case_node(node) ⇒ Object (also: #visit_case_match_node)
- #visit_class_node(node) ⇒ Object (also: #visit_singleton_class_node)
- #visit_def_node(node) ⇒ Object
- #visit_else_node(node) ⇒ Object
- #visit_embedded_statements_node(node) ⇒ Object
- #visit_ensure_node(node) ⇒ Object
- #visit_for_node(node) ⇒ Object
- #visit_hash_node(node) ⇒ Object
- #visit_if_node(node) ⇒ Object
- #visit_in_node(node) ⇒ Object
- #visit_interpolated_string_node(node) ⇒ Object (also: #visit_string_node)
- #visit_interpolated_x_string_node(node) ⇒ Object (also: #visit_x_string_node)
- #visit_lambda_node(node) ⇒ Object
- #visit_module_node(node) ⇒ Object
- #visit_parentheses_node(node) ⇒ Object
- #visit_regular_expression_node(node) ⇒ Object (also: #visit_interpolated_regular_expression_node)
- #visit_rescue_node(node) ⇒ Object
- #visit_super_node(node) ⇒ Object (also: #visit_yield_node, #visit_defined_node)
- #visit_symbol_node(node) ⇒ Object (also: #visit_interpolated_symbol_node)
- #visit_unless_node(node) ⇒ Object
- #visit_until_node(node) ⇒ Object
- #visit_when_node(node) ⇒ Object
- #visit_while_node(node) ⇒ Object
Constructor Details
#initialize ⇒ NestingVisitor
Returns a new instance of NestingVisitor.
10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/irb/nesting_parser.rb', line 10 def initialize # Array of [column, priority(+1/-1), NestingElem(open) or nil(close)] per line. # priority is +1 for open, -1 for close so that close comes before open when sorted. # Example: # if cond # else # end # `else` closes `if` at column 0 first and then opens `else` at column 0 next. @lines = [] # Array of open heredoc NestingElem per line @heredocs = [] end |
Instance Method Details
#close(line, column) ⇒ Object
51 52 53 |
# File 'lib/irb/nesting_parser.rb', line 51 def close(line, column) (@lines[line - 1] ||= []) << [column, -1] end |
#close_closing_loc(node) ⇒ Object
77 78 79 |
# File 'lib/irb/nesting_parser.rb', line 77 def close_closing_loc(node) close_location(node.closing_loc) if node.closing_loc && !node.closing.empty? end |
#close_end_keyword_loc(node) ⇒ Object
73 74 75 |
# File 'lib/irb/nesting_parser.rb', line 73 def close_end_keyword_loc(node) close_location(node.end_keyword_loc) if node.end_keyword == 'end' end |
#close_location(location) ⇒ Object
65 66 67 |
# File 'lib/irb/nesting_parser.rb', line 65 def close_location(location) close(location.end_line, location.end_column) end |
#close_location_start(location) ⇒ Object
69 70 71 |
# File 'lib/irb/nesting_parser.rb', line 69 def close_location_start(location) close(location.start_line, location.start_column) end |
#heredoc_open(node) ⇒ Object
42 43 44 45 |
# File 'lib/irb/nesting_parser.rb', line 42 def heredoc_open(node) elem = NestingElem.new([node.location.start_line, node.location.start_column], :on_heredoc_beg, node.opening) (@heredocs[node.location.start_line - 1] ||= []) << elem end |
#heredoc_string_like(node, type) ⇒ Object
219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/irb/nesting_parser.rb', line 219 def heredoc_string_like(node, type) if node.opening&.start_with?('<<') heredoc_open(node) # Heredoc closing contains trailing newline. We need to exclude it close_location_start(node.closing_loc) if node.closing_loc && !node.closing.empty? elsif node.opening open_location(node.location, type, node.opening) if node.closing && node.closing != '' # Closing of `"#{\n` is "\n". We need to treat it as not-closed. close_location_start(node.closing_loc) if node.opening.match?(/\n\z/) || node.closing != "\n" end end end |
#modifier_node?(node, keyword_loc) ⇒ Boolean
Checks if a node (if, while, etc) is a modifier form that does not need end closing. modifier node: ‘a if b`, non-modifier node: `if a; b; end`
57 58 59 |
# File 'lib/irb/nesting_parser.rb', line 57 def modifier_node?(node, keyword_loc) !(keyword_loc && node.location.start_line == keyword_loc.start_line && node.location.start_column == keyword_loc.start_column) end |
#nestings ⇒ Object
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/irb/nesting_parser.rb', line 24 def nestings size = [@lines.size, @heredocs.size].max nesting = [] size.times.map do |line_index| @lines[line_index]&.sort_by { |col, pri| [col, pri] }&.each do |col, pri, elem| if elem nesting << elem else nesting.pop end end @heredocs[line_index]&.sort_by { |elem| elem.pos[1] }&.reverse_each do |elem| nesting << elem end nesting.dup end end |
#open(line, column, elem) ⇒ Object
47 48 49 |
# File 'lib/irb/nesting_parser.rb', line 47 def open(line, column, elem) (@lines[line - 1] ||= []) << [column, +1, elem] end |
#open_location(location, type, tok) ⇒ Object
61 62 63 |
# File 'lib/irb/nesting_parser.rb', line 61 def open_location(location, type, tok) open(location.start_line, location.start_column, NestingElem.new([location.start_line, location.start_column], type, tok)) end |
#visit_array_node(node) ⇒ Object
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/irb/nesting_parser.rb', line 188 def visit_array_node(node) super type = case node.opening when nil # `x = 1, 2` doesn't have opening nil when '[' :bracket when /\A%W/ :on_words_beg when /\A%w/ :on_qwords_beg when /\A%I/ :on_symbols_beg when /\A%i/ :on_qsymbols_beg end if type open_location(node.location, type, node.opening) close_closing_loc(node) end end |
#visit_begin_node(node) ⇒ Object
174 175 176 177 178 179 180 |
# File 'lib/irb/nesting_parser.rb', line 174 def visit_begin_node(node) super if node.begin_keyword open_location(node.location, :on_kw, 'begin') close_end_keyword_loc(node) end end |
#visit_block_node(node) ⇒ Object
182 183 184 185 186 |
# File 'lib/irb/nesting_parser.rb', line 182 def visit_block_node(node) super open_location(node.location, node.opening == '{' ? :on_lbrace : :on_kw, node.opening) close_closing_loc(node) end |
#visit_block_parameters_node(node) ⇒ Object
290 291 292 293 294 295 296 |
# File 'lib/irb/nesting_parser.rb', line 290 def visit_block_parameters_node(node) super if node.opening == '(' open_location(node.location, :on_lparen, '(') close_closing_loc(node) end end |
#visit_call_node(node) ⇒ Object
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
# File 'lib/irb/nesting_parser.rb', line 274 def visit_call_node(node) super type = case node.opening when '(' :on_lparen when '[' :on_lbracket end if type open_location(node.opening_loc, type, node.opening) close_closing_loc(node) end end |
#visit_case_node(node) ⇒ Object Also known as: visit_case_match_node
127 128 129 130 131 132 133 134 135 |
# File 'lib/irb/nesting_parser.rb', line 127 def visit_case_node(node) super open_location(node.location, :on_kw, 'case') if node.else_clause close_location_start(node.else_clause.location) else close_end_keyword_loc(node) end end |
#visit_class_node(node) ⇒ Object Also known as: visit_singleton_class_node
328 329 330 331 332 |
# File 'lib/irb/nesting_parser.rb', line 328 def visit_class_node(node) super open_location(node.location, :on_kw, 'class') close_end_keyword_loc(node) end |
#visit_def_node(node) ⇒ Object
314 315 316 317 318 319 320 321 322 323 324 325 326 |
# File 'lib/irb/nesting_parser.rb', line 314 def visit_def_node(node) super open_location(node.location, :on_kw, 'def') if node.lparen == '(' open_location(node.lparen_loc, :on_lparen, '(') close_location(node.rparen_loc) if node.rparen == ')' end if node.equal close_location(node.equal_loc) else close_end_keyword_loc(node) end end |
#visit_else_node(node) ⇒ Object
150 151 152 153 154 155 156 |
# File 'lib/irb/nesting_parser.rb', line 150 def visit_else_node(node) super if node.else_keyword == 'else' open_location(node.location, :on_kw, 'else') close_end_keyword_loc(node) end end |
#visit_embedded_statements_node(node) ⇒ Object
233 234 235 236 237 |
# File 'lib/irb/nesting_parser.rb', line 233 def (node) super open_location(node.location, :on_embexpr_beg, '#{') close_closing_loc(node) end |
#visit_ensure_node(node) ⇒ Object
158 159 160 161 162 163 164 |
# File 'lib/irb/nesting_parser.rb', line 158 def visit_ensure_node(node) super return if modifier_node?(node, node.ensure_keyword_loc) close_location_start(node.location) open_location(node.location, :on_kw, 'ensure') end |
#visit_for_node(node) ⇒ Object
81 82 83 84 85 |
# File 'lib/irb/nesting_parser.rb', line 81 def visit_for_node(node) super open_location(node.location, :on_kw, 'for') close_end_keyword_loc(node) end |
#visit_hash_node(node) ⇒ Object
213 214 215 216 217 |
# File 'lib/irb/nesting_parser.rb', line 213 def visit_hash_node(node) super open_location(node.location, :on_lbrace, '{') close_closing_loc(node) end |
#visit_if_node(node) ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/irb/nesting_parser.rb', line 103 def visit_if_node(node) super return if !node.if_keyword || modifier_node?(node, node.if_keyword_loc) open_location(node.location, :on_kw, node.if_keyword) if node.subsequent close_location_start(node.subsequent.location) else close_end_keyword_loc(node) end end |
#visit_in_node(node) ⇒ Object
144 145 146 147 148 |
# File 'lib/irb/nesting_parser.rb', line 144 def visit_in_node(node) super close_location_start(node.location) open_location(node.location, :on_kw, 'in') end |
#visit_interpolated_string_node(node) ⇒ Object Also known as: visit_string_node
239 240 241 242 |
# File 'lib/irb/nesting_parser.rb', line 239 def visit_interpolated_string_node(node) super heredoc_string_like(node, :on_tstring_beg) end |
#visit_interpolated_x_string_node(node) ⇒ Object Also known as: visit_x_string_node
245 246 247 248 |
# File 'lib/irb/nesting_parser.rb', line 245 def visit_interpolated_x_string_node(node) super heredoc_string_like(node, :on_backtick) end |
#visit_lambda_node(node) ⇒ Object
298 299 300 301 302 |
# File 'lib/irb/nesting_parser.rb', line 298 def visit_lambda_node(node) super open_location(node.opening_loc, :on_tlambeg, node.opening) close_closing_loc(node) end |
#visit_module_node(node) ⇒ Object
335 336 337 338 339 |
# File 'lib/irb/nesting_parser.rb', line 335 def visit_module_node(node) super open_location(node.location, :on_kw, 'module') close_end_keyword_loc(node) end |
#visit_parentheses_node(node) ⇒ Object
268 269 270 271 272 |
# File 'lib/irb/nesting_parser.rb', line 268 def visit_parentheses_node(node) super open_location(node.location, :on_lparen, '(') close_closing_loc(node) end |
#visit_regular_expression_node(node) ⇒ Object Also known as: visit_interpolated_regular_expression_node
261 262 263 264 265 |
# File 'lib/irb/nesting_parser.rb', line 261 def visit_regular_expression_node(node) super open_location(node.location, :on_regexp_beg, node.opening) close_closing_loc(node) end |
#visit_rescue_node(node) ⇒ Object
166 167 168 169 170 171 172 |
# File 'lib/irb/nesting_parser.rb', line 166 def visit_rescue_node(node) super return if modifier_node?(node, node.keyword_loc) close_location_start(node.location) open_location(node.location, :on_kw, 'rescue') end |
#visit_super_node(node) ⇒ Object Also known as: visit_yield_node, visit_defined_node
304 305 306 307 308 309 310 |
# File 'lib/irb/nesting_parser.rb', line 304 def visit_super_node(node) super if node.lparen open_location(node.lparen_loc, :on_lparen, '(') close_location(node.rparen_loc) if node.rparen == ')' end end |
#visit_symbol_node(node) ⇒ Object Also known as: visit_interpolated_symbol_node
251 252 253 254 255 256 257 258 |
# File 'lib/irb/nesting_parser.rb', line 251 def visit_symbol_node(node) super unless node.opening.nil? || node.opening.empty? || node.opening == ':' # :"sym" or %s[sym] open_location(node.location, :on_symbeg, node.opening) close_closing_loc(node) end end |
#visit_unless_node(node) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/irb/nesting_parser.rb', line 115 def visit_unless_node(node) super return if modifier_node?(node, node.keyword_loc) open_location(node.location, :on_kw, 'unless') if node.else_clause close_location_start(node.else_clause.location) else close_end_keyword_loc(node) end end |
#visit_until_node(node) ⇒ Object
95 96 97 98 99 100 101 |
# File 'lib/irb/nesting_parser.rb', line 95 def visit_until_node(node) super return if modifier_node?(node, node.keyword_loc) open_location(node.location, :on_kw, 'until') close_closing_loc(node) end |
#visit_when_node(node) ⇒ Object
138 139 140 141 142 |
# File 'lib/irb/nesting_parser.rb', line 138 def visit_when_node(node) super close_location_start(node.location) open_location(node.location, :on_kw, 'when') end |
#visit_while_node(node) ⇒ Object
87 88 89 90 91 92 93 |
# File 'lib/irb/nesting_parser.rb', line 87 def visit_while_node(node) super return if modifier_node?(node, node.keyword_loc) open_location(node.location, :on_kw, 'while') close_closing_loc(node) end |