pry 0.10.2-i386-mswin32 → 1.0.0.pre1-i386-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (189) hide show
  1. data/.document +2 -0
  2. data/.gitignore +16 -0
  3. data/.travis.yml +21 -0
  4. data/.yardopts +3 -0
  5. data/CHANGELOG +503 -0
  6. data/CONTRIBUTORS +55 -0
  7. data/Gemfile +9 -0
  8. data/Guardfile +62 -0
  9. data/LICENSE +2 -2
  10. data/{README.md → README.markdown} +31 -37
  11. data/Rakefile +144 -0
  12. data/TODO +117 -0
  13. data/lib/pry.rb +146 -33
  14. data/lib/pry/cli.rb +13 -35
  15. data/lib/pry/code.rb +63 -24
  16. data/lib/pry/code/loc.rb +2 -2
  17. data/lib/pry/code_object.rb +21 -40
  18. data/lib/pry/command.rb +6 -9
  19. data/lib/pry/command_set.rb +37 -80
  20. data/lib/pry/commands.rb +1 -1
  21. data/lib/pry/commands/amend_line.rb +1 -1
  22. data/lib/pry/commands/bang.rb +1 -1
  23. data/lib/pry/commands/cat.rb +2 -11
  24. data/lib/pry/commands/cat/abstract_formatter.rb +1 -1
  25. data/lib/pry/commands/cat/exception_formatter.rb +7 -6
  26. data/lib/pry/commands/cat/file_formatter.rb +32 -15
  27. data/lib/pry/commands/cat/input_expression_formatter.rb +1 -1
  28. data/lib/pry/commands/cd.rb +3 -14
  29. data/lib/pry/commands/code_collector.rb +4 -4
  30. data/lib/pry/commands/easter_eggs.rb +3 -3
  31. data/lib/pry/commands/edit.rb +22 -10
  32. data/lib/pry/commands/edit/exception_patcher.rb +1 -1
  33. data/lib/pry/commands/edit/file_and_line_locator.rb +2 -0
  34. data/lib/pry/{method/patcher.rb → commands/edit/method_patcher.rb} +37 -40
  35. data/lib/pry/commands/find_method.rb +22 -16
  36. data/lib/pry/commands/gem_install.rb +2 -5
  37. data/lib/pry/commands/gem_open.rb +1 -1
  38. data/lib/pry/commands/gist.rb +11 -10
  39. data/lib/pry/commands/help.rb +14 -14
  40. data/lib/pry/commands/hist.rb +5 -24
  41. data/lib/pry/commands/ls.rb +287 -56
  42. data/lib/pry/commands/play.rb +10 -44
  43. data/lib/pry/commands/pry_backtrace.rb +2 -1
  44. data/lib/pry/commands/raise_up.rb +1 -1
  45. data/lib/pry/commands/reload_code.rb +15 -31
  46. data/lib/pry/commands/ri.rb +3 -7
  47. data/lib/pry/commands/shell_command.rb +12 -17
  48. data/lib/pry/commands/shell_mode.rb +2 -2
  49. data/lib/pry/commands/show_doc.rb +0 -5
  50. data/lib/pry/commands/show_info.rb +10 -11
  51. data/lib/pry/commands/show_source.rb +3 -15
  52. data/lib/pry/commands/simple_prompt.rb +1 -1
  53. data/lib/pry/commands/toggle_color.rb +4 -8
  54. data/lib/pry/commands/whereami.rb +10 -18
  55. data/lib/pry/completion.rb +293 -0
  56. data/lib/pry/config.rb +233 -20
  57. data/lib/pry/core_extensions.rb +19 -29
  58. data/lib/pry/custom_completions.rb +6 -0
  59. data/lib/pry/editor.rb +103 -109
  60. data/lib/pry/helpers/base_helpers.rb +109 -22
  61. data/lib/pry/helpers/command_helpers.rb +8 -10
  62. data/lib/pry/helpers/documentation_helpers.rb +2 -1
  63. data/lib/pry/helpers/text.rb +5 -4
  64. data/lib/pry/history.rb +10 -21
  65. data/lib/pry/history_array.rb +0 -5
  66. data/lib/pry/hooks.rb +29 -9
  67. data/lib/pry/indent.rb +10 -5
  68. data/lib/pry/method.rb +86 -81
  69. data/lib/pry/method/weird_method_locator.rb +2 -4
  70. data/lib/pry/module_candidate.rb +14 -5
  71. data/lib/pry/pager.rb +48 -193
  72. data/lib/pry/plugins.rb +2 -2
  73. data/lib/pry/pry_class.rb +193 -104
  74. data/lib/pry/pry_instance.rb +154 -152
  75. data/lib/pry/rbx_method.rb +13 -0
  76. data/lib/pry/rbx_path.rb +1 -1
  77. data/lib/pry/repl.rb +14 -17
  78. data/lib/pry/repl_file_loader.rb +3 -8
  79. data/lib/pry/rubygem.rb +3 -3
  80. data/lib/pry/terminal.rb +3 -4
  81. data/lib/pry/test/helper.rb +11 -6
  82. data/lib/pry/version.rb +1 -1
  83. data/lib/pry/wrapped_module.rb +56 -49
  84. data/man/pry.1 +195 -0
  85. data/man/pry.1.html +204 -0
  86. data/man/pry.1.ronn +141 -0
  87. data/pry.gemspec +31 -0
  88. data/spec/Procfile +3 -0
  89. data/spec/cli_spec.rb +78 -0
  90. data/spec/code_object_spec.rb +277 -0
  91. data/spec/code_spec.rb +219 -0
  92. data/spec/command_helpers_spec.rb +29 -0
  93. data/spec/command_integration_spec.rb +562 -0
  94. data/spec/command_set_spec.rb +627 -0
  95. data/spec/command_spec.rb +821 -0
  96. data/spec/commands/amend_line_spec.rb +247 -0
  97. data/spec/commands/bang_spec.rb +18 -0
  98. data/spec/commands/cat_spec.rb +164 -0
  99. data/spec/commands/cd_spec.rb +250 -0
  100. data/spec/commands/disable_pry_spec.rb +25 -0
  101. data/spec/commands/edit_spec.rb +725 -0
  102. data/spec/commands/exit_all_spec.rb +27 -0
  103. data/spec/commands/exit_program_spec.rb +19 -0
  104. data/spec/commands/exit_spec.rb +28 -0
  105. data/spec/commands/find_method_spec.rb +70 -0
  106. data/spec/commands/gem_list_spec.rb +26 -0
  107. data/spec/commands/gist_spec.rb +79 -0
  108. data/spec/commands/help_spec.rb +56 -0
  109. data/spec/commands/hist_spec.rb +172 -0
  110. data/spec/commands/jump_to_spec.rb +15 -0
  111. data/spec/commands/ls_spec.rb +189 -0
  112. data/spec/commands/play_spec.rb +136 -0
  113. data/spec/commands/raise_up_spec.rb +56 -0
  114. data/spec/commands/save_file_spec.rb +177 -0
  115. data/spec/commands/show_doc_spec.rb +488 -0
  116. data/spec/commands/show_input_spec.rb +17 -0
  117. data/spec/commands/show_source_spec.rb +760 -0
  118. data/spec/commands/whereami_spec.rb +203 -0
  119. data/spec/completion_spec.rb +221 -0
  120. data/spec/control_d_handler_spec.rb +62 -0
  121. data/spec/documentation_helper_spec.rb +73 -0
  122. data/spec/editor_spec.rb +79 -0
  123. data/spec/exception_whitelist_spec.rb +21 -0
  124. data/spec/fixtures/candidate_helper1.rb +11 -0
  125. data/spec/fixtures/candidate_helper2.rb +8 -0
  126. data/spec/fixtures/example.erb +5 -0
  127. data/spec/fixtures/example_nesting.rb +33 -0
  128. data/spec/fixtures/show_source_doc_examples.rb +15 -0
  129. data/spec/fixtures/testlinkrc +2 -0
  130. data/spec/fixtures/testrc +2 -0
  131. data/spec/fixtures/testrcbad +2 -0
  132. data/spec/fixtures/whereami_helper.rb +6 -0
  133. data/spec/helper.rb +35 -0
  134. data/spec/helpers/bacon.rb +86 -0
  135. data/spec/helpers/mock_pry.rb +44 -0
  136. data/spec/helpers/repl_tester.rb +112 -0
  137. data/spec/helpers/table_spec.rb +105 -0
  138. data/spec/history_array_spec.rb +67 -0
  139. data/spec/hooks_spec.rb +522 -0
  140. data/spec/indent_spec.rb +301 -0
  141. data/spec/method_spec.rb +482 -0
  142. data/spec/prompt_spec.rb +61 -0
  143. data/spec/pry_defaults_spec.rb +420 -0
  144. data/spec/pry_history_spec.rb +69 -0
  145. data/spec/pry_output_spec.rb +95 -0
  146. data/spec/pry_repl_spec.rb +86 -0
  147. data/spec/pry_spec.rb +394 -0
  148. data/spec/pryrc_spec.rb +97 -0
  149. data/spec/run_command_spec.rb +25 -0
  150. data/spec/sticky_locals_spec.rb +147 -0
  151. data/spec/syntax_checking_spec.rb +81 -0
  152. data/spec/wrapped_module_spec.rb +261 -0
  153. data/wiki/Customizing-pry.md +397 -0
  154. data/wiki/Home.md +4 -0
  155. metadata +272 -61
  156. checksums.yaml +0 -7
  157. data/CHANGELOG.md +0 -714
  158. data/lib/pry/code/code_file.rb +0 -103
  159. data/lib/pry/color_printer.rb +0 -55
  160. data/lib/pry/commands/change_inspector.rb +0 -27
  161. data/lib/pry/commands/change_prompt.rb +0 -26
  162. data/lib/pry/commands/list_inspectors.rb +0 -35
  163. data/lib/pry/commands/list_prompts.rb +0 -35
  164. data/lib/pry/commands/ls/constants.rb +0 -47
  165. data/lib/pry/commands/ls/formatter.rb +0 -49
  166. data/lib/pry/commands/ls/globals.rb +0 -48
  167. data/lib/pry/commands/ls/grep.rb +0 -21
  168. data/lib/pry/commands/ls/instance_vars.rb +0 -39
  169. data/lib/pry/commands/ls/interrogatable.rb +0 -18
  170. data/lib/pry/commands/ls/jruby_hacks.rb +0 -49
  171. data/lib/pry/commands/ls/local_names.rb +0 -35
  172. data/lib/pry/commands/ls/local_vars.rb +0 -39
  173. data/lib/pry/commands/ls/ls_entity.rb +0 -70
  174. data/lib/pry/commands/ls/methods.rb +0 -57
  175. data/lib/pry/commands/ls/methods_helper.rb +0 -46
  176. data/lib/pry/commands/ls/self_methods.rb +0 -32
  177. data/lib/pry/commands/watch_expression.rb +0 -105
  178. data/lib/pry/commands/watch_expression/expression.rb +0 -38
  179. data/lib/pry/config/behavior.rb +0 -139
  180. data/lib/pry/config/convenience.rb +0 -25
  181. data/lib/pry/config/default.rb +0 -161
  182. data/lib/pry/exceptions.rb +0 -78
  183. data/lib/pry/input_completer.rb +0 -242
  184. data/lib/pry/input_lock.rb +0 -132
  185. data/lib/pry/inspector.rb +0 -27
  186. data/lib/pry/last_exception.rb +0 -61
  187. data/lib/pry/object_path.rb +0 -82
  188. data/lib/pry/output.rb +0 -50
  189. data/lib/pry/prompt.rb +0 -26
@@ -0,0 +1,301 @@
1
+ require 'helper'
2
+
3
+ # Please keep in mind that any hash signs ("#") in the heredoc strings are
4
+ # placed on purpose. Without these editors might remove the whitespace on empty
5
+ # lines.
6
+ describe Pry::Indent do
7
+ before do
8
+ @indent = Pry::Indent.new
9
+ end
10
+
11
+ it 'should indent an array' do
12
+ input = "array = [\n10,\n15\n]"
13
+ output = "array = [\n 10,\n 15\n]"
14
+
15
+ @indent.indent(input).should == output
16
+ end
17
+
18
+ it 'should indent a hash' do
19
+ input = "hash = {\n:name => 'Ruby'\n}"
20
+ output = "hash = {\n :name => 'Ruby'\n}"
21
+
22
+ @indent.indent(input).should == output
23
+ end
24
+
25
+ it 'should indent a function' do
26
+ input = "def\nreturn 10\nend"
27
+ output = "def\n return 10\nend"
28
+
29
+ @indent.indent(input).should == output
30
+ end
31
+
32
+ it 'should indent a module and class' do
33
+ input = "module Foo\n# Hello world\nend"
34
+ output = "module Foo\n # Hello world\nend"
35
+ input_class = "class Foo\n# Hello world\nend"
36
+ output_class = "class Foo\n # Hello world\nend"
37
+
38
+ @indent.indent(input).should == output
39
+ @indent.indent(input_class).should == output_class
40
+ end
41
+
42
+ it 'should indent separate lines' do
43
+ @indent.indent('def foo').should == 'def foo'
44
+ @indent.indent('return 10').should == ' return 10'
45
+ @indent.indent('end').should == 'end'
46
+ end
47
+
48
+ it 'should not indent single line statements' do
49
+ input = <<TXT.strip
50
+ def hello; end
51
+ puts "Hello"
52
+ TXT
53
+
54
+ @indent.indent(input).should == input
55
+ end
56
+
57
+ it 'should handle multiple open and closing tokens on a line' do
58
+ input = <<TXT.strip
59
+ [10, 15].each do |num|
60
+ puts num
61
+ end
62
+ TXT
63
+
64
+ output = <<TXT.strip
65
+ [10, 15].each do |num|
66
+ puts num
67
+ end
68
+ TXT
69
+
70
+ @indent.indent(input).should == output
71
+ end
72
+
73
+ it 'should properly indent nested code' do
74
+ input = <<TXT.strip
75
+ module A
76
+ module B
77
+ class C
78
+ attr_accessor :test
79
+ # keep
80
+ def number
81
+ return 10
82
+ end
83
+ end
84
+ end
85
+ end
86
+ TXT
87
+
88
+ output = <<TXT.strip
89
+ module A
90
+ module B
91
+ class C
92
+ attr_accessor :test
93
+ # keep
94
+ def number
95
+ return 10
96
+ end
97
+ end
98
+ end
99
+ end
100
+ TXT
101
+
102
+ @indent.indent(input).should == output
103
+ end
104
+
105
+ it 'should indent statements such as if, else, etc' do
106
+ input = <<TXT.strip
107
+ if a == 10
108
+ #
109
+ elsif a == 15
110
+ #
111
+ else
112
+ #
113
+ end
114
+ #
115
+ while true
116
+ #
117
+ end
118
+ #
119
+ for num in [10, 15, 20]
120
+ #
121
+ end
122
+ #
123
+ for num in [10, 15, 20] do
124
+ #
125
+ end
126
+ TXT
127
+
128
+ output = <<TXT.strip
129
+ if a == 10
130
+ #
131
+ elsif a == 15
132
+ #
133
+ else
134
+ #
135
+ end
136
+ #
137
+ while true
138
+ #
139
+ end
140
+ #
141
+ for num in [10, 15, 20]
142
+ #
143
+ end
144
+ #
145
+ for num in [10, 15, 20] do
146
+ #
147
+ end
148
+ TXT
149
+
150
+ @indent.indent(input).should == output
151
+ end
152
+
153
+ it "should correctly handle while <foo> do" do
154
+ input = "while 5 do\n5\nend"
155
+ @indent.indent(input).should == "while 5 do\n 5\nend"
156
+ end
157
+
158
+ it "should ident case statements" do
159
+ input = <<TXT.strip
160
+ case foo
161
+ when 1
162
+ 2
163
+ when 2
164
+ if 3
165
+ 4
166
+ end
167
+ when 5
168
+ #
169
+ else
170
+ #
171
+ end
172
+ TXT
173
+
174
+ output = <<TXT.strip
175
+ case foo
176
+ when 1
177
+ 2
178
+ when 2
179
+ if 3
180
+ 4
181
+ end
182
+ when 5
183
+ #
184
+ else
185
+ #
186
+ end
187
+ TXT
188
+
189
+ @indent.indent(input).should == output
190
+ end
191
+
192
+ it "should indent correctly with nesting" do
193
+ @indent.indent("[[\n[]]\n]").should == "[[\n []]\n]"
194
+ @indent.reset.indent("[[\n[]]\n]").should == "[[\n []]\n]"
195
+ @indent.reset.indent("[[{\n[] =>\n[]}]\n]").should == "[[{\n [] =>\n []}]\n]"
196
+ end
197
+
198
+ it "should not indent single-line ifs" do
199
+ @indent.indent("foo if bar\n#").should == "foo if bar\n#"
200
+ @indent.reset.indent("foo() if bar\n#").should == "foo() if bar\n#"
201
+ @indent.reset.indent("foo 'hi' if bar\n#").should == "foo 'hi' if bar\n#"
202
+ @indent.reset.indent("foo 1 while bar\n#").should == "foo 1 while bar\n#"
203
+ @indent.reset.indent("super if true\n#").should == "super if true\n#"
204
+ @indent.reset.indent("true if false\n#").should == "true if false\n#"
205
+ @indent.reset.indent("String if false\n#").should == "String if false\n#"
206
+ end
207
+
208
+ it "should indent cunningly disguised ifs" do
209
+ @indent.indent("{1 => if bar\n#").should == "{1 => if bar\n #"
210
+ @indent.reset.indent("foo(if bar\n#").should == "foo(if bar\n #"
211
+ @indent.reset.indent("bar(baz, if bar\n#").should == "bar(baz, if bar\n #"
212
+ @indent.reset.indent("[if bar\n#").should == "[if bar\n #"
213
+ @indent.reset.indent("true; while bar\n#").should == "true; while bar\n #"
214
+ end
215
+
216
+ it "should differentiate single/multi-line unless" do
217
+ @indent.indent("foo unless bar\nunless foo\nbar\nend").should == "foo unless bar\nunless foo\n bar\nend"
218
+ end
219
+
220
+ it "should not indent single/multi-line until" do
221
+ @indent.indent("%w{baz} until bar\nuntil foo\nbar\nend").should == "%w{baz} until bar\nuntil foo\n bar\nend"
222
+ end
223
+
224
+ it "should indent begin rescue end" do
225
+ input = <<INPUT.strip
226
+ begin
227
+ doo :something => :wrong
228
+ rescue => e
229
+ doit :right
230
+ end
231
+ INPUT
232
+ output = <<OUTPUT.strip
233
+ begin
234
+ doo :something => :wrong
235
+ rescue => e
236
+ doit :right
237
+ end
238
+ OUTPUT
239
+
240
+ @indent.indent(input).should == output
241
+ end
242
+
243
+ it "should not indent inside strings" do
244
+ @indent.indent(%(def a\n"foo\nbar"\n end)).should == %(def a\n "foo\nbar"\nend)
245
+ @indent.indent(%(def a\nputs %w(foo\nbar), 'foo\nbar'\n end)).should == %(def a\n puts %w(foo\nbar), 'foo\nbar'\nend)
246
+ end
247
+
248
+ it "should not indent inside HEREDOCs" do
249
+ @indent.indent(%(def a\nputs <<FOO\n bar\nFOO\nbaz\nend)).should == %(def a\n puts <<FOO\n bar\nFOO\n baz\nend)
250
+ @indent.indent(%(def a\nputs <<-'^^'\n bar\n\t^^\nbaz\nend)).should == %(def a\n puts <<-'^^'\n bar\n\t^^\n baz\nend)
251
+ end
252
+
253
+ it "should not indent nested HEREDOCs" do
254
+ input = <<INPUT.strip
255
+ def a
256
+ puts <<FOO, <<-BAR, "baz", <<-':p'
257
+ foo
258
+ FOO
259
+ bar
260
+ BAR
261
+ tongue
262
+ :p
263
+ puts :p
264
+ end
265
+ INPUT
266
+
267
+ output = <<OUTPUT.strip
268
+ def a
269
+ puts <<FOO, <<-BAR, "baz", <<-':p'
270
+ foo
271
+ FOO
272
+ bar
273
+ BAR
274
+ tongue
275
+ :p
276
+ puts :p
277
+ end
278
+ OUTPUT
279
+
280
+ @indent.indent(input).should == output
281
+ end
282
+
283
+ describe "nesting" do
284
+ test = File.read("spec/fixtures/example_nesting.rb")
285
+
286
+ test.lines.each_with_index do |line, i|
287
+ result = line.split("#").last.strip
288
+ if result == ""
289
+ it "should fail to parse nesting on line #{i + 1} of example_nesting.rb" do
290
+ lambda {
291
+ Pry::Indent.nesting_at(test, i + 1)
292
+ }.should.raise(Pry::Indent::UnparseableNestingError)
293
+ end
294
+ else
295
+ it "should parse nesting on line #{i + 1} of example_nesting.rb" do
296
+ Pry::Indent.nesting_at(test, i + 1).should == eval(result)
297
+ end
298
+ end
299
+ end
300
+ end
301
+ end
@@ -0,0 +1,482 @@
1
+ require 'helper'
2
+ require 'set'
3
+
4
+ describe Pry::Method do
5
+ it "should use String names for compatibility" do
6
+ klass = Class.new { def hello; end }
7
+ Pry::Method.new(klass.instance_method(:hello)).name.should == "hello"
8
+ end
9
+
10
+ describe ".from_str" do
11
+ it 'should look up instance methods if no methods available and no options provided' do
12
+ klass = Class.new { def hello; end }
13
+ meth = Pry::Method.from_str(:hello, Pry.binding_for(klass))
14
+ meth.should == klass.instance_method(:hello)
15
+ end
16
+
17
+ it 'should look up methods if no instance methods available and no options provided' do
18
+ klass = Class.new { def self.hello; end }
19
+ meth = Pry::Method.from_str(:hello, Pry.binding_for(klass))
20
+ meth.should == klass.method(:hello)
21
+ end
22
+
23
+ it 'should look up instance methods first even if methods available and no options provided' do
24
+ klass = Class.new { def hello; end; def self.hello; end }
25
+ meth = Pry::Method.from_str(:hello, Pry.binding_for(klass))
26
+ meth.should == klass.instance_method(:hello)
27
+ end
28
+
29
+ it 'should look up instance methods if "instance-methods" option provided' do
30
+ klass = Class.new { def hello; end; def self.hello; end }
31
+ meth = Pry::Method.from_str(:hello, Pry.binding_for(klass), {"instance-methods" => true})
32
+ meth.should == klass.instance_method(:hello)
33
+ end
34
+
35
+ it 'should look up methods if :methods option provided' do
36
+ klass = Class.new { def hello; end; def self.hello; end }
37
+ meth = Pry::Method.from_str(:hello, Pry.binding_for(klass), {:methods => true})
38
+ meth.should == klass.method(:hello)
39
+ end
40
+
41
+ it 'should look up instance methods using the Class#method syntax' do
42
+ klass = Class.new { def hello; end; def self.hello; end }
43
+ meth = Pry::Method.from_str("klass#hello", Pry.binding_for(binding))
44
+ meth.should == klass.instance_method(:hello)
45
+ end
46
+
47
+ it 'should look up methods using the object.method syntax' do
48
+ klass = Class.new { def hello; end; def self.hello; end }
49
+ meth = Pry::Method.from_str("klass.hello", Pry.binding_for(binding))
50
+ meth.should == klass.method(:hello)
51
+ end
52
+
53
+ it 'should NOT look up instance methods using the Class#method syntax if no instance methods defined' do
54
+ klass = Class.new { def self.hello; end }
55
+ meth = Pry::Method.from_str("klass#hello", Pry.binding_for(binding))
56
+ meth.should == nil
57
+ end
58
+
59
+ it 'should NOT look up methods using the object.method syntax if no methods defined' do
60
+ klass = Class.new { def hello; end }
61
+ meth = Pry::Method.from_str("klass.hello", Pry.binding_for(binding))
62
+ meth.should == nil
63
+ end
64
+
65
+ it 'should look up methods using klass.new.method syntax' do
66
+ klass = Class.new { def hello; :hello; end }
67
+ meth = Pry::Method.from_str("klass.new.hello", Pry.binding_for(binding))
68
+ meth.name.should == "hello"
69
+ end
70
+
71
+ it 'should look up instance methods using klass.meth#method syntax' do
72
+ klass = Class.new { def self.meth; Class.new; end }
73
+ meth = Pry::Method.from_str("klass.meth#initialize", Pry.binding_for(binding))
74
+ meth.name.should == "initialize"
75
+ end
76
+
77
+ it 'should look up methods using instance::bar syntax' do
78
+ klass = Class.new{ def self.meth; Class.new; end }
79
+ meth = Pry::Method.from_str("klass::meth", Pry.binding_for(binding))
80
+ meth.name.should == "meth"
81
+ end
82
+
83
+ it 'should not raise an exception if receiver does not exist' do
84
+ lambda { Pry::Method.from_str("random_klass.meth", Pry.binding_for(binding)) }.should.not.raise
85
+ end
86
+ end
87
+
88
+ describe '.from_binding' do
89
+ it 'should be able to pick a method out of a binding' do
90
+ Pry::Method.from_binding(Class.new{ def self.foo; binding; end }.foo).name.should == "foo"
91
+ end
92
+
93
+ it 'should NOT find a method from the toplevel binding' do
94
+ Pry::Method.from_binding(TOPLEVEL_BINDING).should == nil
95
+ end
96
+
97
+ it "should find methods that have been undef'd" do
98
+ c = Class.new do
99
+ def self.bar
100
+ class << self; undef bar; end
101
+ binding
102
+ end
103
+ end
104
+
105
+ m = Pry::Method.from_binding(c.bar)
106
+ m.name.should == "bar"
107
+ end
108
+
109
+ # Our source_location trick doesn't work, due to https://github.com/rubinius/rubinius/issues/953
110
+ unless Pry::Helpers::BaseHelpers.rbx?
111
+ it 'should find the super method correctly' do
112
+ a = Class.new{ def gag33; binding; end; def self.line; __LINE__; end }
113
+ b = Class.new(a){ def gag33; super; end }
114
+
115
+ g = b.new.gag33
116
+ m = Pry::Method.from_binding(g)
117
+
118
+ m.owner.should == a
119
+ m.source_line.should == a.line
120
+ m.name.should == "gag33"
121
+ end
122
+ end
123
+
124
+ it 'should find the right method if a super method exists' do
125
+ a = Class.new{ def gag; binding; end; }
126
+ b = Class.new(a){ def gag; super; binding; end; def self.line; __LINE__; end }
127
+
128
+ m = Pry::Method.from_binding(b.new.gag)
129
+
130
+ m.owner.should == b
131
+ m.source_line.should == b.line
132
+ m.name.should == "gag"
133
+ end
134
+
135
+ if defined?(BasicObject) && !Pry::Helpers::BaseHelpers.rbx? # rubinius issue 1921
136
+ it "should find the right method from a BasicObject" do
137
+ a = Class.new(BasicObject) { def gag; ::Kernel.binding; end; def self.line; __LINE__; end }
138
+
139
+ m = Pry::Method.from_binding(a.new.gag)
140
+ m.owner.should == a
141
+ m.source_file.should == __FILE__
142
+ m.source_line.should == a.line
143
+ end
144
+ end
145
+
146
+ it 'should find the right method even if it was renamed and replaced' do
147
+ o = Object.new
148
+ class << o
149
+ def borscht
150
+ "nips"
151
+ binding
152
+ end
153
+ alias paella borscht
154
+ def borscht() paella end
155
+ end
156
+
157
+ m = Pry::Method.from_binding(o.borscht)
158
+ m.source.should == Pry::Method(o.method(:paella)).source
159
+ end
160
+ end
161
+
162
+ describe 'super' do
163
+ it 'should be able to find the super method on a bound method' do
164
+ a = Class.new{ def rar; 4; end }
165
+ b = Class.new(a){ def rar; super; end }
166
+
167
+ obj = b.new
168
+
169
+ zuper = Pry::Method(obj.method(:rar)).super
170
+ zuper.owner.should == a
171
+ zuper.receiver.should == obj
172
+ end
173
+
174
+ it 'should be able to find the super method of an unbound method' do
175
+ a = Class.new{ def rar; 4; end }
176
+ b = Class.new(a){ def rar; super; end }
177
+
178
+ zuper = Pry::Method(b.instance_method(:rar)).super
179
+ zuper.owner.should == a
180
+ end
181
+
182
+ it 'should return nil if no super method exists' do
183
+ a = Class.new{ def rar; super; end }
184
+
185
+ Pry::Method(a.instance_method(:rar)).super.should == nil
186
+ end
187
+
188
+ it 'should be able to find super methods defined on modules' do
189
+ m = Module.new{ def rar; 4; end }
190
+ a = Class.new{ def rar; super; end; include m }
191
+
192
+ zuper = Pry::Method(a.new.method(:rar)).super
193
+ zuper.owner.should == m
194
+ end
195
+
196
+ it 'should be able to find super methods defined on super-classes when there are modules in the way' do
197
+ a = Class.new{ def rar; 4; end }
198
+ m = Module.new{ def mooo; 4; end }
199
+ b = Class.new(a){ def rar; super; end; include m }
200
+
201
+ zuper = Pry::Method(b.new.method(:rar)).super
202
+ zuper.owner.should == a
203
+ end
204
+
205
+ it 'should be able to jump up multiple levels of bound method, even through modules' do
206
+ a = Class.new{ def rar; 4; end }
207
+ m = Module.new{ def rar; 4; end }
208
+ b = Class.new(a){ def rar; super; end; include m }
209
+
210
+ zuper = Pry::Method(b.new.method(:rar)).super
211
+ zuper.owner.should == m
212
+ zuper.super.owner.should == a
213
+ end
214
+ end
215
+
216
+ describe 'all_from_class' do
217
+ def should_find_method(name)
218
+ Pry::Method.all_from_class(@class).map(&:name).should.include(name)
219
+ end
220
+
221
+ it 'should be able to find public instance methods defined in a class' do
222
+ @class = Class.new{ def meth; 1; end }
223
+ should_find_method('meth')
224
+ end
225
+
226
+ it 'should be able to find private and protected instance methods defined in a class' do
227
+ @class = Class.new { protected; def prot; 1; end; private; def priv; 1; end }
228
+ should_find_method('priv')
229
+ should_find_method('prot')
230
+ end
231
+
232
+ it 'should find methods all the way up to Kernel' do
233
+ @class = Class.new
234
+ should_find_method('exit!')
235
+ end
236
+
237
+ it 'should be able to find instance methods defined in a super-class' do
238
+ @class = Class.new(Class.new{ def meth; 1; end }) {}
239
+ should_find_method('meth')
240
+ end
241
+
242
+ it 'should be able to find instance methods defined in modules included into this class' do
243
+ @class = Class.new{ include Module.new{ def meth; 1; end; } }
244
+ should_find_method('meth')
245
+ end
246
+
247
+ it 'should be able to find instance methods defined in modules included into super-classes' do
248
+ @class = Class.new(Class.new{ include Module.new{ def meth; 1; end; } })
249
+ should_find_method('meth')
250
+ end
251
+
252
+ it 'should attribute overridden methods to the sub-class' do
253
+ @class = Class.new(Class.new{ include Module.new{ def meth; 1; end; } }) { def meth; 2; end }
254
+ Pry::Method.all_from_class(@class).detect{ |x| x.name == 'meth' }.owner.should == @class
255
+ end
256
+
257
+ it 'should be able to find methods defined on a singleton class' do
258
+ @class = (class << Object.new; def meth; 1; end; self; end)
259
+ should_find_method('meth')
260
+ end
261
+
262
+ it 'should be able to find methods on super-classes when given a singleton class' do
263
+ @class = (class << Class.new{ def meth; 1; end}.new; self; end)
264
+ should_find_method('meth')
265
+ end
266
+ end
267
+
268
+ describe 'all_from_obj' do
269
+ describe 'on normal objects' do
270
+ def should_find_method(name)
271
+ Pry::Method.all_from_obj(@obj).map(&:name).should.include(name)
272
+ end
273
+
274
+ it "should find methods defined in the object's class" do
275
+ @obj = Class.new{ def meth; 1; end }.new
276
+ should_find_method('meth')
277
+ end
278
+
279
+ it "should find methods defined in modules included into the object's class" do
280
+ @obj = Class.new{ include Module.new{ def meth; 1; end } }.new
281
+ should_find_method('meth')
282
+ end
283
+
284
+ it "should find methods defined in the object's singleton class" do
285
+ @obj = Object.new
286
+ class << @obj; def meth; 1; end; end
287
+ should_find_method('meth')
288
+ end
289
+
290
+ it "should find methods in modules included into the object's singleton class" do
291
+ @obj = Object.new
292
+ @obj.extend Module.new{ def meth; 1; end }
293
+ should_find_method('meth')
294
+ end
295
+
296
+ it "should find methods all the way up to Kernel" do
297
+ @obj = Object.new
298
+ should_find_method('exit!')
299
+ end
300
+
301
+ it "should not find methods defined on the classes singleton class" do
302
+ @obj = Class.new{ class << self; def meth; 1; end; end }.new
303
+ Pry::Method.all_from_obj(@obj).map(&:name).should.not.include('meth')
304
+ end
305
+
306
+ it "should work in the face of an overridden send" do
307
+ @obj = Class.new{ def meth; 1; end; def send; raise EOFError; end }.new
308
+ should_find_method('meth')
309
+ end
310
+ end
311
+
312
+ describe 'on classes' do
313
+ def should_find_method(name)
314
+ Pry::Method.all_from_obj(@class).map(&:name).should.include(name)
315
+ end
316
+
317
+ it "should find methods defined in the class' singleton class" do
318
+ @class = Class.new{ class << self; def meth; 1; end; end }
319
+ should_find_method('meth')
320
+ end
321
+
322
+ it "should find methods defined on modules extended into the class" do
323
+ @class = Class.new{ extend Module.new{ def meth; 1; end; } }
324
+ should_find_method('meth')
325
+ end
326
+
327
+ it "should find methods defined on the singleton class of super-classes" do
328
+ @class = Class.new(Class.new{ class << self; def meth; 1; end; end })
329
+ should_find_method('meth')
330
+ end
331
+
332
+ it "should not find methods defined within the class" do
333
+ @class = Class.new{ def meth; 1; end }
334
+ Pry::Method.all_from_obj(@obj).map(&:name).should.not.include('meth')
335
+ end
336
+
337
+ it "should find methods defined on Class" do
338
+ @class = Class.new
339
+ should_find_method('allocate')
340
+ end
341
+
342
+ it "should find methods defined on Kernel" do
343
+ @class = Class.new
344
+ should_find_method('exit!')
345
+ end
346
+
347
+ it "should attribute overridden methods to the sub-class' singleton class" do
348
+ @class = Class.new(Class.new{ class << self; def meth; 1; end; end }) { class << self; def meth; 1; end; end }
349
+ Pry::Method.all_from_obj(@class).detect{ |x| x.name == 'meth' }.owner.should == (class << @class; self; end)
350
+ end
351
+
352
+ it "should attrbute overridden methods to the class not the module" do
353
+ @class = Class.new { class << self; def meth; 1; end; end; extend Module.new{ def meth; 1; end; } }
354
+ Pry::Method.all_from_obj(@class).detect{ |x| x.name == 'meth' }.owner.should == (class << @class; self; end)
355
+ end
356
+
357
+ it "should attribute overridden methods to the relevant singleton class in preference to Class" do
358
+ @class = Class.new { class << self; def allocate; 1; end; end }
359
+ Pry::Method.all_from_obj(@class).detect{ |x| x.name == 'allocate' }.owner.should == (class << @class; self; end)
360
+ end
361
+ end
362
+
363
+ describe 'method resolution order' do
364
+ module LS
365
+ class Top; end
366
+
367
+ class Next < Top; end
368
+
369
+ module M; end
370
+ module N; include M; end
371
+ module O; include M; end
372
+ module P; end
373
+
374
+ class Low < Next; include N; include P; end
375
+ class Lower < Low; extend N; end
376
+ class Bottom < Lower; extend O; end
377
+ end
378
+
379
+ def singleton_class(obj); class << obj; self; end; end
380
+
381
+ it "should look at a class and then its superclass" do
382
+ Pry::Method.instance_resolution_order(LS::Next).should == [LS::Next] + Pry::Method.instance_resolution_order(LS::Top)
383
+ end
384
+
385
+ it "should include the included modules between a class and its superclass" do
386
+ Pry::Method.instance_resolution_order(LS::Low).should == [LS::Low, LS::P, LS::N, LS::M] + Pry::Method.instance_resolution_order(LS::Next)
387
+ end
388
+
389
+ it "should not include modules extended into the class" do
390
+ Pry::Method.instance_resolution_order(LS::Bottom).should == [LS::Bottom] + Pry::Method.instance_resolution_order(LS::Lower)
391
+ end
392
+
393
+ it "should include included modules for Modules" do
394
+ Pry::Method.instance_resolution_order(LS::O).should == [LS::O, LS::M]
395
+ end
396
+
397
+ it "should include the singleton class of objects" do
398
+ obj = LS::Low.new
399
+ Pry::Method.resolution_order(obj).should == [singleton_class(obj)] + Pry::Method.instance_resolution_order(LS::Low)
400
+ end
401
+
402
+ it "should not include singleton classes of numbers" do
403
+ Pry::Method.resolution_order(4).should == Pry::Method.instance_resolution_order(Fixnum)
404
+ end
405
+
406
+ it "should include singleton classes for classes" do
407
+ Pry::Method.resolution_order(LS::Low).should == [singleton_class(LS::Low)] + Pry::Method.resolution_order(LS::Next)
408
+ end
409
+
410
+ it "should include modules included into singleton classes" do
411
+ Pry::Method.resolution_order(LS::Lower).should == [singleton_class(LS::Lower), LS::N, LS::M] + Pry::Method.resolution_order(LS::Low)
412
+ end
413
+
414
+ it "should include modules at most once" do
415
+ Pry::Method.resolution_order(LS::Bottom).count(LS::M).should == 1
416
+ end
417
+
418
+ it "should include modules at the point which they would be reached" do
419
+ Pry::Method.resolution_order(LS::Bottom).should == [singleton_class(LS::Bottom), LS::O] + (Pry::Method.resolution_order(LS::Lower))
420
+ end
421
+
422
+ it "should include the Pry::Method.instance_resolution_order of Class after the singleton classes" do
423
+ Pry::Method.resolution_order(LS::Top).should ==
424
+ [singleton_class(LS::Top), singleton_class(Object), (defined? BasicObject) && singleton_class(BasicObject)].compact +
425
+ Pry::Method.instance_resolution_order(Class)
426
+ end
427
+ end
428
+ end
429
+
430
+ describe 'method_name_from_first_line' do
431
+ it 'should work in all simple cases' do
432
+ meth = Pry::Method.new(nil)
433
+ meth.send(:method_name_from_first_line, "def x").should == "x"
434
+ meth.send(:method_name_from_first_line, "def self.x").should == "x"
435
+ meth.send(:method_name_from_first_line, "def ClassName.x").should == "x"
436
+ meth.send(:method_name_from_first_line, "def obj_name.x").should == "x"
437
+ end
438
+ end
439
+
440
+ describe 'method aliases' do
441
+ before do
442
+ @class = Class.new {
443
+ def eat
444
+ end
445
+
446
+ alias fress eat
447
+ alias_method :omnomnom, :fress
448
+
449
+ def eruct
450
+ end
451
+ }
452
+ end
453
+
454
+ it 'should be able to find method aliases' do
455
+ meth = Pry::Method(@class.new.method(:eat))
456
+ aliases = Set.new(meth.aliases)
457
+
458
+ aliases.should == Set.new(["fress", "omnomnom"])
459
+ end
460
+
461
+ it 'should return an empty Array if cannot find aliases' do
462
+ meth = Pry::Method(@class.new.method(:eruct))
463
+ meth.aliases.should.be.empty
464
+ end
465
+
466
+ it 'should not include the own name in the list of aliases' do
467
+ meth = Pry::Method(@class.new.method(:eat))
468
+ meth.aliases.should.not.include "eat"
469
+ end
470
+
471
+ unless Pry::Helpers::BaseHelpers.mri_18?
472
+ # Ruby 1.8 doesn't support this feature.
473
+ it 'should be able to find aliases for methods implemented in C' do
474
+ meth = Pry::Method(Hash.new.method(:key?))
475
+ aliases = Set.new(meth.aliases)
476
+
477
+ aliases.should == Set.new(["include?", "member?", "has_key?"])
478
+ end
479
+ end
480
+
481
+ end
482
+ end