Skip to content

Commit 957fd79

Browse files
authored
Suppress error highlight for some incomplete code (#1173)
It is better to not render `class` with RED-REVERSE color. Filter specific errors if error location is at the last non-newline non-comment token position.
1 parent d842f3d commit 957fd79

2 files changed

Lines changed: 49 additions & 2 deletions

File tree

lib/irb/color.rb

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,13 @@ def colorize_code(code, complete: true, ignore_error: false, colorable: colorabl
168168
# IRB::ColorPrinter skips colorizing syntax invalid fragments
169169
return Reline::Unicode.escape_for_print(code) if ignore_error && !result.success?
170170

171+
prism_node, prism_tokens = result.value
171172
errors = result.errors
173+
172174
unless complete
173-
errors = errors.reject { |error| error.message =~ /\Aexpected a|unexpected end-of-input|unterminated/ }
175+
errors = filter_incomplete_code_errors(errors, prism_tokens)
174176
end
175177

176-
prism_node, prism_tokens = result.value
177178
visitor = ColorizeVisitor.new
178179
prism_node.accept(visitor)
179180

@@ -282,6 +283,29 @@ def visit_symbol_node(node)
282283

283284
private
284285

286+
FILTERED_ERROR_TYPES = [
287+
:class_name, :module_name, # `class`, `class owner_module`
288+
:write_target_unexpected, # `a, b`
289+
:parameter_wild_loose_comma, # `def f(a,`
290+
:argument_no_forwarding_star, # `[*`
291+
:argument_no_forwarding_star_star, # `f(**`
292+
:argument_no_forwarding_ampersand, # `f(&`
293+
:def_endless, # `def f =`
294+
:embdoc_term, # `=begin`
295+
]
296+
297+
# Filter out syntax errors that are likely to be caused by incomplete code, to avoid showing misleading error highlights to users.
298+
def filter_incomplete_code_errors(errors, tokens)
299+
last_non_comment_space_token, = tokens.reverse_each.find do |t,|
300+
t.type != :COMMENT && t.type != :EOF && t.type != :IGNORED_NEWLINE && t.type != :NEWLINE
301+
end
302+
last_offset = last_non_comment_space_token ? last_non_comment_space_token.location.end_offset : 0
303+
errors.reject do |error|
304+
error.message.match?(/\Aexpected a|unexpected end-of-input|unterminated/) ||
305+
(error.location.end_offset == last_offset && FILTERED_ERROR_TYPES.include?(error.type))
306+
end
307+
end
308+
285309
def without_circular_ref(obj, seen:, &block)
286310
return false if seen.key?(obj)
287311
seen[obj] = true

test/irb/test_color.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,29 @@ def test_colorize_code_complete_false
168168
{
169169
"'foo' + 'bar" => "#{RED}#{BOLD}'#{CLEAR}#{RED}foo#{CLEAR}#{RED}#{BOLD}'#{CLEAR} + #{RED}#{BOLD}'#{CLEAR}#{RED}bar#{CLEAR}",
170170
"('foo" => "(#{RED}#{BOLD}'#{CLEAR}#{RED}foo#{CLEAR}",
171+
"if true" => "#{GREEN}if#{CLEAR} #{CYAN}#{BOLD}true#{CLEAR}",
172+
"tap do end end tap do" => "tap #{GREEN}do#{CLEAR} #{GREEN}end#{CLEAR} #{RED}#{REVERSE}end#{CLEAR} tap #{GREEN}do#{CLEAR}",
173+
174+
# Specially handled cases
175+
"class" => "#{GREEN}class#{CLEAR}",
176+
"class#" => "#{GREEN}class#{CLEAR}#{BLUE}#{BOLD}\##{CLEAR}",
177+
"class;" => "#{RED}#{REVERSE}class#{CLEAR};",
178+
"module" => "#{GREEN}module#{CLEAR}",
179+
"module#" => "#{GREEN}module#{CLEAR}#{BLUE}#{BOLD}\##{CLEAR}",
180+
"module;" => "#{RED}#{REVERSE}module#{CLEAR};",
181+
"class owner_module" => "#{GREEN}class#{CLEAR} owner_module",
182+
"module owner_module" => "#{GREEN}module#{CLEAR} owner_module",
183+
"a, b" => "a, b",
184+
"a, b#" => "a, b#{BLUE}#{BOLD}\##{CLEAR}",
185+
"a, b;" => "#{RED}#{REVERSE}a, b#{CLEAR};",
186+
"def f(a,#" => "#{GREEN}def#{CLEAR} #{BLUE}#{BOLD}f#{CLEAR}(a,#{BLUE}#{BOLD}\##{CLEAR}",
187+
"def f(a,)" => "#{GREEN}def#{CLEAR} #{BLUE}#{BOLD}f#{CLEAR}(a#{RED}#{REVERSE},#{CLEAR})",
188+
"[*" => "[*",
189+
"f(*" => "f(*",
190+
"f(**" => "f(**",
191+
"f(&" => "f(&",
192+
"def f =" => "#{GREEN}def#{CLEAR} #{BLUE}#{BOLD}f#{CLEAR} =",
193+
"=begin" => "#{BLUE}#{BOLD}=begin#{CLEAR}",
171194
}.each do |code, result|
172195
assert_equal_with_term(result, code, complete: false)
173196

0 commit comments

Comments
 (0)