pry 0.10.0.pre2-universal-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +702 -0
- data/LICENSE +25 -0
- data/README.md +406 -0
- data/bin/pry +16 -0
- data/lib/pry.rb +161 -0
- data/lib/pry/cli.rb +220 -0
- data/lib/pry/code.rb +346 -0
- data/lib/pry/code/code_file.rb +103 -0
- data/lib/pry/code/code_range.rb +71 -0
- data/lib/pry/code/loc.rb +92 -0
- data/lib/pry/code_object.rb +172 -0
- data/lib/pry/color_printer.rb +55 -0
- data/lib/pry/command.rb +692 -0
- data/lib/pry/command_set.rb +443 -0
- data/lib/pry/commands.rb +6 -0
- data/lib/pry/commands/amend_line.rb +99 -0
- data/lib/pry/commands/bang.rb +20 -0
- data/lib/pry/commands/bang_pry.rb +17 -0
- data/lib/pry/commands/cat.rb +62 -0
- data/lib/pry/commands/cat/abstract_formatter.rb +27 -0
- data/lib/pry/commands/cat/exception_formatter.rb +77 -0
- data/lib/pry/commands/cat/file_formatter.rb +67 -0
- data/lib/pry/commands/cat/input_expression_formatter.rb +43 -0
- data/lib/pry/commands/cd.rb +41 -0
- data/lib/pry/commands/change_inspector.rb +27 -0
- data/lib/pry/commands/change_prompt.rb +26 -0
- data/lib/pry/commands/code_collector.rb +165 -0
- data/lib/pry/commands/disable_pry.rb +27 -0
- data/lib/pry/commands/disabled_commands.rb +2 -0
- data/lib/pry/commands/easter_eggs.rb +112 -0
- data/lib/pry/commands/edit.rb +195 -0
- data/lib/pry/commands/edit/exception_patcher.rb +25 -0
- data/lib/pry/commands/edit/file_and_line_locator.rb +36 -0
- data/lib/pry/commands/exit.rb +42 -0
- data/lib/pry/commands/exit_all.rb +29 -0
- data/lib/pry/commands/exit_program.rb +23 -0
- data/lib/pry/commands/find_method.rb +193 -0
- data/lib/pry/commands/fix_indent.rb +19 -0
- data/lib/pry/commands/gem_cd.rb +26 -0
- data/lib/pry/commands/gem_install.rb +32 -0
- data/lib/pry/commands/gem_list.rb +33 -0
- data/lib/pry/commands/gem_open.rb +29 -0
- data/lib/pry/commands/gist.rb +101 -0
- data/lib/pry/commands/help.rb +164 -0
- data/lib/pry/commands/hist.rb +180 -0
- data/lib/pry/commands/import_set.rb +22 -0
- data/lib/pry/commands/install_command.rb +53 -0
- data/lib/pry/commands/jump_to.rb +29 -0
- data/lib/pry/commands/list_inspectors.rb +35 -0
- data/lib/pry/commands/list_prompts.rb +35 -0
- data/lib/pry/commands/ls.rb +114 -0
- data/lib/pry/commands/ls/constants.rb +47 -0
- data/lib/pry/commands/ls/formatter.rb +49 -0
- data/lib/pry/commands/ls/globals.rb +48 -0
- data/lib/pry/commands/ls/grep.rb +21 -0
- data/lib/pry/commands/ls/instance_vars.rb +39 -0
- data/lib/pry/commands/ls/interrogatable.rb +18 -0
- data/lib/pry/commands/ls/jruby_hacks.rb +49 -0
- data/lib/pry/commands/ls/local_names.rb +35 -0
- data/lib/pry/commands/ls/local_vars.rb +39 -0
- data/lib/pry/commands/ls/ls_entity.rb +70 -0
- data/lib/pry/commands/ls/methods.rb +57 -0
- data/lib/pry/commands/ls/methods_helper.rb +46 -0
- data/lib/pry/commands/ls/self_methods.rb +32 -0
- data/lib/pry/commands/nesting.rb +25 -0
- data/lib/pry/commands/play.rb +103 -0
- data/lib/pry/commands/pry_backtrace.rb +25 -0
- data/lib/pry/commands/pry_version.rb +17 -0
- data/lib/pry/commands/raise_up.rb +32 -0
- data/lib/pry/commands/reload_code.rb +62 -0
- data/lib/pry/commands/reset.rb +18 -0
- data/lib/pry/commands/ri.rb +60 -0
- data/lib/pry/commands/save_file.rb +61 -0
- data/lib/pry/commands/shell_command.rb +48 -0
- data/lib/pry/commands/shell_mode.rb +25 -0
- data/lib/pry/commands/show_doc.rb +83 -0
- data/lib/pry/commands/show_info.rb +195 -0
- data/lib/pry/commands/show_input.rb +17 -0
- data/lib/pry/commands/show_source.rb +50 -0
- data/lib/pry/commands/simple_prompt.rb +22 -0
- data/lib/pry/commands/stat.rb +40 -0
- data/lib/pry/commands/switch_to.rb +23 -0
- data/lib/pry/commands/toggle_color.rb +24 -0
- data/lib/pry/commands/watch_expression.rb +105 -0
- data/lib/pry/commands/watch_expression/expression.rb +38 -0
- data/lib/pry/commands/whereami.rb +190 -0
- data/lib/pry/commands/wtf.rb +57 -0
- data/lib/pry/config.rb +24 -0
- data/lib/pry/config/behavior.rb +139 -0
- data/lib/pry/config/convenience.rb +26 -0
- data/lib/pry/config/default.rb +165 -0
- data/lib/pry/core_extensions.rb +131 -0
- data/lib/pry/editor.rb +133 -0
- data/lib/pry/exceptions.rb +77 -0
- data/lib/pry/helpers.rb +5 -0
- data/lib/pry/helpers/base_helpers.rb +113 -0
- data/lib/pry/helpers/command_helpers.rb +156 -0
- data/lib/pry/helpers/documentation_helpers.rb +75 -0
- data/lib/pry/helpers/options_helpers.rb +27 -0
- data/lib/pry/helpers/table.rb +109 -0
- data/lib/pry/helpers/text.rb +107 -0
- data/lib/pry/history.rb +125 -0
- data/lib/pry/history_array.rb +121 -0
- data/lib/pry/hooks.rb +230 -0
- data/lib/pry/indent.rb +406 -0
- data/lib/pry/input_completer.rb +242 -0
- data/lib/pry/input_lock.rb +132 -0
- data/lib/pry/inspector.rb +27 -0
- data/lib/pry/last_exception.rb +61 -0
- data/lib/pry/method.rb +546 -0
- data/lib/pry/method/disowned.rb +53 -0
- data/lib/pry/method/patcher.rb +125 -0
- data/lib/pry/method/weird_method_locator.rb +186 -0
- data/lib/pry/module_candidate.rb +136 -0
- data/lib/pry/object_path.rb +82 -0
- data/lib/pry/output.rb +50 -0
- data/lib/pry/pager.rb +234 -0
- data/lib/pry/plugins.rb +103 -0
- data/lib/pry/prompt.rb +26 -0
- data/lib/pry/pry_class.rb +375 -0
- data/lib/pry/pry_instance.rb +654 -0
- data/lib/pry/rbx_path.rb +22 -0
- data/lib/pry/repl.rb +202 -0
- data/lib/pry/repl_file_loader.rb +74 -0
- data/lib/pry/rubygem.rb +82 -0
- data/lib/pry/terminal.rb +79 -0
- data/lib/pry/test/helper.rb +170 -0
- data/lib/pry/version.rb +3 -0
- data/lib/pry/wrapped_module.rb +373 -0
- metadata +248 -0
data/lib/pry/method.rb
ADDED
@@ -0,0 +1,546 @@
|
|
1
|
+
require 'pry/helpers/documentation_helpers'
|
2
|
+
|
3
|
+
class Pry
|
4
|
+
class << self
|
5
|
+
# If the given object is a `Pry::Method`, return it unaltered. If it's
|
6
|
+
# anything else, return it wrapped in a `Pry::Method` instance.
|
7
|
+
def Method(obj)
|
8
|
+
if obj.is_a? Pry::Method
|
9
|
+
obj
|
10
|
+
else
|
11
|
+
Pry::Method.new(obj)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# This class wraps the normal `Method` and `UnboundMethod` classes
|
17
|
+
# to provide extra functionality useful to Pry.
|
18
|
+
class Method
|
19
|
+
require 'pry/method/weird_method_locator'
|
20
|
+
require 'pry/method/disowned'
|
21
|
+
require 'pry/method/patcher'
|
22
|
+
|
23
|
+
extend Helpers::BaseHelpers
|
24
|
+
include Helpers::BaseHelpers
|
25
|
+
include Helpers::DocumentationHelpers
|
26
|
+
include CodeObject::Helpers
|
27
|
+
|
28
|
+
class << self
|
29
|
+
# Given a string representing a method name and optionally a binding to
|
30
|
+
# search in, find and return the requested method wrapped in a `Pry::Method`
|
31
|
+
# instance.
|
32
|
+
#
|
33
|
+
# @param [String] name The name of the method to retrieve.
|
34
|
+
# @param [Binding] target The context in which to search for the method.
|
35
|
+
# @param [Hash] options
|
36
|
+
# @option options [Boolean] :instance Look for an instance method if `name` doesn't
|
37
|
+
# contain any context.
|
38
|
+
# @option options [Boolean] :methods Look for a bound/singleton method if `name` doesn't
|
39
|
+
# contain any context.
|
40
|
+
# @return [Pry::Method, nil] A `Pry::Method` instance containing the requested
|
41
|
+
# method, or `nil` if name is `nil` or no method could be located matching the parameters.
|
42
|
+
def from_str(name, target=TOPLEVEL_BINDING, options={})
|
43
|
+
if name.nil?
|
44
|
+
nil
|
45
|
+
elsif name.to_s =~ /(.+)\#(\S+)\Z/
|
46
|
+
context, meth_name = $1, $2
|
47
|
+
from_module(target.eval(context), meth_name, target)
|
48
|
+
elsif name.to_s =~ /(.+)(\[\])\Z/
|
49
|
+
context, meth_name = $1, $2
|
50
|
+
from_obj(target.eval(context), meth_name, target)
|
51
|
+
elsif name.to_s =~ /(.+)(\.|::)(\S+)\Z/
|
52
|
+
context, meth_name = $1, $3
|
53
|
+
from_obj(target.eval(context), meth_name, target)
|
54
|
+
elsif options[:instance]
|
55
|
+
from_module(target.eval("self"), name, target)
|
56
|
+
elsif options[:methods]
|
57
|
+
from_obj(target.eval("self"), name, target)
|
58
|
+
else
|
59
|
+
from_str(name, target, :instance => true) or
|
60
|
+
from_str(name, target, :methods => true)
|
61
|
+
end
|
62
|
+
|
63
|
+
rescue Pry::RescuableException
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
|
67
|
+
# Given a `Binding`, try to extract the `::Method` it originated from and
|
68
|
+
# use it to instantiate a `Pry::Method`. Return `nil` if this isn't
|
69
|
+
# possible.
|
70
|
+
#
|
71
|
+
# @param [Binding] b
|
72
|
+
# @return [Pry::Method, nil]
|
73
|
+
#
|
74
|
+
def from_binding(b)
|
75
|
+
meth_name = b.eval('::Kernel.__method__')
|
76
|
+
if [:__script__, nil].include?(meth_name)
|
77
|
+
nil
|
78
|
+
else
|
79
|
+
method = begin
|
80
|
+
if Object === b.eval('self')
|
81
|
+
new(Kernel.instance_method(:method).bind(b.eval("self")).call(meth_name))
|
82
|
+
else
|
83
|
+
new(b.eval('class << self; self; end.instance_method(::Kernel.__method__).bind(self)'))
|
84
|
+
end
|
85
|
+
rescue NameError, NoMethodError
|
86
|
+
Disowned.new(b.eval('self'), meth_name.to_s)
|
87
|
+
end
|
88
|
+
|
89
|
+
if WeirdMethodLocator.weird_method?(method, b)
|
90
|
+
WeirdMethodLocator.new(method, b).get_method || method
|
91
|
+
else
|
92
|
+
method
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# In order to support 2.0 Refinements we need to look up methods
|
98
|
+
# inside the relevant Binding.
|
99
|
+
# @param [Object] obj The owner/receiver of the method.
|
100
|
+
# @param [Symbol] method_name The name of the method.
|
101
|
+
# @param [Symbol] method_type The type of method: :method or :instance_method
|
102
|
+
# @param [Binding] target The binding where the method is looked up.
|
103
|
+
# @return [Method, UnboundMethod] The 'refined' method object.
|
104
|
+
def lookup_method_via_binding(obj, method_name, method_type, target=TOPLEVEL_BINDING)
|
105
|
+
Pry.current[:obj] = obj
|
106
|
+
Pry.current[:name] = method_name
|
107
|
+
receiver = obj.is_a?(Module) ? "Module" : "Kernel"
|
108
|
+
target.eval("::#{receiver}.instance_method(:#{method_type}).bind(Pry.current[:obj]).call(Pry.current[:name])")
|
109
|
+
ensure
|
110
|
+
Pry.current[:obj] = Pry.current[:name] = nil
|
111
|
+
end
|
112
|
+
|
113
|
+
# Given a `Class` or `Module` and the name of a method, try to
|
114
|
+
# instantiate a `Pry::Method` containing the instance method of
|
115
|
+
# that name. Return `nil` if no such method exists.
|
116
|
+
#
|
117
|
+
# @param [Class, Module] klass
|
118
|
+
# @param [String] name
|
119
|
+
# @param [Binding] target The binding where the method is looked up.
|
120
|
+
# @return [Pry::Method, nil]
|
121
|
+
def from_class(klass, name, target=TOPLEVEL_BINDING)
|
122
|
+
new(lookup_method_via_binding(klass, name, :instance_method, target)) rescue nil
|
123
|
+
end
|
124
|
+
alias from_module from_class
|
125
|
+
|
126
|
+
# Given an object and the name of a method, try to instantiate
|
127
|
+
# a `Pry::Method` containing the method of that name bound to
|
128
|
+
# that object. Return `nil` if no such method exists.
|
129
|
+
#
|
130
|
+
# @param [Object] obj
|
131
|
+
# @param [String] name
|
132
|
+
# @param [Binding] target The binding where the method is looked up.
|
133
|
+
# @return [Pry::Method, nil]
|
134
|
+
def from_obj(obj, name, target=TOPLEVEL_BINDING)
|
135
|
+
new(lookup_method_via_binding(obj, name, :method, target)) rescue nil
|
136
|
+
end
|
137
|
+
|
138
|
+
# Get all of the instance methods of a `Class` or `Module`
|
139
|
+
# @param [Class,Module] klass
|
140
|
+
# @param [Boolean] include_super Whether to include methods from ancestors.
|
141
|
+
# @return [Array[Pry::Method]]
|
142
|
+
def all_from_class(klass, include_super=true)
|
143
|
+
%w(public protected private).map do |visibility|
|
144
|
+
safe_send(klass, :"#{visibility}_instance_methods", include_super).map do |method_name|
|
145
|
+
new(safe_send(klass, :instance_method, method_name), :visibility => visibility.to_sym)
|
146
|
+
end
|
147
|
+
end.flatten(1)
|
148
|
+
end
|
149
|
+
|
150
|
+
#
|
151
|
+
# Get all of the methods on an `Object`
|
152
|
+
#
|
153
|
+
# @param [Object] obj
|
154
|
+
#
|
155
|
+
# @param [Boolean] include_super
|
156
|
+
# indicates whether or not to include methods from ancestors.
|
157
|
+
#
|
158
|
+
# @return [Array[Pry::Method]]
|
159
|
+
#
|
160
|
+
def all_from_obj(obj, include_super=true)
|
161
|
+
all_from_class(singleton_class_of(obj), include_super)
|
162
|
+
end
|
163
|
+
|
164
|
+
#
|
165
|
+
# @deprecated
|
166
|
+
# please use {#all_from_obj} instead.
|
167
|
+
# the `method_type` argument is ignored.
|
168
|
+
#
|
169
|
+
def all_from_common(obj, method_type = nil, include_super=true)
|
170
|
+
all_from_obj(obj, include_super)
|
171
|
+
end
|
172
|
+
|
173
|
+
# Get every `Class` and `Module`, in order, that will be checked when looking
|
174
|
+
# for an instance method to call on this object.
|
175
|
+
# @param [Object] obj
|
176
|
+
# @return [Array[Class, Module]]
|
177
|
+
def resolution_order(obj)
|
178
|
+
if Class === obj
|
179
|
+
singleton_class_resolution_order(obj) + instance_resolution_order(Class)
|
180
|
+
else
|
181
|
+
klass = singleton_class_of(obj) rescue obj.class
|
182
|
+
instance_resolution_order(klass)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# Get every `Class` and `Module`, in order, that will be checked when looking
|
187
|
+
# for methods on instances of the given `Class` or `Module`.
|
188
|
+
# This does not treat singleton classes of classes specially.
|
189
|
+
# @param [Class, Module] klass
|
190
|
+
# @return [Array[Class, Module]]
|
191
|
+
def instance_resolution_order(klass)
|
192
|
+
# include klass in case it is a singleton class,
|
193
|
+
([klass] + Pry::Method.safe_send(klass, :ancestors)).uniq
|
194
|
+
end
|
195
|
+
|
196
|
+
def method_definition?(name, definition_line)
|
197
|
+
singleton_method_definition?(name, definition_line) ||
|
198
|
+
instance_method_definition?(name, definition_line)
|
199
|
+
end
|
200
|
+
|
201
|
+
def singleton_method_definition?(name, definition_line)
|
202
|
+
/^define_singleton_method\(?\s*[:\"\']#{Regexp.escape(name)}|^def\s*self\.#{Regexp.escape(name)}/ =~ definition_line.strip
|
203
|
+
end
|
204
|
+
|
205
|
+
def instance_method_definition?(name, definition_line)
|
206
|
+
/^define_method\(?\s*[:\"\']#{Regexp.escape(name)}|^def\s*#{Regexp.escape(name)}/ =~ definition_line.strip
|
207
|
+
end
|
208
|
+
|
209
|
+
# Get the singleton classes of superclasses that could define methods on
|
210
|
+
# the given class object, and any modules they include.
|
211
|
+
# If a module is included at multiple points in the ancestry, only
|
212
|
+
# the lowest copy will be returned.
|
213
|
+
def singleton_class_resolution_order(klass)
|
214
|
+
ancestors = Pry::Method.safe_send(klass, :ancestors)
|
215
|
+
resolution_order = ancestors.grep(Class).map do |anc|
|
216
|
+
[singleton_class_of(anc), *singleton_class_of(anc).included_modules]
|
217
|
+
end.flatten(1)
|
218
|
+
|
219
|
+
resolution_order.reverse.uniq.reverse - Class.included_modules
|
220
|
+
end
|
221
|
+
|
222
|
+
def singleton_class_of(obj)
|
223
|
+
begin
|
224
|
+
class << obj; self; end
|
225
|
+
rescue TypeError # can't define singleton. Fixnum, Symbol, Float, ...
|
226
|
+
obj.class
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
# A new instance of `Pry::Method` wrapping the given `::Method`, `UnboundMethod`, or `Proc`.
|
232
|
+
#
|
233
|
+
# @param [::Method, UnboundMethod, Proc] method
|
234
|
+
# @param [Hash] known_info Can be used to pre-cache expensive to compute stuff.
|
235
|
+
# @return [Pry::Method]
|
236
|
+
def initialize(method, known_info={})
|
237
|
+
@method = method
|
238
|
+
@visibility = known_info[:visibility]
|
239
|
+
end
|
240
|
+
|
241
|
+
# Get the name of the method as a String, regardless of the underlying Method#name type.
|
242
|
+
# @return [String]
|
243
|
+
def name
|
244
|
+
@method.name.to_s
|
245
|
+
end
|
246
|
+
|
247
|
+
# Get the owner of the method as a Pry::Module
|
248
|
+
# @return [Pry::Module]
|
249
|
+
def wrapped_owner
|
250
|
+
@wrapped_owner ||= Pry::WrappedModule.new(owner)
|
251
|
+
end
|
252
|
+
|
253
|
+
# Get underlying object wrapped by this Pry::Method instance
|
254
|
+
# @return [Method, UnboundMethod, Proc]
|
255
|
+
def wrapped
|
256
|
+
@method
|
257
|
+
end
|
258
|
+
|
259
|
+
# Is the method undefined? (aka `Disowned`)
|
260
|
+
# @return [Boolean] false
|
261
|
+
def undefined?
|
262
|
+
false
|
263
|
+
end
|
264
|
+
|
265
|
+
# Get the name of the method including the class on which it was defined.
|
266
|
+
# @example
|
267
|
+
# method(:puts).method_name
|
268
|
+
# => "Kernel.puts"
|
269
|
+
# @return [String]
|
270
|
+
def name_with_owner
|
271
|
+
"#{wrapped_owner.method_prefix}#{name}"
|
272
|
+
end
|
273
|
+
|
274
|
+
# @return [String, nil] The source code of the method, or `nil` if it's unavailable.
|
275
|
+
def source
|
276
|
+
@source ||= case source_type
|
277
|
+
when :c
|
278
|
+
c_source
|
279
|
+
when :ruby
|
280
|
+
ruby_source
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
# Update the live copy of the method's source.
|
285
|
+
def redefine(source)
|
286
|
+
Patcher.new(self).patch_in_ram source
|
287
|
+
Pry::Method(owner.instance_method(name))
|
288
|
+
end
|
289
|
+
|
290
|
+
# Can we get the source code for this method?
|
291
|
+
# @return [Boolean]
|
292
|
+
def source?
|
293
|
+
!!source
|
294
|
+
rescue MethodSource::SourceNotFoundError
|
295
|
+
false
|
296
|
+
end
|
297
|
+
|
298
|
+
# @return [String, nil] The documentation for the method, or `nil` if it's
|
299
|
+
# unavailable.
|
300
|
+
def doc
|
301
|
+
@doc ||= case source_type
|
302
|
+
when :c
|
303
|
+
info = pry_doc_info
|
304
|
+
info.docstring if info
|
305
|
+
when :ruby
|
306
|
+
get_comment_content(comment)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
# @return [Symbol] The source type of the method. The options are
|
311
|
+
# `:ruby` for Ruby methods or `:c` for methods written in C.
|
312
|
+
def source_type
|
313
|
+
source_location.nil? ? :c : :ruby
|
314
|
+
end
|
315
|
+
|
316
|
+
# @return [String, nil] The name of the file the method is defined in, or
|
317
|
+
# `nil` if the filename is unavailable.
|
318
|
+
def source_file
|
319
|
+
if source_location.nil?
|
320
|
+
if !rbx? and source_type == :c
|
321
|
+
info = pry_doc_info
|
322
|
+
info.file if info
|
323
|
+
end
|
324
|
+
else
|
325
|
+
source_location.first
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
# @return [Fixnum, nil] The line of code in `source_file` which begins
|
330
|
+
# the method's definition, or `nil` if that information is unavailable.
|
331
|
+
def source_line
|
332
|
+
source_location.nil? ? nil : source_location.last
|
333
|
+
end
|
334
|
+
|
335
|
+
# @return [Range, nil] The range of lines in `source_file` which contain
|
336
|
+
# the method's definition, or `nil` if that information is unavailable.
|
337
|
+
def source_range
|
338
|
+
source_location.nil? ? nil : (source_line)..(source_line + source.lines.count - 1)
|
339
|
+
end
|
340
|
+
|
341
|
+
# @return [Symbol] The visibility of the method. May be `:public`,
|
342
|
+
# `:protected`, or `:private`.
|
343
|
+
def visibility
|
344
|
+
@visibility ||= if owner.public_instance_methods.any? { |m| m.to_s == name }
|
345
|
+
:public
|
346
|
+
elsif owner.protected_instance_methods.any? { |m| m.to_s == name }
|
347
|
+
:protected
|
348
|
+
elsif owner.private_instance_methods.any? { |m| m.to_s == name }
|
349
|
+
:private
|
350
|
+
else
|
351
|
+
:none
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
# @return [String] A representation of the method's signature, including its
|
356
|
+
# name and parameters. Optional and "rest" parameters are marked with `*`
|
357
|
+
# and block parameters with `&`. If the parameter names are unavailable,
|
358
|
+
# they're given numbered names instead.
|
359
|
+
# Paraphrased from `awesome_print` gem.
|
360
|
+
def signature
|
361
|
+
if respond_to?(:parameters)
|
362
|
+
args = parameters.inject([]) do |arr, (type, name)|
|
363
|
+
name ||= (type == :block ? 'block' : "arg#{arr.size + 1}")
|
364
|
+
arr << case type
|
365
|
+
when :req then name.to_s
|
366
|
+
when :opt then "#{name}=?"
|
367
|
+
when :rest then "*#{name}"
|
368
|
+
when :block then "&#{name}"
|
369
|
+
else '?'
|
370
|
+
end
|
371
|
+
end
|
372
|
+
else
|
373
|
+
args = (1..arity.abs).map { |i| "arg#{i}" }
|
374
|
+
args[-1] = "*#{args[-1]}" if arity < 0
|
375
|
+
end
|
376
|
+
|
377
|
+
"#{name}(#{args.join(', ')})"
|
378
|
+
end
|
379
|
+
|
380
|
+
# @return [Pry::Method, nil] The wrapped method that is called when you
|
381
|
+
# use "super" in the body of this method.
|
382
|
+
def super(times=1)
|
383
|
+
if UnboundMethod === @method
|
384
|
+
sup = super_using_ancestors(Pry::Method.instance_resolution_order(owner), times)
|
385
|
+
else
|
386
|
+
sup = super_using_ancestors(Pry::Method.resolution_order(receiver), times)
|
387
|
+
sup &&= sup.bind(receiver)
|
388
|
+
end
|
389
|
+
Pry::Method.new(sup) if sup
|
390
|
+
end
|
391
|
+
|
392
|
+
# @return [String, nil] The original name the method was defined under,
|
393
|
+
# before any aliasing, or `nil` if it can't be determined.
|
394
|
+
def original_name
|
395
|
+
return nil if source_type != :ruby
|
396
|
+
method_name_from_first_line(source.lines.first)
|
397
|
+
end
|
398
|
+
|
399
|
+
# @return [Boolean] Was the method defined outside a source file?
|
400
|
+
def dynamically_defined?
|
401
|
+
!!(source_file and source_file =~ /(\(.*\))|<.*>/)
|
402
|
+
end
|
403
|
+
|
404
|
+
# @return [Boolean] Whether the method is unbound.
|
405
|
+
def unbound_method?
|
406
|
+
is_a?(::UnboundMethod)
|
407
|
+
end
|
408
|
+
|
409
|
+
# @return [Boolean] Whether the method is bound.
|
410
|
+
def bound_method?
|
411
|
+
is_a?(::Method)
|
412
|
+
end
|
413
|
+
|
414
|
+
# @return [Boolean] Whether the method is a singleton method.
|
415
|
+
def singleton_method?
|
416
|
+
wrapped_owner.singleton_class?
|
417
|
+
end
|
418
|
+
|
419
|
+
# @return [Boolean] Was the method defined within the Pry REPL?
|
420
|
+
def pry_method?
|
421
|
+
source_file == Pry.eval_path
|
422
|
+
end
|
423
|
+
|
424
|
+
# @return [Array<String>] All known aliases for the method.
|
425
|
+
def aliases
|
426
|
+
owner = @method.owner
|
427
|
+
# Avoid using `to_sym` on {Method#name}, which returns a `String`, because
|
428
|
+
# it won't be garbage collected.
|
429
|
+
name = @method.name
|
430
|
+
|
431
|
+
all_methods_to_compare = owner.instance_methods | owner.private_instance_methods
|
432
|
+
alias_list = all_methods_to_compare.combination(2).select do |pair|
|
433
|
+
pair.include?(name) &&
|
434
|
+
owner.instance_method(pair.first) == owner.instance_method(pair.last)
|
435
|
+
end.flatten
|
436
|
+
alias_list.delete(name)
|
437
|
+
|
438
|
+
alias_list.map(&:to_s)
|
439
|
+
end
|
440
|
+
|
441
|
+
# @return [Boolean] Is the method definitely an alias?
|
442
|
+
def alias?
|
443
|
+
name != original_name
|
444
|
+
end
|
445
|
+
|
446
|
+
# @return [Boolean]
|
447
|
+
def ==(obj)
|
448
|
+
if obj.is_a? Pry::Method
|
449
|
+
obj == @method
|
450
|
+
else
|
451
|
+
@method == obj
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
# @param [Class] klass
|
456
|
+
# @return [Boolean]
|
457
|
+
def is_a?(klass)
|
458
|
+
klass == Pry::Method or @method.is_a?(klass)
|
459
|
+
end
|
460
|
+
alias kind_of? is_a?
|
461
|
+
|
462
|
+
# @param [String, Symbol] method_name
|
463
|
+
# @return [Boolean]
|
464
|
+
def respond_to?(method_name)
|
465
|
+
super or @method.respond_to?(method_name)
|
466
|
+
end
|
467
|
+
|
468
|
+
# Delegate any unknown calls to the wrapped method.
|
469
|
+
def method_missing(method_name, *args, &block)
|
470
|
+
@method.send(method_name, *args, &block)
|
471
|
+
end
|
472
|
+
|
473
|
+
def comment
|
474
|
+
Pry::Code.from_file(source_file).comment_describing(source_line)
|
475
|
+
end
|
476
|
+
|
477
|
+
private
|
478
|
+
|
479
|
+
# @return [YARD::CodeObjects::MethodObject]
|
480
|
+
# @raise [CommandError] when the method can't be found or `pry-doc` isn't installed.
|
481
|
+
def pry_doc_info
|
482
|
+
if Pry.config.has_pry_doc
|
483
|
+
Pry::MethodInfo.info_for(@method) or raise CommandError, "Cannot locate this method: #{name}. (source_location returns nil)"
|
484
|
+
else
|
485
|
+
fail_msg = "Cannot locate this method: #{name}."
|
486
|
+
if mri?
|
487
|
+
fail_msg += ' Try `gem-install pry-doc` to get access to Ruby Core documentation.'
|
488
|
+
end
|
489
|
+
raise CommandError, fail_msg
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
# @param [Class, Module] ancestors The ancestors to investigate
|
494
|
+
# @return [Method] The unwrapped super-method
|
495
|
+
def super_using_ancestors(ancestors, times=1)
|
496
|
+
next_owner = self.owner
|
497
|
+
times.times do
|
498
|
+
i = ancestors.index(next_owner) + 1
|
499
|
+
while ancestors[i] && !(ancestors[i].method_defined?(name) || ancestors[i].private_method_defined?(name))
|
500
|
+
i += 1
|
501
|
+
end
|
502
|
+
next_owner = ancestors[i] or return nil
|
503
|
+
end
|
504
|
+
|
505
|
+
safe_send(next_owner, :instance_method, name) rescue nil
|
506
|
+
end
|
507
|
+
|
508
|
+
# @param [String] first_ln The first line of a method definition.
|
509
|
+
# @return [String, nil]
|
510
|
+
def method_name_from_first_line(first_ln)
|
511
|
+
return nil if first_ln.strip !~ /^def /
|
512
|
+
|
513
|
+
tokens = CodeRay.scan(first_ln, :ruby)
|
514
|
+
tokens = tokens.tokens.each_slice(2) if tokens.respond_to?(:tokens)
|
515
|
+
tokens.each_cons(2) do |t1, t2|
|
516
|
+
if t2.last == :method || t2.last == :ident && t1 == [".", :operator]
|
517
|
+
return t2.first
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
nil
|
522
|
+
end
|
523
|
+
|
524
|
+
def c_source
|
525
|
+
info = pry_doc_info
|
526
|
+
if info and info.source
|
527
|
+
strip_comments_from_c_code(info.source)
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
def ruby_source
|
532
|
+
# clone of MethodSource.source_helper that knows to use our
|
533
|
+
# hacked version of source_location for rbx core methods, and
|
534
|
+
# our input buffer for methods defined in (pry)
|
535
|
+
file, line = *source_location
|
536
|
+
raise SourceNotFoundError, "Could not locate source for #{name_with_owner}!" unless file
|
537
|
+
|
538
|
+
begin
|
539
|
+
code = Pry::Code.from_file(file).expression_at(line)
|
540
|
+
rescue SyntaxError => e
|
541
|
+
raise MethodSource::SourceNotFoundError.new(e.message)
|
542
|
+
end
|
543
|
+
strip_leading_whitespace(code)
|
544
|
+
end
|
545
|
+
end
|
546
|
+
end
|