Skip to content

Commit

Permalink
Allow assigning and using local variable name conflicting with command (
Browse files Browse the repository at this point in the history
  • Loading branch information
tompng authored Jun 30, 2024
1 parent c844176 commit 00603d4
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 0 deletions.
8 changes: 8 additions & 0 deletions lib/irb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,8 @@ def build_statement(code)
end
end

ASSIGN_OPERATORS_REGEXP = Regexp.union(%w[= += -= *= /= %= **= &= |= &&= ||= ^= <<= >>=])

def parse_command(code)
command_name, arg = code.strip.split(/\s+/, 2)
return unless code.lines.size == 1 && command_name
Expand All @@ -1149,6 +1151,12 @@ def parse_command(code)
return [alias_name, arg]
end

# Assignment-like expression is not a command
return if arg.start_with?(ASSIGN_OPERATORS_REGEXP) && !arg.start_with?(/==|=~/)

# Local variable have precedence over command
return if @context.local_variables.include?(command)

# Check visibility
public_method = !!Kernel.instance_method(:public_method).bind_call(@context.main, command) rescue false
private_method = !public_method && !!Kernel.instance_method(:method).bind_call(@context.main, command) rescue false
Expand Down
45 changes: 45 additions & 0 deletions test/irb/command/test_custom_command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -145,5 +145,50 @@ def execute(*)
assert_include(output, "No description provided.")
assert_not_include(output, "Maybe IRB bug")
end

def test_command_name_local_variable
write_ruby <<~RUBY
require "irb/command"
class FooBarCommand < IRB::Command::Base
category 'CommandTest'
description 'test'
def execute(arg)
puts "arg=\#{arg.inspect}"
end
end
IRB::Command.register(:foo_bar, FooBarCommand)
binding.irb
RUBY

output = run_ruby_file do
type "binding.irb"
type "foo_bar == 1 || 1"
type "foo_bar =~ /2/ || 2"
type "exit"
type "binding.irb"
type "foo_bar = '3'; foo_bar"
type "foo_bar == 4 || '4'"
type "foo_bar =~ /5/ || '5'"
type "exit"
type "binding.irb"
type "foo_bar ||= '6'; foo_bar"
type "foo_bar == 7 || '7'"
type "foo_bar =~ /8/ || '8'"
type "exit"
type "exit"
end

assert_include(output, 'arg="== 1 || 1"')
assert_include(output, 'arg="=~ /2/ || 2"')
assert_include(output, '=> "3"')
assert_include(output, '=> "4"')
assert_include(output, '=> "5"')
assert_include(output, '=> "6"')
assert_include(output, '=> "7"')
assert_include(output, '=> "8"')
end
end
end

0 comments on commit 00603d4

Please sign in to comment.