Skip to content

Commit 00603d4

Browse files
authored
Allow assigning and using local variable name conflicting with command (#961)
1 parent c844176 commit 00603d4

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

lib/irb.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,8 @@ def build_statement(code)
11381138
end
11391139
end
11401140

1141+
ASSIGN_OPERATORS_REGEXP = Regexp.union(%w[= += -= *= /= %= **= &= |= &&= ||= ^= <<= >>=])
1142+
11411143
def parse_command(code)
11421144
command_name, arg = code.strip.split(/\s+/, 2)
11431145
return unless code.lines.size == 1 && command_name
@@ -1149,6 +1151,12 @@ def parse_command(code)
11491151
return [alias_name, arg]
11501152
end
11511153

1154+
# Assignment-like expression is not a command
1155+
return if arg.start_with?(ASSIGN_OPERATORS_REGEXP) && !arg.start_with?(/==|=~/)
1156+
1157+
# Local variable have precedence over command
1158+
return if @context.local_variables.include?(command)
1159+
11521160
# Check visibility
11531161
public_method = !!Kernel.instance_method(:public_method).bind_call(@context.main, command) rescue false
11541162
private_method = !public_method && !!Kernel.instance_method(:method).bind_call(@context.main, command) rescue false

test/irb/command/test_custom_command.rb

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,5 +145,50 @@ def execute(*)
145145
assert_include(output, "No description provided.")
146146
assert_not_include(output, "Maybe IRB bug")
147147
end
148+
149+
def test_command_name_local_variable
150+
write_ruby <<~RUBY
151+
require "irb/command"
152+
153+
class FooBarCommand < IRB::Command::Base
154+
category 'CommandTest'
155+
description 'test'
156+
def execute(arg)
157+
puts "arg=\#{arg.inspect}"
158+
end
159+
end
160+
161+
IRB::Command.register(:foo_bar, FooBarCommand)
162+
163+
binding.irb
164+
RUBY
165+
166+
output = run_ruby_file do
167+
type "binding.irb"
168+
type "foo_bar == 1 || 1"
169+
type "foo_bar =~ /2/ || 2"
170+
type "exit"
171+
type "binding.irb"
172+
type "foo_bar = '3'; foo_bar"
173+
type "foo_bar == 4 || '4'"
174+
type "foo_bar =~ /5/ || '5'"
175+
type "exit"
176+
type "binding.irb"
177+
type "foo_bar ||= '6'; foo_bar"
178+
type "foo_bar == 7 || '7'"
179+
type "foo_bar =~ /8/ || '8'"
180+
type "exit"
181+
type "exit"
182+
end
183+
184+
assert_include(output, 'arg="== 1 || 1"')
185+
assert_include(output, 'arg="=~ /2/ || 2"')
186+
assert_include(output, '=> "3"')
187+
assert_include(output, '=> "4"')
188+
assert_include(output, '=> "5"')
189+
assert_include(output, '=> "6"')
190+
assert_include(output, '=> "7"')
191+
assert_include(output, '=> "8"')
192+
end
148193
end
149194
end

0 commit comments

Comments
 (0)