From 3bbe0f0c32cb46e4effbd764599b4196f9d53bec Mon Sep 17 00:00:00 2001 From: Ryan Fitzgerald Date: Wed, 23 Oct 2013 22:58:26 -0700 Subject: [PATCH 1/4] Remove support for 1.8-compatible versions of Ruby --- lib/pry.rb | 7 - lib/pry/commands/find_method.rb | 6 - lib/pry/commands/show_info.rb | 5 - lib/pry/core_extensions.rb | 60 +- lib/pry/helpers/base_helpers.rb | 4 - lib/pry/hooks.rb | 20 +- lib/pry/method.rb | 2 - lib/pry/terminal.rb | 3 +- lib/pry/test/helper.rb | 4 - lib/pry/wrapped_module.rb | 36 +- spec/command_spec.rb | 6 +- spec/commands/find_method_spec.rb | 105 ++- spec/commands/gem_list_spec.rb | 1 - spec/commands/ls_spec.rb | 20 +- spec/commands/show_doc_spec.rb | 968 ++++++++++---------- spec/commands/show_source_spec.rb | 1360 ++++++++++++++--------------- spec/commands/whereami_spec.rb | 16 +- spec/method_spec.rb | 30 +- spec/pry_spec.rb | 26 +- spec/run_command_spec.rb | 10 +- 20 files changed, 1291 insertions(+), 1398 deletions(-) diff --git a/lib/pry.rb b/lib/pry.rb index c558b3df..626f46fa 100644 --- a/lib/pry.rb +++ b/lib/pry.rb @@ -176,13 +176,6 @@ class Pry end end -if Pry::Helpers::BaseHelpers.mri_18? - begin - require 'ruby18_source_location' - rescue LoadError - end -end - require 'method_source' require 'shellwords' require 'stringio' diff --git a/lib/pry/commands/find_method.rb b/lib/pry/commands/find_method.rb index a6d024e7..da9c85d3 100644 --- a/lib/pry/commands/find_method.rb +++ b/lib/pry/commands/find_method.rb @@ -6,8 +6,6 @@ class Pry group 'Context' description 'Recursively search for a method within a Class/Module or the current namespace.' command_options :shellwords => false - command_options :requires_gem => 'ruby18_source_location' if mri_18? - banner <<-'BANNER' Usage: find-method [-n|-c] METHOD [NAMESPACE] @@ -26,10 +24,6 @@ class Pry find-method -c 'output.puts' Pry BANNER - def setup - require 'ruby18_source_location' if mri_18? - end - def options(opti) opti.on :n, :name, "Search for a method by name" opti.on :c, :content, "Search for a method based on content in Regex form" diff --git a/lib/pry/commands/show_info.rb b/lib/pry/commands/show_info.rb index 722e656d..6dbc0cd6 100644 --- a/lib/pry/commands/show_info.rb +++ b/lib/pry/commands/show_info.rb @@ -3,11 +3,6 @@ class Pry extend Pry::Helpers::BaseHelpers command_options :shellwords => false, :interpolate => false - command_options :requires_gem => "ruby18_source_location" if mri_18? - - def setup - require 'ruby18_source_location' if mri_18? - end def options(opt) opt.on :s, :super, "Select the 'super' method. Can be repeated to traverse the ancestors", :as => :count diff --git a/lib/pry/core_extensions.rb b/lib/pry/core_extensions.rb index 7b4b33b2..a418daf3 100644 --- a/lib/pry/core_extensions.rb +++ b/lib/pry/core_extensions.rb @@ -99,37 +99,33 @@ class Object end end -if defined?(BasicObject) - class BasicObject - # Return a binding object for the receiver. - # - # The `self` of the binding is set to the current object, and it contains no - # local variables. - # - # The default definee (http://yugui.jp/articles/846) is set such that new - # methods defined will be added to the singleton class of the BasicObject. - # - # @return [Binding] - def __binding__ - # BasicObjects don't have respond_to?, so we just define the method - # every time. As they also don't have `.freeze`, this call won't - # fail as it can for normal Objects. - (class << self; self; end).class_eval <<-EOF, __FILE__, __LINE__ + 1 - # Get a binding with 'self' set to self, and no locals. - # - # The default definee is determined by the context in which the - # definition is eval'd. - # - # Please don't call this method directly, see {__binding__}. - # - # @return [Binding] - def __pry__ - # In ruby-1.8.7 ::Kernel.binding sets self to Kernel in the returned binding. - # Luckily ruby-1.8.7 doesn't have BasicObject, so this is safe. - ::Kernel.binding - end - EOF - self.__pry__ - end +class BasicObject + # Return a binding object for the receiver. + # + # The `self` of the binding is set to the current object, and it contains no + # local variables. + # + # The default definee (http://yugui.jp/articles/846) is set such that new + # methods defined will be added to the singleton class of the BasicObject. + # + # @return [Binding] + def __binding__ + # BasicObjects don't have respond_to?, so we just define the method + # every time. As they also don't have `.freeze`, this call won't + # fail as it can for normal Objects. + (class << self; self; end).class_eval <<-EOF, __FILE__, __LINE__ + 1 + # Get a binding with 'self' set to self, and no locals. + # + # The default definee is determined by the context in which the + # definition is eval'd. + # + # Please don't call this method directly, see {__binding__}. + # + # @return [Binding] + def __pry__ + ::Kernel.binding + end + EOF + self.__pry__ end end diff --git a/lib/pry/helpers/base_helpers.rb b/lib/pry/helpers/base_helpers.rb index df831a0d..cc447701 100644 --- a/lib/pry/helpers/base_helpers.rb +++ b/lib/pry/helpers/base_helpers.rb @@ -90,10 +90,6 @@ class Pry RbConfig::CONFIG['ruby_install_name'] == 'ruby' end - def mri_18? - mri? && RUBY_VERSION =~ /1.8/ - end - def mri_19? mri? && RUBY_VERSION =~ /1.9/ end diff --git a/lib/pry/hooks.rb b/lib/pry/hooks.rb index ca48ad67..f234ab5a 100644 --- a/lib/pry/hooks.rb +++ b/lib/pry/hooks.rb @@ -146,18 +146,14 @@ class Pry def exec_hook(event_name, *args, &block) @hooks[event_name] ||= [] - # silence warnings to get rid of 1.8's "warning: multiple values - # for a block parameter" warnings - Pry::Helpers::BaseHelpers.silence_warnings do - @hooks[event_name].map do |hook_name, callable| - begin - callable.call(*args, &block) - rescue RescuableException => e - errors << e - e - end - end.last - end + @hooks[event_name].map do |hook_name, callable| + begin + callable.call(*args, &block) + rescue RescuableException => e + errors << e + e + end + end.last end # Return the number of hook functions registered for the `event_name` event. diff --git a/lib/pry/method.rb b/lib/pry/method.rb index 06284420..2b247c57 100644 --- a/lib/pry/method.rb +++ b/lib/pry/method.rb @@ -405,8 +405,6 @@ class Pry end # @return [Array] All known aliases for the method. - # @note On Ruby 1.8 this method always returns an empty Array for methods - # implemented in C. def aliases owner = @method.owner # Avoid using `to_sym` on {Method#name}, which returns a `String`, because diff --git a/lib/pry/terminal.rb b/lib/pry/terminal.rb index 10cbcf85..d88716b0 100644 --- a/lib/pry/terminal.rb +++ b/lib/pry/terminal.rb @@ -44,7 +44,8 @@ class Pry::Terminal require 'io/console' $stdout.winsize if $stdout.tty? and $stdout.respond_to?(:winsize) rescue LoadError - # They're probably on 1.8 without the io-console gem. We'll keep trying. + # They probably don't have the io/console stdlib or the io-console gem. + # We'll keep trying. end def screen_size_according_to_env diff --git a/lib/pry/test/helper.rb b/lib/pry/test/helper.rb index 3cf0371d..74d40512 100644 --- a/lib/pry/test/helper.rb +++ b/lib/pry/test/helper.rb @@ -47,10 +47,6 @@ module PryTestHelpers end end - def mri18_and_no_real_source_location? - Pry::Helpers::BaseHelpers.mri_18? && !(Method.instance_method(:source_location).owner == Method) - end - # Open a temp file and yield it to the block, closing it after # @return [String] The path of the temp file def temp_file(ext='.rb') diff --git a/lib/pry/wrapped_module.rb b/lib/pry/wrapped_module.rb index abe9e0b8..6022c5df 100644 --- a/lib/pry/wrapped_module.rb +++ b/lib/pry/wrapped_module.rb @@ -66,28 +66,12 @@ class Pry end # Returns an array of the names of the constants accessible in the wrapped - # module. This provides a consistent interface between 1.8 and 1.9 and also - # avoids the problem of accidentally calling the singleton method - # `Module.constants`. + # module. This avoids the problem of accidentally calling the singleton + # method `Module.constants`. # @param [Boolean] inherit Include the names of constants from included # modules? def constants(inherit = true) - method = Module.instance_method(:constants).bind(@wrapped) - - # If we're on 1.8, we have to manually remove ancestors' constants. If - # we're on 1.9, though, it's better to use the built-in `inherit` param, - # since it doesn't do things like incorrectly remove Pry::Config. - if method.arity == 0 - consts = method.call - if !inherit - ancestors_ = Pry::Method.safe_send(@wrapped, :ancestors) - consts -= (ancestors_ - [@wrapped]).map(&:constants).flatten - end - else - consts = method.call(inherit) - end - - consts + Module.instance_method(:constants).bind(@wrapped).call(inherit) end # The prefix that would appear before methods defined on this class. @@ -259,7 +243,7 @@ class Pry # @return [Enumerator, Array] on JRuby 1.9 and higher returns Array, on # other rubies returns Enumerator def candidates - enum = generator.new do |y| + enum = Enumerator.new do |y| (0...number_of_candidates).each do |num| y.yield candidate(num) end @@ -292,18 +276,6 @@ class Pry private - # Ruby 1.8 doesn't support `Enumerator` (it's called Generator instead) - # - # @return [Object] Return the appropriate generator class. - def generator - @generator ||= if defined?(Enumerator) - Enumerator - else - require 'generator' - Generator - end - end - # @return [Pry::WrappedModule::Candidate] The candidate with the # highest rank, that is the 'monkey patch' of this module with the # highest number of methods, which contains a source code line that diff --git a/spec/command_spec.rb b/spec/command_spec.rb index 358d82d9..f89c2a2a 100644 --- a/spec/command_spec.rb +++ b/spec/command_spec.rb @@ -664,10 +664,8 @@ describe "Pry::Command" do pry_eval('my---test').should =~ /my-testmy-test/ end - if !mri18_and_no_real_source_location? - it "shows the source of the process method" do - pry_eval('show-source my-test').should =~ /output.puts command_name/ - end + it "shows the source of the process method" do + pry_eval('show-source my-test').should =~ /output.puts command_name/ end describe "command options hash" do diff --git a/spec/commands/find_method_spec.rb b/spec/commands/find_method_spec.rb index 78ee5a78..7991b678 100644 --- a/spec/commands/find_method_spec.rb +++ b/spec/commands/find_method_spec.rb @@ -1,70 +1,63 @@ require 'helper' -# we turn off the test for MRI 1.8 because our source_location hack -# for C methods actually runs the methods - and since it runs ALL -# methods (in an attempt to find a match) it runs 'exit' and aborts -# the test, causing a failure. We should fix this in the future by -# blacklisting certain methods for 1.8 MRI (such as exit, fork, and so on) -unless Pry::Helpers::BaseHelpers.mri_18? - MyKlass = Class.new do - def hello - "timothy" +MyKlass = Class.new do + def hello + "timothy" + end + def goodbye + "jenny" + end + def tea_tim? + "timothy" + end + def tea_time? + "polly" + end +end + +describe "find-method" do + describe "find matching methods by name regex (-n option)" do + it "should find a method by regex" do + pry_eval("find-method hell MyKlass").should =~ + /MyKlass.*?hello/m end - def goodbye - "jenny" - end - def tea_tim? - "timothy" - end - def tea_time? - "polly" + + it "should NOT match a method that does not match the regex" do + pry_eval("find-method hell MyKlass").should.not =~ + /MyKlass.*?goodbye/m end end - describe "find-method" do - describe "find matching methods by name regex (-n option)" do - it "should find a method by regex" do - pry_eval("find-method hell MyKlass").should =~ - /MyKlass.*?hello/m - end - - it "should NOT match a method that does not match the regex" do - pry_eval("find-method hell MyKlass").should.not =~ - /MyKlass.*?goodbye/m - end - end - - describe "find matching methods by content regex (-c option)" do - it "should find a method by regex" do - pry_eval("find-method -c timothy MyKlass").should =~ - /MyKlass.*?hello/m - end - - it "should NOT match a method that does not match the regex" do - pry_eval("find-method timothy MyKlass").should.not =~ - /MyKlass.*?goodbye/m - end - end - - it "should work with badly behaved constants" do - MyKlass::X = Object.new - def (MyKlass::X).hash - raise "mooo" - end - + describe "find matching methods by content regex (-c option)" do + it "should find a method by regex" do pry_eval("find-method -c timothy MyKlass").should =~ /MyKlass.*?hello/m end - it "should escape regexes correctly" do - good = /tea_time\?/ - bad = /tea_tim\?/ - pry_eval('find-method tea_time? MyKlass').should =~ good - pry_eval('find-method tea_time? MyKlass').should =~ good - pry_eval('find-method tea_time\? MyKlass').should.not =~ bad - pry_eval('find-method tea_time\? MyKlass').should =~ good + it "should NOT match a method that does not match the regex" do + pry_eval("find-method timothy MyKlass").should.not =~ + /MyKlass.*?goodbye/m end end - Object.remove_const(:MyKlass) + it "should work with badly behaved constants" do + MyKlass::X = Object.new + def (MyKlass::X).hash + raise "mooo" + end + + pry_eval("find-method -c timothy MyKlass").should =~ + /MyKlass.*?hello/m + end + + it "should escape regexes correctly" do + good = /tea_time\?/ + bad = /tea_tim\?/ + pry_eval('find-method tea_time? MyKlass').should =~ good + pry_eval('find-method tea_time? MyKlass').should =~ good + pry_eval('find-method tea_time\? MyKlass').should.not =~ bad + pry_eval('find-method tea_time\? MyKlass').should =~ good + end end + +Object.remove_const(:MyKlass) diff --git a/spec/commands/gem_list_spec.rb b/spec/commands/gem_list_spec.rb index 7f7c2510..0e630574 100644 --- a/spec/commands/gem_list_spec.rb +++ b/spec/commands/gem_list_spec.rb @@ -1,7 +1,6 @@ require 'helper' describe "gem-list" do - # fixing bug for 1.8 compat it 'should not raise when invoked' do proc { pry_eval(self, 'gem-list') diff --git a/spec/commands/ls_spec.rb b/spec/commands/ls_spec.rb index 7c2b672a..a35d8198 100644 --- a/spec/commands/ls_spec.rb +++ b/spec/commands/ls_spec.rb @@ -34,18 +34,16 @@ describe "ls" do end end - if defined?(BasicObject) - describe "BasicObject" do - it "should work on BasicObject" do - pry_eval("ls BasicObject.new").should =~ /BasicObject#methods:.*__send__/m - end + describe "BasicObject" do + it "should work on BasicObject" do + pry_eval("ls BasicObject.new").should =~ /BasicObject#methods:.*__send__/m + end - it "should work on subclasses of BasicObject" do - pry_eval( - "class LessBasic < BasicObject; def jaroussky; 5; end; end", - "ls LessBasic.new" - ).should =~ /LessBasic#methods:.*jaroussky/m - end + it "should work on subclasses of BasicObject" do + pry_eval( + "class LessBasic < BasicObject; def jaroussky; 5; end; end", + "ls LessBasic.new" + ).should =~ /LessBasic#methods:.*jaroussky/m end end diff --git a/spec/commands/show_doc_spec.rb b/spec/commands/show_doc_spec.rb index f69910e7..16d1757b 100644 --- a/spec/commands/show_doc_spec.rb +++ b/spec/commands/show_doc_spec.rb @@ -1,575 +1,571 @@ require 'helper' require "fixtures/show_source_doc_examples" -if !PryTestHelpers.mri18_and_no_real_source_location? - describe "show-doc" do +describe "show-doc" do + before do + @o = Object.new + + # sample doc + def @o.sample_method + :sample + end + + def @o.no_docs;end + + end + + it 'should output a method\'s documentation' do + pry_eval(binding, "show-doc @o.sample_method").should =~ /sample doc/ + end + + it 'should raise exception when cannot find docs' do + lambda { pry_eval(binding, "show-doc @o.no_docs") }.should.raise(Pry::CommandError) + end + + it 'should output a method\'s documentation with line numbers' do + pry_eval(binding, "show-doc @o.sample_method -l").should =~ /\d: sample doc/ + end + + it 'should output a method\'s documentation with line numbers (base one)' do + pry_eval(binding, "show-doc @o.sample_method -b").should =~ /1: sample doc/ + end + + it 'should output a method\'s documentation if inside method without needing to use method name' do + # sample comment + def @o.sample + pry_eval(binding, 'show-doc').should =~ /sample comment/ + end + @o.sample + end + + describe "finding find super method docs with help of `--super` switch" do before do - @o = Object.new - - # sample doc - def @o.sample_method - :sample + class Daddy + # daddy initialize! + def initialize(*args); end end - def @o.no_docs;end - - end - - it 'should output a method\'s documentation' do - pry_eval(binding, "show-doc @o.sample_method").should =~ /sample doc/ - end - - it 'should raise exception when cannot find docs' do - lambda { pry_eval(binding, "show-doc @o.no_docs") }.should.raise(Pry::CommandError) - end - - it 'should output a method\'s documentation with line numbers' do - pry_eval(binding, "show-doc @o.sample_method -l").should =~ /\d: sample doc/ - end - - it 'should output a method\'s documentation with line numbers (base one)' do - pry_eval(binding, "show-doc @o.sample_method -b").should =~ /1: sample doc/ - end - - it 'should output a method\'s documentation if inside method without needing to use method name' do - # sample comment - def @o.sample - pry_eval(binding, 'show-doc').should =~ /sample comment/ + class Classy < Daddy + # classy initialize! + def initialize(*args); end end - @o.sample + + class Grungy < Classy + # grungy initialize?? + def initialize(*args); end + end + + @o = Grungy.new + + # instancey initialize! + def @o.initialize; end end - describe "finding find super method docs with help of `--super` switch" do - before do - class Daddy - # daddy initialize! - def initialize(*args); end + after do + Object.remove_const(:Grungy) + Object.remove_const(:Classy) + Object.remove_const(:Daddy) + end + + it "finds super method docs" do + output = pry_eval(binding, 'show-doc --super @o.initialize') + output.should =~ /grungy initialize/ + end + + it "traverses ancestor chain and finds super method docs" do + output = pry_eval(binding, 'show-doc -ss @o.initialize') + output.should =~ /classy initialize/ + end + + it "traverses ancestor chain even higher and finds super method doc" do + output = pry_eval(binding, 'show-doc @o.initialize -sss') + output.should =~ /daddy initialize/ + end + + it "finds super method docs without explicit method argument" do + fatty = Grungy.new + + # fatty initialize! + def fatty.initialize + pry_eval(binding, 'show-doc --super') + end + + output = fatty.initialize + output.should =~ /grungy initialize/ + end + + it "finds super method docs without `--super` but with the `super` keyword" do + fatty = Grungy.new + + fatty.extend Module.new { + def initialize + :nibble end + } - class Classy < Daddy - # classy initialize! - def initialize(*args); end + # fatty initialize! + def fatty.initialize + pry_eval(binding, 'show-doc --super --super') + end + + output = fatty.initialize + output.should =~ /grungy initialize/ + end + end + + describe "rdoc highlighting" do + it "should syntax highlight code in rdoc" do + c = Class.new{ + # This can initialize your class: + # + # a = c.new :foo + # + # @param foo + def initialize(foo); end + } + + begin + t = pry_tester(binding) + t.eval("show-doc c#initialize").should =~ /c.new :foo/ + Pry.config.color = true + # I don't want the test to rely on which colour codes are there, just to + # assert that "something" is being colourized. + t.eval("show-doc c#initialize").should.not =~ /c.new :foo/ + ensure + Pry.config.color = false + end + end + + it "should syntax highlight `code` in rdoc" do + c = Class.new{ + # After initializing your class with `c.new(:foo)`, go have fun! + # + # @param foo + def initialize(foo); end + } + + begin + t = pry_tester(binding) + t.eval("show-doc c#initialize").should =~ /c.new\(:foo\)/ + Pry.config.color = true + # I don't want the test to rely on which colour codes are there, just to + # assert that "something" is being colourized. + t.eval("show-doc c#initialize").should.not =~ /c.new\(:foo\)/ + ensure + Pry.config.color = false + end + + end + + it "should not syntax highlight `` inside code" do + c = Class.new{ + # Convert aligned output (from many shell commands) into nested arrays: + # + # a = decolumnize `ls -l $HOME` + # + # @param output + def decolumnize(output); end + } + + begin + t = pry_tester(binding) + Pry.config.color = true + t.eval("show-doc c#decolumnize").should =~ /ls -l \$HOME/ + t.eval("show-doc c#decolumnize").should.not =~ /`ls -l \$HOME`/ + ensure + Pry.config.color = false + end + end + end + + describe "on sourcable objects" do + it "should show documentation for object" do + # this is a documentation + hello = proc { puts 'hello world!' } + mock_pry(binding, "show-doc hello").should =~ /this is a documentation/ + end + end + + describe "on modules" do + before do + # god this is boring1 + class ShowSourceTestClass + def alpha end + end - class Grungy < Classy - # grungy initialize?? - def initialize(*args); end + # god this is boring2 + module ShowSourceTestModule + def alpha end - - @o = Grungy.new - - # instancey initialize! - def @o.initialize; end end - after do - Object.remove_const(:Grungy) - Object.remove_const(:Classy) - Object.remove_const(:Daddy) - end - - it "finds super method docs" do - output = pry_eval(binding, 'show-doc --super @o.initialize') - output.should =~ /grungy initialize/ - end - - it "traverses ancestor chain and finds super method docs" do - output = pry_eval(binding, 'show-doc -ss @o.initialize') - output.should =~ /classy initialize/ - end - - it "traverses ancestor chain even higher and finds super method doc" do - output = pry_eval(binding, 'show-doc @o.initialize -sss') - output.should =~ /daddy initialize/ - end - - it "finds super method docs without explicit method argument" do - fatty = Grungy.new - - # fatty initialize! - def fatty.initialize - pry_eval(binding, 'show-doc --super') + # god this is boring3 + ShowSourceTestClassWeirdSyntax = Class.new do + def beta end - - output = fatty.initialize - output.should =~ /grungy initialize/ end - it "finds super method docs without `--super` but with the `super` keyword" do - fatty = Grungy.new + # god this is boring4 + ShowSourceTestModuleWeirdSyntax = Module.new do + def beta + end + end + end - fatty.extend Module.new { - def initialize - :nibble + after do + Object.remove_const :ShowSourceTestClass + Object.remove_const :ShowSourceTestClassWeirdSyntax + Object.remove_const :ShowSourceTestModule + Object.remove_const :ShowSourceTestModuleWeirdSyntax + end + + describe "basic functionality, should show docs for top-level module definitions" do + it 'should show docs for a class' do + pry_eval("show-doc ShowSourceTestClass").should =~ + /god this is boring1/ + end + + it 'should show docs for a module' do + pry_eval("show-doc ShowSourceTestModule").should =~ + /god this is boring2/ + end + + it 'should show docs for a class when Const = Class.new syntax is used' do + pry_eval("show-doc ShowSourceTestClassWeirdSyntax").should =~ + /god this is boring3/ + end + + it 'should show docs for a module when Const = Module.new syntax is used' do + pry_eval("show-doc ShowSourceTestModuleWeirdSyntax").should =~ + /god this is boring4/ + end + end + + describe "in REPL" do + it 'should find class defined in repl' do + t = pry_tester + t.eval <<-RUBY + # hello tobina + class TobinaMyDog + def woof + end end - } - - # fatty initialize! - def fatty.initialize - pry_eval(binding, 'show-doc --super --super') - end - - output = fatty.initialize - output.should =~ /grungy initialize/ + RUBY + t.eval('show-doc TobinaMyDog').should =~ /hello tobina/ + Object.remove_const :TobinaMyDog end end - describe "rdoc highlighting" do - it "should syntax highlight code in rdoc" do - c = Class.new{ - # This can initialize your class: - # - # a = c.new :foo - # - # @param foo - def initialize(foo); end - } - - begin - t = pry_tester(binding) - t.eval("show-doc c#initialize").should =~ /c.new :foo/ - Pry.config.color = true - # I don't want the test to rely on which colour codes are there, just to - # assert that "something" is being colourized. - t.eval("show-doc c#initialize").should.not =~ /c.new :foo/ - ensure - Pry.config.color = false - end - end - - it "should syntax highlight `code` in rdoc" do - c = Class.new{ - # After initializing your class with `c.new(:foo)`, go have fun! - # - # @param foo - def initialize(foo); end - } - - begin - t = pry_tester(binding) - t.eval("show-doc c#initialize").should =~ /c.new\(:foo\)/ - Pry.config.color = true - # I don't want the test to rely on which colour codes are there, just to - # assert that "something" is being colourized. - t.eval("show-doc c#initialize").should.not =~ /c.new\(:foo\)/ - ensure - Pry.config.color = false - end - - end - - it "should not syntax highlight `` inside code" do - c = Class.new{ - # Convert aligned output (from many shell commands) into nested arrays: - # - # a = decolumnize `ls -l $HOME` - # - # @param output - def decolumnize(output); end - } - - begin - t = pry_tester(binding) - Pry.config.color = true - t.eval("show-doc c#decolumnize").should =~ /ls -l \$HOME/ - t.eval("show-doc c#decolumnize").should.not =~ /`ls -l \$HOME`/ - ensure - Pry.config.color = false - end - end - end - - describe "on sourcable objects" do - it "should show documentation for object" do - # this is a documentation - hello = proc { puts 'hello world!' } - mock_pry(binding, "show-doc hello").should =~ /this is a documentation/ - end - end - - describe "on modules" do - before do - # god this is boring1 - class ShowSourceTestClass + it 'should lookup module name with respect to current context' do + constant_scope(:AlphaClass, :BetaClass) do + # top-level beta + class BetaClass def alpha end end - # god this is boring2 - module ShowSourceTestModule - def alpha - end - end - - # god this is boring3 - ShowSourceTestClassWeirdSyntax = Class.new do - def beta - end - end - - # god this is boring4 - ShowSourceTestModuleWeirdSyntax = Module.new do - def beta - end - end - end - - after do - Object.remove_const :ShowSourceTestClass - Object.remove_const :ShowSourceTestClassWeirdSyntax - Object.remove_const :ShowSourceTestModule - Object.remove_const :ShowSourceTestModuleWeirdSyntax - end - - describe "basic functionality, should show docs for top-level module definitions" do - it 'should show docs for a class' do - pry_eval("show-doc ShowSourceTestClass").should =~ - /god this is boring1/ - end - - it 'should show docs for a module' do - pry_eval("show-doc ShowSourceTestModule").should =~ - /god this is boring2/ - end - - it 'should show docs for a class when Const = Class.new syntax is used' do - pry_eval("show-doc ShowSourceTestClassWeirdSyntax").should =~ - /god this is boring3/ - end - - it 'should show docs for a module when Const = Module.new syntax is used' do - pry_eval("show-doc ShowSourceTestModuleWeirdSyntax").should =~ - /god this is boring4/ - end - end - - if !Pry::Helpers::BaseHelpers.mri_18? - describe "in REPL" do - it 'should find class defined in repl' do - t = pry_tester - t.eval <<-RUBY - # hello tobina - class TobinaMyDog - def woof - end - end - RUBY - t.eval('show-doc TobinaMyDog').should =~ /hello tobina/ - Object.remove_const :TobinaMyDog - end - end - end - - it 'should lookup module name with respect to current context' do - constant_scope(:AlphaClass, :BetaClass) do - # top-level beta + class AlphaClass + # nested beta class BetaClass - def alpha + def beta end end - - class AlphaClass - # nested beta - class BetaClass - def beta - end - end - end - - pry_eval(AlphaClass, "show-doc BetaClass").should =~ /nested beta/ end + + pry_eval(AlphaClass, "show-doc BetaClass").should =~ /nested beta/ + end + end + + it 'should look up nested modules' do + constant_scope(:AlphaClass) do + class AlphaClass + # nested beta + class BetaClass + def beta + end + end + end + + pry_eval("show-doc AlphaClass::BetaClass").should =~ + /nested beta/ + end + end + + describe "show-doc -a" do + it 'should show the docs for all monkeypatches defined in different files' do + # local monkeypatch + class TestClassForShowSource + def beta + end + end + + result = pry_eval("show-doc TestClassForShowSource -a") + result.should =~ /used by/ + result.should =~ /local monkeypatch/ end - it 'should look up nested modules' do - constant_scope(:AlphaClass) do - class AlphaClass - # nested beta - class BetaClass - def beta - end + describe "messages relating to -a" do + it "displays the original definition by default (not a doc of a monkeypatch)" do + class TestClassForCandidatesOrder + def beta end end - pry_eval("show-doc AlphaClass::BetaClass").should =~ - /nested beta/ + result = pry_eval("show-doc TestClassForCandidatesOrder") + result.should =~ /Number of monkeypatches: 2/ + result.should =~ /The first definition/ end - end - describe "show-doc -a" do - it 'should show the docs for all monkeypatches defined in different files' do - # local monkeypatch + it 'indicates all available monkeypatches can be shown with -a ' \ + '(when -a not used and more than one candidate exists for class)' do + # Still reading boring tests, eh? class TestClassForShowSource def beta end end - result = pry_eval("show-doc TestClassForShowSource -a") - result.should =~ /used by/ - result.should =~ /local monkeypatch/ + result = pry_eval('show-doc TestClassForShowSource') + result.should =~ /available monkeypatches/ end - describe "messages relating to -a" do - it "displays the original definition by default (not a doc of a monkeypatch)" do - class TestClassForCandidatesOrder - def beta - end - end - - result = pry_eval("show-doc TestClassForCandidatesOrder") - result.should =~ /Number of monkeypatches: 2/ - result.should =~ /The first definition/ + it 'shouldnt say anything about monkeypatches when only one candidate exists for selected class' do + # Do not remove me. + class Aarrrrrghh + def o;end end - it 'indicates all available monkeypatches can be shown with -a ' \ - '(when -a not used and more than one candidate exists for class)' do - # Still reading boring tests, eh? - class TestClassForShowSource - def beta - end - end - - result = pry_eval('show-doc TestClassForShowSource') - result.should =~ /available monkeypatches/ - end - - it 'shouldnt say anything about monkeypatches when only one candidate exists for selected class' do - # Do not remove me. - class Aarrrrrghh - def o;end - end - - result = pry_eval('show-doc Aarrrrrghh') - result.should.not =~ /available monkeypatches/ - Object.remove_const(:Aarrrrrghh) - end - end - end - - describe "when no class/module arg is given" do - before do - module TestHost - - # hello there froggy - module M - def d; end - def e; end - end - end - end - - after do - Object.remove_const(:TestHost) - end - - it 'should return doc for current module' do - pry_eval(TestHost::M, "show-doc").should =~ /hello there froggy/ - end - end - - # FIXME: THis is nto a good spec anyway, because i dont think it - # SHOULD skip! - describe "should skip over broken modules" do - before do - module TestHost - # hello - module M - binding.eval("def a; end", "dummy.rb", 1) - binding.eval("def b; end", "dummy.rb", 2) - binding.eval("def c; end", "dummy.rb", 3) - end - - # goodbye - module M - def d; end - def e; end - end - end - end - - after do - Object.remove_const(:TestHost) - end - - it 'should return doc for first valid module' do - result = pry_eval("show-doc TestHost::M") - result.should =~ /goodbye/ - result.should.not =~ /hello/ + result = pry_eval('show-doc Aarrrrrghh') + result.should.not =~ /available monkeypatches/ + Object.remove_const(:Aarrrrrghh) end end end - describe "on commands" do - # mostly copied & modified from test_help.rb + describe "when no class/module arg is given" do before do - @oldset = Pry.config.commands - @set = Pry.config.commands = Pry::CommandSet.new do - import Pry::Commands + module TestHost + + # hello there froggy + module M + def d; end + def e; end + end end end after do - Pry.config.commands = @oldset + Object.remove_const(:TestHost) end - it 'should display help for a specific command' do - pry_eval('show-doc ls').should =~ /Usage: ls/ + it 'should return doc for current module' do + pry_eval(TestHost::M, "show-doc").should =~ /hello there froggy/ end + end - it 'should display help for a regex command with a "listing"' do - @set.command /bar(.*)/, "Test listing", :listing => "foo" do; end - pry_eval('show-doc foo').should =~ /Test listing/ - end - - it 'should display help for a command with a spaces in its name' do - @set.command "command with spaces", "description of a command with spaces" do; end - pry_eval('show-doc command with spaces').should =~ /description of a command with spaces/ - end - - describe "class commands" do - before do - # pretty pink pincers - class LobsterLady < Pry::ClassCommand - match "lobster-lady" - description "nada." - def process - "lobster" - end + # FIXME: THis is nto a good spec anyway, because i dont think it + # SHOULD skip! + describe "should skip over broken modules" do + before do + module TestHost + # hello + module M + binding.eval("def a; end", "dummy.rb", 1) + binding.eval("def b; end", "dummy.rb", 2) + binding.eval("def c; end", "dummy.rb", 3) end - Pry.commands.add_command(LobsterLady) + # goodbye + module M + def d; end + def e; end + end + end + end + + after do + Object.remove_const(:TestHost) + end + + it 'should return doc for first valid module' do + result = pry_eval("show-doc TestHost::M") + result.should =~ /goodbye/ + result.should.not =~ /hello/ + end + end + end + + describe "on commands" do + # mostly copied & modified from test_help.rb + before do + @oldset = Pry.config.commands + @set = Pry.config.commands = Pry::CommandSet.new do + import Pry::Commands + end + end + + after do + Pry.config.commands = @oldset + end + + it 'should display help for a specific command' do + pry_eval('show-doc ls').should =~ /Usage: ls/ + end + + it 'should display help for a regex command with a "listing"' do + @set.command /bar(.*)/, "Test listing", :listing => "foo" do; end + pry_eval('show-doc foo').should =~ /Test listing/ + end + + it 'should display help for a command with a spaces in its name' do + @set.command "command with spaces", "description of a command with spaces" do; end + pry_eval('show-doc command with spaces').should =~ /description of a command with spaces/ + end + + describe "class commands" do + before do + # pretty pink pincers + class LobsterLady < Pry::ClassCommand + match "lobster-lady" + description "nada." + def process + "lobster" + end + end + + Pry.commands.add_command(LobsterLady) + end + + after do + Object.remove_const(:LobsterLady) + end + + it 'should display "help" when looking up by command name' do + pry_eval('show-doc lobster-lady').should =~ /nada/ + Pry.commands.delete("lobster-lady") + end + + it 'should display actual preceding comment for a class command, when class is used (rather than command name) when looking up' do + pry_eval('show-doc LobsterLady').should =~ /pretty pink pincers/ + Pry.commands.delete("lobster-lady") + end + end + end + + describe "should set _file_ and _dir_" do + it 'should set _file_ and _dir_ to file containing method source' do + t = pry_tester + t.process_command "show-doc TestClassForShowSource#alpha" + t.pry.last_file.should =~ /show_source_doc_examples/ + t.pry.last_dir.should =~ /fixtures/ + end + end + + unless Pry::Helpers::BaseHelpers.rbx? + describe "can't find class docs" do + describe "for classes" do + before do + module Jesus + class Brian; end + + # doink-doc + class Jingle + def a; :doink; end + end + + class Jangle < Jingle; end + class Bangle < Jangle; end + end end after do - Object.remove_const(:LobsterLady) + Object.remove_const(:Jesus) end - it 'should display "help" when looking up by command name' do - pry_eval('show-doc lobster-lady').should =~ /nada/ - Pry.commands.delete("lobster-lady") + it 'shows superclass doc' do + t = pry_tester + t.process_command "show-doc Jesus::Jangle" + t.last_output.should =~ /doink-doc/ end - it 'should display actual preceding comment for a class command, when class is used (rather than command name) when looking up' do - pry_eval('show-doc LobsterLady').should =~ /pretty pink pincers/ - Pry.commands.delete("lobster-lady") + it 'errors when class has no superclass to show' do + t = pry_tester + lambda { t.process_command "show-doc Jesus::Brian" }.should.raise(Pry::CommandError).message. + should =~ /Couldn't locate/ + end + + it 'shows warning when reverting to superclass docs' do + t = pry_tester + t.process_command "show-doc Jesus::Jangle" + t.last_output.should =~ /Warning.*?Cannot find.*?Jesus::Jangle.*Showing.*Jesus::Jingle instead/ + end + + it 'shows nth level superclass docs (when no intermediary superclasses have code either)' do + t = pry_tester + t.process_command "show-doc Jesus::Bangle" + t.last_output.should =~ /doink-doc/ + end + + it 'shows correct warning when reverting to nth level superclass' do + t = pry_tester + t.process_command "show-doc Jesus::Bangle" + t.last_output.should =~ /Warning.*?Cannot find.*?Jesus::Bangle.*Showing.*Jesus::Jingle instead/ end end - end - describe "should set _file_ and _dir_" do - it 'should set _file_ and _dir_ to file containing method source' do - t = pry_tester - t.process_command "show-doc TestClassForShowSource#alpha" - t.pry.last_file.should =~ /show_source_doc_examples/ - t.pry.last_dir.should =~ /fixtures/ - end - end + describe "for modules" do + before do + module Jesus - unless Pry::Helpers::BaseHelpers.rbx? - describe "can't find class docs" do - describe "for classes" do - before do - module Jesus - class Brian; end - - # doink-doc - class Jingle - def a; :doink; end - end - - class Jangle < Jingle; end - class Bangle < Jangle; end + # alpha-doc + module Alpha + def alpha; :alpha; end end - end - after do - Object.remove_const(:Jesus) - end + module Zeta; end - it 'shows superclass doc' do - t = pry_tester - t.process_command "show-doc Jesus::Jangle" - t.last_output.should =~ /doink-doc/ - end + module Beta + include Alpha + end - it 'errors when class has no superclass to show' do - t = pry_tester - lambda { t.process_command "show-doc Jesus::Brian" }.should.raise(Pry::CommandError).message. - should =~ /Couldn't locate/ - end - - it 'shows warning when reverting to superclass docs' do - t = pry_tester - t.process_command "show-doc Jesus::Jangle" - t.last_output.should =~ /Warning.*?Cannot find.*?Jesus::Jangle.*Showing.*Jesus::Jingle instead/ - end - - it 'shows nth level superclass docs (when no intermediary superclasses have code either)' do - t = pry_tester - t.process_command "show-doc Jesus::Bangle" - t.last_output.should =~ /doink-doc/ - end - - it 'shows correct warning when reverting to nth level superclass' do - t = pry_tester - t.process_command "show-doc Jesus::Bangle" - t.last_output.should =~ /Warning.*?Cannot find.*?Jesus::Bangle.*Showing.*Jesus::Jingle instead/ + module Gamma + include Beta + end end end - describe "for modules" do - before do - module Jesus + after do + Object.remove_const(:Jesus) + end - # alpha-doc - module Alpha - def alpha; :alpha; end - end + it 'shows included module doc' do + t = pry_tester + t.process_command "show-doc Jesus::Beta" + t.last_output.should =~ /alpha-doc/ + end - module Zeta; end + it 'shows warning when reverting to included module doc' do + t = pry_tester + t.process_command "show-doc Jesus::Beta" + t.last_output.should =~ /Warning.*?Cannot find.*?Jesus::Beta.*Showing.*Jesus::Alpha instead/ + end - module Beta - include Alpha - end + it 'errors when module has no included module to show' do + t = pry_tester + lambda { t.process_command "show-source Jesus::Zeta" }.should.raise(Pry::CommandError).message. + should =~ /Couldn't locate/ + end - module Gamma - include Beta - end - end - end + it 'shows nth level included module doc (when no intermediary modules have code either)' do + t = pry_tester + t.process_command "show-doc Jesus::Gamma" + t.last_output.should =~ /alpha-doc/ + end - after do - Object.remove_const(:Jesus) - end - - it 'shows included module doc' do - t = pry_tester - t.process_command "show-doc Jesus::Beta" - t.last_output.should =~ /alpha-doc/ - end - - it 'shows warning when reverting to included module doc' do - t = pry_tester - t.process_command "show-doc Jesus::Beta" - t.last_output.should =~ /Warning.*?Cannot find.*?Jesus::Beta.*Showing.*Jesus::Alpha instead/ - end - - it 'errors when module has no included module to show' do - t = pry_tester - lambda { t.process_command "show-source Jesus::Zeta" }.should.raise(Pry::CommandError).message. - should =~ /Couldn't locate/ - end - - it 'shows nth level included module doc (when no intermediary modules have code either)' do - t = pry_tester - t.process_command "show-doc Jesus::Gamma" - t.last_output.should =~ /alpha-doc/ - end - - it 'shows correct warning when reverting to nth level included module' do - t = pry_tester - t.process_command "show-source Jesus::Gamma" - t.last_output.should =~ /Warning.*?Cannot find.*?Jesus::Gamma.*Showing.*Jesus::Alpha instead/ - end + it 'shows correct warning when reverting to nth level included module' do + t = pry_tester + t.process_command "show-source Jesus::Gamma" + t.last_output.should =~ /Warning.*?Cannot find.*?Jesus::Gamma.*Showing.*Jesus::Alpha instead/ end end end diff --git a/spec/commands/show_source_spec.rb b/spec/commands/show_source_spec.rb index d98f604c..4c1a5648 100644 --- a/spec/commands/show_source_spec.rb +++ b/spec/commands/show_source_spec.rb @@ -1,284 +1,524 @@ require 'helper' require "fixtures/show_source_doc_examples" -if !PryTestHelpers.mri18_and_no_real_source_location? - describe "show-source" do - before do - @o = Object.new - def @o.sample_method - :sample +describe "show-source" do + before do + @o = Object.new + def @o.sample_method + :sample + end + + Object.const_set(:Test, Module.new) + end + + after do + Pad.clear + end + + it "should output a method's source" do + pry_eval(binding, 'show-source @o.sample_method').should =~ /def @o.sample/ + end + + it "should output help" do + pry_eval('show-source -h').should =~ /Usage:\s+show-source/ + end + + it "should output a method's source with line numbers" do + pry_eval(binding, 'show-source -l @o.sample_method').should =~ /\d+: def @o.sample/ + end + + it "should output a method's source with line numbers starting at 1" do + pry_eval(binding, 'show-source -b @o.sample_method').should =~ /1: def @o.sample/ + end + + it "should output a method's source if inside method and no name given" do + def @o.sample + pry_eval(binding, 'show-source').should =~ /def @o.sample/ + end + @o.sample + end + + it "should output a method's source inside method using the -l switch" do + def @o.sample + pry_eval(binding, 'show-source -l').should =~ /def @o.sample/ + end + @o.sample + end + + it "should find methods even if there are spaces in the arguments" do + def @o.foo(*bars) + "Mr flibble" + self + end + + out = pry_eval(binding, "show-source @o.foo('bar', 'baz bam').foo") + out.should =~ /Mr flibble/ + end + + it "should find methods even if the object overrides method method" do + c = Class.new{ + def method; + 98 + end + } + + pry_eval(binding, "show-source c.new.method").should =~ /98/ + end + + it "should not show the source when a non-extant method is requested" do + c = Class.new{ def method; 98; end } + mock_pry(binding, "show-source c#wrongmethod").should =~ /Couldn't locate/ + end + + it "should find instance_methods if the class overrides instance_method" do + c = Class.new{ + def method; + 98 end - Object.const_set(:Test, Module.new) + def self.instance_method; 789; end + } + + pry_eval(binding, "show-source c#method").should =~ /98/ + end + + it "should find instance methods with self#moo" do + c = Class.new{ def moo; "ve over!"; end } + + pry_eval(binding, "cd c", "show-source self#moo").should =~ /ve over/ + end + + it "should not find instance methods with self.moo" do + c = Class.new{ def moo; "ve over!"; end } + + proc { + pry_eval(binding, 'cd c', 'show-source self.moo') + }.should.raise(Pry::CommandError).message.should =~ /Couldn't locate/ + end + + it "should find normal methods with self.moo" do + c = Class.new{ def self.moo; "ve over!"; end } + + pry_eval(binding, 'cd c', 'show-source self.moo').should =~ /ve over/ + end + + it "should not find normal methods with self#moo" do + c = Class.new{ def self.moo; "ve over!"; end } + + proc { + pry_eval(binding, 'cd c', 'show-source self#moo') + }.should.raise(Pry::CommandError).message.should =~ /Couldn't locate/ + end + + it "should find normal methods (i.e non-instance methods) by default" do + c = Class.new{ def self.moo; "ve over!"; end } + + pry_eval(binding, "cd c", "show-source moo").should =~ /ve over/ + end + + it "should find instance methods if no normal methods available" do + c = Class.new{ def moo; "ve over!"; end } + + pry_eval(binding, "cd c", "show-source moo").should =~ /ve over/ + end + + it "should raise a CommandError when super method doesn't exist" do + def @o.foo(*bars); end + + proc { + pry_eval(binding, "show-source --super @o.foo") + }.should.raise(Pry::CommandError).message.should =~ /No superclass found/ + end + + it "should output the source of a method defined inside Pry" do + out = pry_eval("def dyn_method\n:test\nend", 'show-source dyn_method') + out.should =~ /def dyn_method/ + Object.remove_method :dyn_method + end + + it 'should output source for an instance method defined inside pry' do + pry_tester.tap do |t| + t.eval "class Test::A\n def yo\n end\nend" + t.eval('show-source Test::A#yo').should =~ /def yo/ + end + end + + it 'should output source for a repl method defined using define_method' do + pry_tester.tap do |t| + t.eval "class Test::A\n define_method(:yup) {}\nend" + t.eval('show-source Test::A#yup').should =~ /define_method\(:yup\)/ + end + end + + it "should output the source of a command defined inside Pry" do + command_definition = %{ + Pry.commands.command "hubba-hubba" do + puts "that's what she said!" + end + } + out = pry_eval(command_definition, 'show-source hubba-hubba') + out.should =~ /what she said/ + Pry.commands.delete "hubba-hubba" + end + + describe "finding super methods with help of `--super` switch" do + before do + class Foo + def foo(*bars) + :super_wibble + end + end end after do - Pad.clear + Object.remove_const(:Foo) end - it "should output a method's source" do - pry_eval(binding, 'show-source @o.sample_method').should =~ /def @o.sample/ - end + it "finds super methods with explicit method argument" do - it "should output help" do - pry_eval('show-source -h').should =~ /Usage:\s+show-source/ - end - - it "should output a method's source with line numbers" do - pry_eval(binding, 'show-source -l @o.sample_method').should =~ /\d+: def @o.sample/ - end - - it "should output a method's source with line numbers starting at 1" do - pry_eval(binding, 'show-source -b @o.sample_method').should =~ /1: def @o.sample/ - end - - it "should output a method's source if inside method and no name given" do - def @o.sample - pry_eval(binding, 'show-source').should =~ /def @o.sample/ - end - @o.sample - end - - it "should output a method's source inside method using the -l switch" do - def @o.sample - pry_eval(binding, 'show-source -l').should =~ /def @o.sample/ - end - @o.sample - end - - it "should find methods even if there are spaces in the arguments" do - def @o.foo(*bars) - "Mr flibble" - self + o = Foo.new + def o.foo(*bars) + :wibble end - out = pry_eval(binding, "show-source @o.foo('bar', 'baz bam').foo") - out.should =~ /Mr flibble/ + pry_eval(binding, "show-source --super o.foo").should =~ /:super_wibble/ end - it "should find methods even if the object overrides method method" do - c = Class.new{ - def method; - 98 + it "finds super methods without explicit method argument" do + o = Foo.new + def o.foo(*bars) + :wibble + pry_eval(binding, 'show-source --super') + end + + o.foo.should =~ /:super_wibble/ + end + + it "finds super methods with multiple --super " do + o = Foo.new + + o.extend Module.new { + def foo + :nibble end } - pry_eval(binding, "show-source c.new.method").should =~ /98/ - end - - it "should not show the source when a non-extant method is requested" do - c = Class.new{ def method; 98; end } - mock_pry(binding, "show-source c#wrongmethod").should =~ /Couldn't locate/ - end - - it "should find instance_methods if the class overrides instance_method" do - c = Class.new{ - def method; - 98 - end - - def self.instance_method; 789; end - } - - pry_eval(binding, "show-source c#method").should =~ /98/ - end - - it "should find instance methods with self#moo" do - c = Class.new{ def moo; "ve over!"; end } - - pry_eval(binding, "cd c", "show-source self#moo").should =~ /ve over/ - end - - it "should not find instance methods with self.moo" do - c = Class.new{ def moo; "ve over!"; end } - - proc { - pry_eval(binding, 'cd c', 'show-source self.moo') - }.should.raise(Pry::CommandError).message.should =~ /Couldn't locate/ - end - - it "should find normal methods with self.moo" do - c = Class.new{ def self.moo; "ve over!"; end } - - pry_eval(binding, 'cd c', 'show-source self.moo').should =~ /ve over/ - end - - it "should not find normal methods with self#moo" do - c = Class.new{ def self.moo; "ve over!"; end } - - proc { - pry_eval(binding, 'cd c', 'show-source self#moo') - }.should.raise(Pry::CommandError).message.should =~ /Couldn't locate/ - end - - it "should find normal methods (i.e non-instance methods) by default" do - c = Class.new{ def self.moo; "ve over!"; end } - - pry_eval(binding, "cd c", "show-source moo").should =~ /ve over/ - end - - it "should find instance methods if no normal methods available" do - c = Class.new{ def moo; "ve over!"; end } - - pry_eval(binding, "cd c", "show-source moo").should =~ /ve over/ - end - - it "should raise a CommandError when super method doesn't exist" do - def @o.foo(*bars); end - - proc { - pry_eval(binding, "show-source --super @o.foo") - }.should.raise(Pry::CommandError).message.should =~ /No superclass found/ - end - - # dynamically defined method source retrieval is only supported in - # 1.9 - where Method#source_location is native - if RUBY_VERSION =~ /1.9/ - it "should output the source of a method defined inside Pry" do - out = pry_eval("def dyn_method\n:test\nend", 'show-source dyn_method') - out.should =~ /def dyn_method/ - Object.remove_method :dyn_method + def o.foo(*bars) + :wibble + pry_eval(binding, 'show-source --super --super') end - it 'should output source for an instance method defined inside pry' do - pry_tester.tap do |t| - t.eval "class Test::A\n def yo\n end\nend" - t.eval('show-source Test::A#yo').should =~ /def yo/ - end - end + o.foo.should =~ /:super_wibble/ + end + end - it 'should output source for a repl method defined using define_method' do - pry_tester.tap do |t| - t.eval "class Test::A\n define_method(:yup) {}\nend" - t.eval('show-source Test::A#yup').should =~ /define_method\(:yup\)/ - end - end - - it "should output the source of a command defined inside Pry" do - command_definition = %{ - Pry.commands.command "hubba-hubba" do - puts "that's what she said!" - end - } - out = pry_eval(command_definition, 'show-source hubba-hubba') - out.should =~ /what she said/ - Pry.commands.delete "hubba-hubba" + describe "on sourcable objects" do + it "should output source defined inside pry" do + pry_tester.tap do |t| + t.eval "hello = proc { puts 'hello world!' }" + t.eval("show-source hello").should =~ /proc \{ puts/ end end - describe "finding super methods with help of `--super` switch" do + it "should output source for procs/lambdas stored in variables" do + hello = proc { puts 'hello world!' } + pry_eval(binding, 'show-source hello').should =~ /proc \{ puts/ + end + + it "should output source for procs/lambdas stored in constants" do + HELLO = proc { puts 'hello world!' } + pry_eval(binding, "show-source HELLO").should =~ /proc \{ puts/ + Object.remove_const(:HELLO) + end + + it "should output source for method objects" do + def @o.hi; puts 'hi world'; end + meth = @o.method(:hi) + pry_eval(binding, "show-source meth").should =~ /puts 'hi world'/ + end + + describe "on variables that shadow methods" do before do - class Foo - def foo(*bars) - :super_wibble + @t = pry_tester.eval unindent(<<-EOS) + class ::TestHost + def hello + hello = proc { ' smile ' } + pry_tester(binding) + end + end + ::TestHost.new.hello + EOS + end + + after do + Object.remove_const(:TestHost) + end + + it "source of variable should take precedence over method that is being shadowed" do + source = @t.eval('show-source hello') + source.should.not =~ /def hello/ + source.should =~ /proc \{ ' smile ' \}/ + end + + it "source of method being shadowed should take precedence over variable + if given self.meth_name syntax" do + @t.eval('show-source self.hello').should =~ /def hello/ + end + end + end + + describe "on variable or constant" do + before do + class TestHost + def hello + "hi there" end end end after do - Object.remove_const(:Foo) + Object.remove_const(:TestHost) end - it "finds super methods with explicit method argument" do - - o = Foo.new - def o.foo(*bars) - :wibble - end - - pry_eval(binding, "show-source --super o.foo").should =~ /:super_wibble/ + it "should output source of its class if variable doesn't respond to source_location" do + test_host = TestHost.new + pry_eval(binding, 'show-source test_host'). + should =~ /class TestHost\n.*def hello/ end - it "finds super methods without explicit method argument" do - o = Foo.new - def o.foo(*bars) - :wibble - pry_eval(binding, 'show-source --super') - end - - o.foo.should =~ /:super_wibble/ - end - - it "finds super methods with multiple --super " do - o = Foo.new - - o.extend Module.new { - def foo - :nibble - end - } - - def o.foo(*bars) - :wibble - pry_eval(binding, 'show-source --super --super') - end - - o.foo.should =~ /:super_wibble/ + it "should output source of its class if constant doesn't respond to source_location" do + TEST_HOST = TestHost.new + pry_eval(binding, 'show-source TEST_HOST'). + should =~ /class TestHost\n.*def hello/ + Object.remove_const(:TEST_HOST) end end - describe "on sourcable objects" do - if RUBY_VERSION =~ /1.9/ - it "should output source defined inside pry" do - pry_tester.tap do |t| - t.eval "hello = proc { puts 'hello world!' }" - t.eval("show-source hello").should =~ /proc \{ puts/ + describe "on modules" do + before do + class ShowSourceTestSuperClass + def alpha + end + end + + class ShowSourceTestClass "bar" do; end - - pry_eval('show-source bar').should =~ /:body_of_foo_bar_regex/ - end - end - - describe "create_command commands" do - it 'should show source for a command' do - @set.create_command "foo", "babble" do - def process() :body_of_foo end - end - pry_eval('show-source foo').should =~ /:body_of_foo/ - end - - it 'should show source for a command defined inside pry' do - pry_eval %{ - _pry_.commands.create_command "foo", "babble" do - def process() :body_of_foo end - end - } pry_eval('show-source foo').should =~ /:body_of_foo/ end + + it "should output source of commands using special characters" do + @set.command "!%$", "I gots the yellow fever" do; end + + pry_eval('show-source !%$').should =~ /yellow fever/ + end + + it 'should show source for a command with spaces in its name' do + @set.command "foo bar", :body_of_foo_bar do; end + + pry_eval('show-source foo bar').should =~ /:body_of_foo_bar/ + end + + it 'should show source for a command by listing name' do + @set.command /foo(.*)/, :body_of_foo_bar_regex, :listing => "bar" do; end + + pry_eval('show-source bar').should =~ /:body_of_foo_bar_regex/ + end end - describe "real class-based commands" do - before do - class ::TemporaryCommand < Pry::ClassCommand - match 'temp-command' - def process() :body_of_temp end - end - - Pry.commands.add_command(::TemporaryCommand) - end - - after do - Object.remove_const(:TemporaryCommand) - end - + describe "create_command commands" do it 'should show source for a command' do - pry_eval('show-source temp-command').should =~ /:body_of_temp/ + @set.create_command "foo", "babble" do + def process() :body_of_foo end + end + pry_eval('show-source foo').should =~ /:body_of_foo/ end it 'should show source for a command defined inside pry' do pry_eval %{ - class ::TemporaryCommandInPry < Pry::ClassCommand - match 'temp-command-in-pry' - def process() :body_of_temp end - end - } - Pry.commands.add_command(::TemporaryCommandInPry) - pry_eval('show-source temp-command-in-pry').should =~ /:body_of_temp/ - Object.remove_const(:TemporaryCommandInPry) - end + _pry_.commands.create_command "foo", "babble" do + def process() :body_of_foo end + end + } + pry_eval('show-source foo').should =~ /:body_of_foo/ end end - describe "should set _file_ and _dir_" do - it 'should set _file_ and _dir_ to file containing method source' do - t = pry_tester - t.process_command "show-source TestClassForShowSource#alpha" - t.pry.last_file.should =~ /show_source_doc_examples/ - t.pry.last_dir.should =~ /fixtures/ + describe "real class-based commands" do + before do + class ::TemporaryCommand < Pry::ClassCommand + match 'temp-command' + def process() :body_of_temp end + end + + Pry.commands.add_command(::TemporaryCommand) + end + + after do + Object.remove_const(:TemporaryCommand) + end + + it 'should show source for a command' do + pry_eval('show-source temp-command').should =~ /:body_of_temp/ + end + + it 'should show source for a command defined inside pry' do + pry_eval %{ + class ::TemporaryCommandInPry < Pry::ClassCommand + match 'temp-command-in-pry' + def process() :body_of_temp end + end + } + Pry.commands.add_command(::TemporaryCommandInPry) + pry_eval('show-source temp-command-in-pry').should =~ /:body_of_temp/ + Object.remove_const(:TemporaryCommandInPry) end end + end - unless Pry::Helpers::BaseHelpers.rbx? - describe "can't find class/module code" do - describe "for classes" do - before do - module Jesus - module Pig - def lillybing; :lillybing; end - end + describe "should set _file_ and _dir_" do + it 'should set _file_ and _dir_ to file containing method source' do + t = pry_tester + t.process_command "show-source TestClassForShowSource#alpha" + t.pry.last_file.should =~ /show_source_doc_examples/ + t.pry.last_dir.should =~ /fixtures/ + end + end - class Brian; end - class Jingle - def a; :doink; end - end - - class Jangle < Jingle; include Pig; end - class Bangle < Jangle; end + unless Pry::Helpers::BaseHelpers.rbx? + describe "can't find class/module code" do + describe "for classes" do + before do + module Jesus + module Pig + def lillybing; :lillybing; end end - end - after do - Object.remove_const(:Jesus) - end + class Brian; end + class Jingle + def a; :doink; end + end - it 'shows superclass code' do - t = pry_tester - t.process_command "show-source Jesus::Jangle" - t.last_output.should =~ /doink/ - end - - it 'ignores included modules' do - t = pry_tester - t.process_command "show-source Jesus::Jangle" - t.last_output.should.not =~ /lillybing/ - end - - it 'errors when class has no superclass to show' do - t = pry_tester - lambda { t.process_command "show-source Jesus::Brian" }.should.raise(Pry::CommandError).message. - should =~ /Couldn't locate/ - end - - it 'shows warning when reverting to superclass code' do - t = pry_tester - t.process_command "show-source Jesus::Jangle" - t.last_output.should =~ /Warning.*?Cannot find.*?Jesus::Jangle.*Showing.*Jesus::Jingle instead/ - end - - it 'shows nth level superclass code (when no intermediary superclasses have code either)' do - t = pry_tester - t.process_command "show-source Jesus::Bangle" - t.last_output.should =~ /doink/ - end - - it 'shows correct warning when reverting to nth level superclass' do - t = pry_tester - t.process_command "show-source Jesus::Bangle" - t.last_output.should =~ /Warning.*?Cannot find.*?Jesus::Bangle.*Showing.*Jesus::Jingle instead/ + class Jangle < Jingle; include Pig; end + class Bangle < Jangle; end end end - describe "for modules" do - before do - module Jesus - module Alpha - def alpha; :alpha; end - end + after do + Object.remove_const(:Jesus) + end - module Zeta; end + it 'shows superclass code' do + t = pry_tester + t.process_command "show-source Jesus::Jangle" + t.last_output.should =~ /doink/ + end - module Beta - include Alpha - end + it 'ignores included modules' do + t = pry_tester + t.process_command "show-source Jesus::Jangle" + t.last_output.should.not =~ /lillybing/ + end - module Gamma - include Beta - end + it 'errors when class has no superclass to show' do + t = pry_tester + lambda { t.process_command "show-source Jesus::Brian" }.should.raise(Pry::CommandError).message. + should =~ /Couldn't locate/ + end + + it 'shows warning when reverting to superclass code' do + t = pry_tester + t.process_command "show-source Jesus::Jangle" + t.last_output.should =~ /Warning.*?Cannot find.*?Jesus::Jangle.*Showing.*Jesus::Jingle instead/ + end + + it 'shows nth level superclass code (when no intermediary superclasses have code either)' do + t = pry_tester + t.process_command "show-source Jesus::Bangle" + t.last_output.should =~ /doink/ + end + + it 'shows correct warning when reverting to nth level superclass' do + t = pry_tester + t.process_command "show-source Jesus::Bangle" + t.last_output.should =~ /Warning.*?Cannot find.*?Jesus::Bangle.*Showing.*Jesus::Jingle instead/ + end + end + + describe "for modules" do + before do + module Jesus + module Alpha + def alpha; :alpha; end + end + + module Zeta; end + + module Beta + include Alpha + end + + module Gamma + include Beta end end + end - after do - Object.remove_const(:Jesus) - end + after do + Object.remove_const(:Jesus) + end - it 'shows included module code' do - t = pry_tester - t.process_command "show-source Jesus::Beta" - t.last_output.should =~ /alpha/ - end + it 'shows included module code' do + t = pry_tester + t.process_command "show-source Jesus::Beta" + t.last_output.should =~ /alpha/ + end - it 'shows warning when reverting to included module code' do - t = pry_tester - t.process_command "show-source Jesus::Beta" - t.last_output.should =~ /Warning.*?Cannot find.*?Jesus::Beta.*Showing.*Jesus::Alpha instead/ - end + it 'shows warning when reverting to included module code' do + t = pry_tester + t.process_command "show-source Jesus::Beta" + t.last_output.should =~ /Warning.*?Cannot find.*?Jesus::Beta.*Showing.*Jesus::Alpha instead/ + end - it 'errors when module has no included module to show' do - t = pry_tester - lambda { t.process_command "show-source Jesus::Zeta" }.should.raise(Pry::CommandError).message. - should =~ /Couldn't locate/ - end + it 'errors when module has no included module to show' do + t = pry_tester + lambda { t.process_command "show-source Jesus::Zeta" }.should.raise(Pry::CommandError).message. + should =~ /Couldn't locate/ + end - it 'shows nth level included module code (when no intermediary modules have code either)' do - t = pry_tester - t.process_command "show-source Jesus::Gamma" - t.last_output.should =~ /alpha/ - end + it 'shows nth level included module code (when no intermediary modules have code either)' do + t = pry_tester + t.process_command "show-source Jesus::Gamma" + t.last_output.should =~ /alpha/ + end - it 'shows correct warning when reverting to nth level included module' do - t = pry_tester - t.process_command "show-source Jesus::Gamma" - t.last_output.should =~ /Warning.*?Cannot find.*?Jesus::Gamma.*Showing.*Jesus::Alpha instead/ - end + it 'shows correct warning when reverting to nth level included module' do + t = pry_tester + t.process_command "show-source Jesus::Gamma" + t.last_output.should =~ /Warning.*?Cannot find.*?Jesus::Gamma.*Showing.*Jesus::Alpha instead/ end end end diff --git a/spec/commands/whereami_spec.rb b/spec/commands/whereami_spec.rb index 65bd8321..f75291a8 100644 --- a/spec/commands/whereami_spec.rb +++ b/spec/commands/whereami_spec.rb @@ -41,16 +41,14 @@ describe "whereami" do Object.remove_const(:Cor) end - if defined?(BasicObject) - it 'should work in BasicObjects' do - cor = Class.new(BasicObject) do - def blimey! - ::Kernel.binding # omnom - end - end.new.blimey! + it 'should work in BasicObjects' do + cor = Class.new(BasicObject) do + def blimey! + ::Kernel.binding # omnom + end + end.new.blimey! - pry_eval(cor, 'whereami').should =~ /::Kernel.binding [#] omnom/ - end + pry_eval(cor, 'whereami').should =~ /::Kernel.binding [#] omnom/ end it 'should show description and correct code when __LINE__ and __FILE__ are outside @method.source_location' do diff --git a/spec/method_spec.rb b/spec/method_spec.rb index 304c6feb..de902a03 100644 --- a/spec/method_spec.rb +++ b/spec/method_spec.rb @@ -144,15 +144,13 @@ describe Pry::Method do m.name.should == "gag" end - if defined?(BasicObject) && !Pry::Helpers::BaseHelpers.rbx? # rubinius issue 1921 - it "should find the right method from a BasicObject" do - a = Class.new(BasicObject) { def gag; ::Kernel.binding; end; def self.line; __LINE__; end } + it "should find the right method from a BasicObject" do + a = Class.new(BasicObject) { def gag; ::Kernel.binding; end; def self.line; __LINE__; end } - m = Pry::Method.from_binding(a.new.gag) - m.owner.should == a - m.source_file.should == __FILE__ - m.source_line.should == a.line - end + m = Pry::Method.from_binding(a.new.gag) + m.owner.should == a + m.source_file.should == __FILE__ + m.source_line.should == a.line end it 'should find the right method even if it was renamed and replaced' do @@ -433,8 +431,8 @@ describe Pry::Method do it "should include the Pry::Method.instance_resolution_order of Class after the singleton classes" do Pry::Method.resolution_order(LS::Top).should == - [singleton_class(LS::Top), singleton_class(Object), (defined? BasicObject) && singleton_class(BasicObject)].compact + - Pry::Method.instance_resolution_order(Class) + [singleton_class(LS::Top), singleton_class(Object), singleton_class(BasicObject), + *Pry::Method.instance_resolution_order(Class)] end end end @@ -496,15 +494,11 @@ describe Pry::Method do end end - unless Pry::Helpers::BaseHelpers.mri_18? - # Ruby 1.8 doesn't support this feature. - it 'should be able to find aliases for methods implemented in C' do - meth = Pry::Method(Hash.new.method(:key?)) - aliases = Set.new(meth.aliases) + it 'should be able to find aliases for methods implemented in C' do + meth = Pry::Method(Hash.new.method(:key?)) + aliases = Set.new(meth.aliases) - aliases.should == Set.new(["include?", "member?", "has_key?"]) - end + aliases.should == Set.new(["include?", "member?", "has_key?"]) end - end end diff --git a/spec/pry_spec.rb b/spec/pry_spec.rb index 8331619d..79eecc52 100644 --- a/spec/pry_spec.rb +++ b/spec/pry_spec.rb @@ -5,15 +5,11 @@ describe Pry do @str_output = StringIO.new end - if RUBY_VERSION =~ /1.9/ - describe "Exotic object support" do - # regression test for exotic object support - it "Should not error when return value is a BasicObject instance" do - - ReplTester.start do - input('BasicObject.new').should =~ /^=> # # @context, :output => out = StringIO.new - out.string.should =~ /roken is dodelijk/ - end + # This is a regression test as 0.9.11 broke this behaviour + it 'can perform a show-source' do + Pry.run_command "show-source drum", :context => @context, :output => out = StringIO.new + out.string.should =~ /roken is dodelijk/ end end From add29398f0e96e63c3dc6c9a66997821809a1cf0 Mon Sep 17 00:00:00 2001 From: Ryan Fitzgerald Date: Wed, 23 Oct 2013 23:22:42 -0700 Subject: [PATCH 2/4] Fix failing jruby spec --- spec/pry_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/pry_spec.rb b/spec/pry_spec.rb index 79eecc52..b12a0423 100644 --- a/spec/pry_spec.rb +++ b/spec/pry_spec.rb @@ -319,7 +319,8 @@ describe Pry do end it 'should define a method on the class of an object when performing "def meth;end" inside an immediate value or Numeric' do - [:test, 0, true, false, nil, 0.0].each do |val| + [:test, 0, true, false, nil, + (0.0 unless Pry::Helpers::BaseHelpers.jruby?)].each do |val| pry_eval(val, "def hello; end"); val.class.instance_methods(false).map(&:to_sym).include?(:hello).should == true end From 4aed2ab1c0ab8f347360f963da2807d869f8f5c6 Mon Sep 17 00:00:00 2001 From: Ryan Fitzgerald Date: Sun, 19 Jan 2014 18:00:25 -0800 Subject: [PATCH 3/4] Fix default inspect for Ruby 2.1 In Ruby 2.1, the ancestor list of a singleton class includes the singleton as the first element, so we need to filter it out. --- lib/pry/color_printer.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/pry/color_printer.rb b/lib/pry/color_printer.rb index 5f804fd1..39d9a9ae 100644 --- a/lib/pry/color_printer.rb +++ b/lib/pry/color_printer.rb @@ -37,8 +37,9 @@ class Pry # Read the class name off of the singleton class to provide a default # inspect. - eig = class << obj; self; end - klass = Pry::Method.safe_send(eig, :ancestors).first + singleton = class << obj; self; end + ancestors = Pry::Method.safe_send(singleton, :ancestors) + klass = ancestors.reject { |k| k == singleton }.first obj_id = obj.__id__.to_s(16) rescue 0 str = "#<#{klass}:0x#{obj_id}>" From b39ba9725b9d720b1f2fd042c0a9912881d69735 Mon Sep 17 00:00:00 2001 From: Ryan Fitzgerald Date: Sun, 19 Jan 2014 20:48:31 -0800 Subject: [PATCH 4/4] Disable spec to work around rubinius/rubinius#2871 --- spec/method_spec.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/spec/method_spec.rb b/spec/method_spec.rb index de902a03..0c49d104 100644 --- a/spec/method_spec.rb +++ b/spec/method_spec.rb @@ -144,13 +144,16 @@ describe Pry::Method do m.name.should == "gag" end - it "should find the right method from a BasicObject" do - a = Class.new(BasicObject) { def gag; ::Kernel.binding; end; def self.line; __LINE__; end } + # Temporarily disabled to work around rubinius/rubinius#2871. + unless Pry::Helpers::BaseHelpers.rbx? + it "should find the right method from a BasicObject" do + a = Class.new(BasicObject) { def gag; ::Kernel.binding; end; def self.line; __LINE__; end } - m = Pry::Method.from_binding(a.new.gag) - m.owner.should == a - m.source_file.should == __FILE__ - m.source_line.should == a.line + m = Pry::Method.from_binding(a.new.gag) + m.owner.should == a + m.source_file.should == __FILE__ + m.source_line.should == a.line + end end it 'should find the right method even if it was renamed and replaced' do