@@ -280,7 +280,7 @@ def retrieve_completion_data(input, bind:, doc_namespace:)
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,28 @@ 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+
469+ converted if pattern . match? ( converted )
470+ rescue Encoding ::UndefinedConversionError , Encoding ::InvalidByteSequenceError , Encoding ::CompatibilityError , EncodingError
471+ # Skip candidates that cannot be converted to the target encoding
472+ nil
473+ end
474+ end
475+
464476 def select_message ( receiver , message , candidates , sep = "." )
465- candidates . grep ( /^#{ Regexp . quote ( message ) } / ) . collect do |e |
477+ safe_grep ( candidates , /^#{ Regexp . quote ( message ) } / ) . collect do |e |
466478 case e
467479 when /^[a-zA-Z_]/
468480 receiver + sep + e
0 commit comments