require 'helper' require "fixtures/show_source_doc_examples" 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 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 Object.remove_const(:Foo) 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/ 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/ end end 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 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 @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(:TestHost) end 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 "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 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 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 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 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 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 class Brian; end class Jingle def a; :doink; end end class Jangle < Jingle; include Pig; end class Bangle < Jangle; end end end after do Object.remove_const(:Jesus) 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/ 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 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 '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 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 end end