mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
b77ac183d8
The spec was failing because on 2.7 hash directly return nil without hashing the key if they are empty: ```ruby m = Module.new do def self.hash; end end h = {} h[m] # => nil h[1] = 2 h[m] # => ArgumentError ``` So we need to require IRB so that the to_ignore set isn't empty
253 lines
5.8 KiB
Ruby
253 lines
5.8 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "readline" unless defined?(Readline)
|
|
require "pry/input_completer"
|
|
|
|
def completer_test(bind, pry = nil, assert_flag = true)
|
|
test = proc do |symbol|
|
|
input = pry || Readline
|
|
input_completer = Pry::InputCompleter.new(input, pry)
|
|
completions = input_completer.call(symbol[0..-2], target: Pry.binding_for(bind))
|
|
expect(completions.include?(symbol)).to eq(assert_flag)
|
|
end
|
|
proc { |*symbols| symbols.each(&test) }
|
|
end
|
|
|
|
describe Pry::InputCompleter do
|
|
before do
|
|
# The AMQP gem has some classes like this:
|
|
# pry(main)> AMQP::Protocol::Test::ContentOk.name
|
|
# => :content_ok
|
|
module SymbolyName
|
|
def self.name
|
|
:symboly_name
|
|
end
|
|
end
|
|
|
|
@before_completer = Pry.config.completer
|
|
Pry.config.completer = Pry::InputCompleter
|
|
end
|
|
|
|
after do
|
|
Pry.config.completer = @before_completer
|
|
Object.remove_const :SymbolyName
|
|
end
|
|
|
|
it "should not crash if there's a Module that has a symbolic name." do
|
|
skip unless Pry::Helpers::Platform.jruby?
|
|
expect do
|
|
Pry::InputCompleter.new(Readline).call(
|
|
"a.to_s.", target: Pry.binding_for(Object.new)
|
|
)
|
|
end.not_to raise_error
|
|
end
|
|
|
|
it 'should take parenthesis and other characters into account for symbols' do
|
|
expect do
|
|
Pry::InputCompleter.new(Readline).call(
|
|
":class)", target: Pry.binding_for(Object.new)
|
|
)
|
|
end.not_to raise_error
|
|
end
|
|
|
|
it 'should complete instance variables' do
|
|
object = Class.new.new
|
|
|
|
# set variables in appropriate scope
|
|
object.instance_variable_set(:'@name', 'Pry')
|
|
object.class.send(:class_variable_set, :'@@number', 10)
|
|
|
|
# check to see if variables are in scope
|
|
expect(object.instance_variables
|
|
.map(&:to_sym)
|
|
.include?(:'@name')).to eq true
|
|
|
|
expect(object.class.class_variables
|
|
.map(&:to_sym)
|
|
.include?(:'@@number')).to eq true
|
|
|
|
# Complete instance variables.
|
|
b = Pry.binding_for(object)
|
|
completer_test(b).call('@name', '@name.downcase')
|
|
|
|
# Complete class variables.
|
|
b = Pry.binding_for(object.class)
|
|
completer_test(b).call('@@number', '@@number.class')
|
|
end
|
|
|
|
it 'should complete for stdlib symbols' do
|
|
o = Object.new
|
|
# Regexp
|
|
completer_test(o).call('/foo/.extend')
|
|
|
|
# Array
|
|
completer_test(o).call('[1].push')
|
|
|
|
# Hash
|
|
completer_test(o).call('{"a" => "b"}.keys')
|
|
|
|
# Proc
|
|
completer_test(o).call('{2}.call')
|
|
|
|
# Symbol
|
|
completer_test(o).call(':symbol.to_s')
|
|
|
|
# Absolute Constant
|
|
completer_test(o).call('::IndexError')
|
|
end
|
|
|
|
it 'should complete for target symbols' do
|
|
o = Object.new
|
|
|
|
# Constant
|
|
module Mod
|
|
remove_const :CON if defined? CON
|
|
CON = 'Constant'.freeze
|
|
module Mod2
|
|
end
|
|
end
|
|
|
|
completer_test(Mod).call('CON')
|
|
|
|
# Constants or Class Methods
|
|
completer_test(o).call('Mod::CON')
|
|
|
|
# Symbol
|
|
_foo = :symbol
|
|
completer_test(o).call(':symbol')
|
|
|
|
# Variables
|
|
class << o
|
|
attr_accessor :foo
|
|
end
|
|
o.foo = 'bar'
|
|
completer_test(binding).call('o.foo')
|
|
|
|
# trailing slash
|
|
expect(Pry::InputCompleter.new(Readline).call('Mod2/', target: Pry.binding_for(Mod))
|
|
.include?('Mod2/')).to eq(true)
|
|
end
|
|
|
|
it 'should complete for arbitrary scopes' do
|
|
module Bar
|
|
@barvar = :bar
|
|
end
|
|
|
|
module Baz
|
|
remove_const :CON if defined? CON
|
|
@bar = Bar
|
|
@bazvar = :baz
|
|
CON = :constant
|
|
end
|
|
|
|
pry = Pry.new(target: Baz)
|
|
pry.push_binding(Bar)
|
|
|
|
b = Pry.binding_for(Bar)
|
|
completer_test(b, pry).call("../@bazvar")
|
|
completer_test(b, pry).call('/CON')
|
|
end
|
|
|
|
it 'should complete for stdlib symbols' do
|
|
o = Object.new
|
|
# Regexp
|
|
completer_test(o).call('/foo/.extend')
|
|
|
|
# Array
|
|
completer_test(o).call('[1].push')
|
|
|
|
# Hash
|
|
completer_test(o).call('{"a" => "b"}.keys')
|
|
|
|
# Proc
|
|
completer_test(o).call('{2}.call')
|
|
|
|
# Symbol
|
|
completer_test(o).call(':symbol.to_s')
|
|
|
|
# Absolute Constant
|
|
completer_test(o).call('::IndexError')
|
|
end
|
|
|
|
it 'should complete for target symbols' do
|
|
o = Object.new
|
|
|
|
# Constant
|
|
module Mod
|
|
remove_const :CON if defined? CON
|
|
CON = 'Constant'.freeze
|
|
module Mod2
|
|
end
|
|
end
|
|
|
|
completer_test(Mod).call('CON')
|
|
|
|
# Constants or Class Methods
|
|
completer_test(o).call('Mod::CON')
|
|
|
|
# Symbol
|
|
_foo = :symbol
|
|
completer_test(o).call(':symbol')
|
|
|
|
# Variables
|
|
class << o
|
|
attr_accessor :foo
|
|
end
|
|
o.foo = 'bar'
|
|
completer_test(binding).call('o.foo')
|
|
|
|
# trailing slash
|
|
expect(Pry::InputCompleter.new(Readline).call('Mod2/', target: Pry.binding_for(Mod))
|
|
.include?('Mod2/')).to eq(true)
|
|
end
|
|
|
|
it 'should complete for arbitrary scopes' do
|
|
module Bar
|
|
@barvar = :bar
|
|
end
|
|
|
|
module Baz
|
|
remove_const :CON if defined? CON
|
|
@bar = Bar
|
|
@bazvar = :baz
|
|
CON = :constant
|
|
end
|
|
|
|
pry = Pry.new(target: Baz)
|
|
pry.push_binding(Bar)
|
|
|
|
b = Pry.binding_for(Bar)
|
|
completer_test(b, pry).call("../@bazvar")
|
|
completer_test(b, pry).call('/CON')
|
|
end
|
|
|
|
it 'should not return nil in its output' do
|
|
pry = Pry.new
|
|
expect(Pry::InputCompleter.new(Readline, pry).call("pry.", target: binding))
|
|
.not_to include nil
|
|
end
|
|
|
|
it 'completes expressions with all available methods' do
|
|
completer_test(self).call("[].size.chars")
|
|
end
|
|
|
|
it 'does not offer methods from restricted modules' do
|
|
require 'irb'
|
|
completer_test(self, nil, false).call("[].size.parse_printf_format")
|
|
end
|
|
|
|
unless Pry::Helpers::Platform.jruby?
|
|
# Classes that override .hash are still hashable in JRuby, for some reason.
|
|
it 'ignores methods from modules that override Object#hash incompatibly' do
|
|
require 'irb'
|
|
|
|
m = Module.new do
|
|
def self.hash; end
|
|
|
|
def aaaa; end
|
|
end
|
|
|
|
completer_test(m, nil, false).call("[].size.aaaa")
|
|
end
|
|
end
|
|
end
|