@@ -275,12 +275,12 @@ def retrieve_completion_data(input, bind:, doc_namespace:)
275275 nil
276276 else
277277 sym = $1
278- candidates = Symbol . all_symbols . collect do |s |
278+ candidates = Symbol . all_symbols . filter_map do |s |
279279 s . inspect
280280 rescue EncodingError
281281 # ignore
282282 end
283- candidates . grep ( /^#{ Regexp . quote ( sym ) } / )
283+ safe_grep ( candidates , /^#{ Regexp . quote ( sym ) } / )
284284 end
285285 when /^::([A-Z][^:\. \( \) ]*)$/
286286 # Absolute Constant or class methods
@@ -291,7 +291,7 @@ def retrieve_completion_data(input, bind:, doc_namespace:)
291291 if doc_namespace
292292 candidates . find { |i | i == receiver }
293293 else
294- candidates . grep ( /^#{ Regexp . quote ( receiver ) } / ) . collect { |e | "::" + e }
294+ safe_grep ( candidates , /^#{ Regexp . quote ( receiver ) } / ) . collect { |e | "::" + e }
295295 end
296296
297297 when /^([A-Z].*)::([^:.]*)$/
@@ -378,7 +378,7 @@ def retrieve_completion_data(input, bind:, doc_namespace:)
378378 if doc_namespace
379379 all_gvars . find { |i | i == gvar }
380380 else
381- all_gvars . grep ( Regexp . new ( Regexp . quote ( gvar ) ) )
381+ safe_grep ( all_gvars , Regexp . new ( Regexp . quote ( gvar ) ) )
382382 end
383383
384384 when /^([^.:"].*)(\. |::)([^.]*)$/
@@ -453,16 +453,27 @@ def retrieve_completion_data(input, bind:, doc_namespace:)
453453 else
454454 candidates = ( bind . eval_methods | bind . eval_private_methods | bind . local_variables | bind . eval_instance_variables | bind . eval_class_constants ) . collect { |m | m . to_s }
455455 candidates |= RubyLex ::RESERVED_WORDS . map ( &:to_s )
456- candidates . grep ( /^#{ Regexp . quote ( input ) } / ) . sort
456+ safe_grep ( candidates , /^#{ Regexp . quote ( input ) } / ) . sort
457457 end
458458 end
459459 end
460460
461461 # Set of available operators in Ruby
462462 Operators = %w[ % & * ** + - / < << <= <=> == === =~ > >= >> [] []= ^ ! != !~ ]
463463
464+ def safe_grep ( candidates , pattern )
465+ target_encoding = Encoding . default_external
466+ candidates . filter_map do |candidate |
467+ converted = candidate . encoding == target_encoding ? candidate : candidate . encode ( target_encoding )
468+ converted if pattern . match? ( converted )
469+ rescue EncodingError
470+ # Skip candidates that have encoding issues
471+ nil
472+ end
473+ end
474+
464475 def select_message ( receiver , message , candidates , sep = "." )
465- candidates . grep ( /^#{ Regexp . quote ( message ) } / ) . collect do |e |
476+ safe_grep ( candidates , /^#{ Regexp . quote ( message ) } / ) . collect do |e |
466477 case e
467478 when /^[a-zA-Z_]/
468479 receiver + sep + e
0 commit comments