From abf8a0f6fa9c880597f095a7b005089c3244f38a Mon Sep 17 00:00:00 2001 From: Serj Prikhodko Date: Thu, 18 Jan 2024 16:06:25 +0100 Subject: [PATCH 1/6] Add a test-case for `Symbol#inspect` --- spec/unit/unparser_spec.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spec/unit/unparser_spec.rb b/spec/unit/unparser_spec.rb index c979d1a9..05e147f3 100644 --- a/spec/unit/unparser_spec.rb +++ b/spec/unit/unparser_spec.rb @@ -390,6 +390,9 @@ def noop "false" end RUBY + + # Test Symbol#inspect Ruby bug: https://bugs.ruby-lang.org/issues/18905 + assert_source(':"8 >="') end describe 'corpus' do From 73d94bd2140be3306f7a555ab7b53e8316649cb2 Mon Sep 17 00:00:00 2001 From: Serj Prikhodko Date: Thu, 18 Jan 2024 16:31:38 +0100 Subject: [PATCH 2/6] Handle `Symbol#inspect` for Ruby `<3.2.0` --- lib/unparser/emitter/primitive.rb | 6 +++++- spec/unit/unparser_spec.rb | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/unparser/emitter/primitive.rb b/lib/unparser/emitter/primitive.rb index e173704d..d04eec48 100644 --- a/lib/unparser/emitter/primitive.rb +++ b/lib/unparser/emitter/primitive.rb @@ -15,7 +15,11 @@ class Inspect < self private def dispatch - write(value.inspect) + if RUBY_VERSION < '3.2' && node.type == :sym && value[-1] == '=' + write(":#{value.name.inspect}") + else + write(value.inspect) + end end end # Inspect diff --git a/spec/unit/unparser_spec.rb b/spec/unit/unparser_spec.rb index 05e147f3..43d6867a 100644 --- a/spec/unit/unparser_spec.rb +++ b/spec/unit/unparser_spec.rb @@ -392,6 +392,8 @@ def noop RUBY # Test Symbol#inspect Ruby bug: https://bugs.ruby-lang.org/issues/18905 + assert_source(':"@="') + assert_source(':"$$$$="') assert_source(':"8 >="') end From 4a0ac3e2e482c41a635daf2284c6eb81e277896f Mon Sep 17 00:00:00 2001 From: Serj Prikhodko Date: Thu, 18 Jan 2024 16:33:00 +0100 Subject: [PATCH 3/6] Extract dedicated `Symbol` emitter --- lib/unparser/emitter/primitive.rb | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/unparser/emitter/primitive.rb b/lib/unparser/emitter/primitive.rb index d04eec48..f26a9243 100644 --- a/lib/unparser/emitter/primitive.rb +++ b/lib/unparser/emitter/primitive.rb @@ -10,19 +10,31 @@ class Primitive < self # Emitter for primitives based on Object#inspect class Inspect < self - handle :sym, :str + handle :str private def dispatch - if RUBY_VERSION < '3.2' && node.type == :sym && value[-1] == '=' + write(value.inspect) + end + + end # Inspect + + class Symbol < self + + handle :sym + + private + + def dispatch + if RUBY_VERSION < '3.2' && value[-1] == '=' write(":#{value.name.inspect}") else write(value.inspect) end end - end # Inspect + end # Symbol # Emitter for complex literals class Complex < self From c90147dcda082540bcd248fdd69b2f719017b5eb Mon Sep 17 00:00:00 2001 From: Serj Prikhodko Date: Thu, 18 Jan 2024 17:23:56 +0100 Subject: [PATCH 4/6] Disable mutant on `Symbol#dispatch` as it depends on Ruby version and would fail on CI. --- lib/unparser/emitter/primitive.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/unparser/emitter/primitive.rb b/lib/unparser/emitter/primitive.rb index f26a9243..8c75c77b 100644 --- a/lib/unparser/emitter/primitive.rb +++ b/lib/unparser/emitter/primitive.rb @@ -26,6 +26,7 @@ class Symbol < self private + # mutant:disable def dispatch if RUBY_VERSION < '3.2' && value[-1] == '=' write(":#{value.name.inspect}") From d8c0b59297f0319a9469a287c2e36b8bd04c0496 Mon Sep 17 00:00:00 2001 From: Serj Prikhodko Date: Thu, 18 Jan 2024 20:13:32 +0100 Subject: [PATCH 5/6] Improve symbol detection logic --- lib/unparser/emitter/primitive.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/unparser/emitter/primitive.rb b/lib/unparser/emitter/primitive.rb index 8c75c77b..57f42ec8 100644 --- a/lib/unparser/emitter/primitive.rb +++ b/lib/unparser/emitter/primitive.rb @@ -28,7 +28,7 @@ class Symbol < self # mutant:disable def dispatch - if RUBY_VERSION < '3.2' && value[-1] == '=' + if RUBY_VERSION < '3.2' && value.match?(/=\z/) write(":#{value.name.inspect}") else write(value.inspect) From 03c572231c8b69c82d00e2e6315a0f695bb6e79b Mon Sep 17 00:00:00 2001 From: Serj Prikhodko Date: Tue, 23 Jan 2024 10:23:46 +0100 Subject: [PATCH 6/6] Replace `regexp` check with `parse` --- lib/unparser/emitter/primitive.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/unparser/emitter/primitive.rb b/lib/unparser/emitter/primitive.rb index 57f42ec8..ec17b16b 100644 --- a/lib/unparser/emitter/primitive.rb +++ b/lib/unparser/emitter/primitive.rb @@ -28,13 +28,22 @@ class Symbol < self # mutant:disable def dispatch - if RUBY_VERSION < '3.2' && value.match?(/=\z/) + if inspect_breaks_parsing? write(":#{value.name.inspect}") else write(value.inspect) end end + # mutant:disable + def inspect_breaks_parsing? + return false unless RUBY_VERSION < '3.2.' + + Unparser.parse(value.inspect) + false + rescue Parser::SyntaxError + true + end end # Symbol # Emitter for complex literals