pry 0.10.pre.1-i386-mswin32 → 0.10.0.pre3-i386-mswin32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +702 -0
  3. data/LICENSE +2 -2
  4. data/{README.markdown → README.md} +41 -35
  5. data/lib/pry.rb +82 -139
  6. data/lib/pry/cli.rb +77 -30
  7. data/lib/pry/code.rb +122 -183
  8. data/lib/pry/code/code_file.rb +103 -0
  9. data/lib/pry/code/code_range.rb +71 -0
  10. data/lib/pry/code/loc.rb +92 -0
  11. data/lib/pry/code_object.rb +172 -0
  12. data/lib/pry/color_printer.rb +55 -0
  13. data/lib/pry/command.rb +184 -28
  14. data/lib/pry/command_set.rb +113 -59
  15. data/lib/pry/commands.rb +4 -27
  16. data/lib/pry/commands/amend_line.rb +99 -0
  17. data/lib/pry/commands/bang.rb +20 -0
  18. data/lib/pry/commands/bang_pry.rb +17 -0
  19. data/lib/pry/commands/cat.rb +62 -0
  20. data/lib/pry/commands/cat/abstract_formatter.rb +27 -0
  21. data/lib/pry/commands/cat/exception_formatter.rb +77 -0
  22. data/lib/pry/commands/cat/file_formatter.rb +67 -0
  23. data/lib/pry/commands/cat/input_expression_formatter.rb +43 -0
  24. data/lib/pry/commands/cd.rb +41 -0
  25. data/lib/pry/commands/change_inspector.rb +27 -0
  26. data/lib/pry/commands/change_prompt.rb +26 -0
  27. data/lib/pry/commands/code_collector.rb +165 -0
  28. data/lib/pry/commands/disable_pry.rb +27 -0
  29. data/lib/pry/commands/disabled_commands.rb +2 -0
  30. data/lib/pry/commands/easter_eggs.rb +112 -0
  31. data/lib/pry/commands/edit.rb +195 -0
  32. data/lib/pry/commands/edit/exception_patcher.rb +25 -0
  33. data/lib/pry/commands/edit/file_and_line_locator.rb +36 -0
  34. data/lib/pry/commands/exit.rb +42 -0
  35. data/lib/pry/commands/exit_all.rb +29 -0
  36. data/lib/pry/commands/exit_program.rb +23 -0
  37. data/lib/pry/commands/find_method.rb +193 -0
  38. data/lib/pry/commands/fix_indent.rb +19 -0
  39. data/lib/pry/commands/gem_cd.rb +26 -0
  40. data/lib/pry/commands/gem_install.rb +32 -0
  41. data/lib/pry/commands/gem_list.rb +33 -0
  42. data/lib/pry/commands/gem_open.rb +29 -0
  43. data/lib/pry/commands/gist.rb +101 -0
  44. data/lib/pry/commands/help.rb +164 -0
  45. data/lib/pry/commands/hist.rb +180 -0
  46. data/lib/pry/commands/import_set.rb +22 -0
  47. data/lib/pry/commands/install_command.rb +53 -0
  48. data/lib/pry/commands/jump_to.rb +29 -0
  49. data/lib/pry/commands/list_inspectors.rb +35 -0
  50. data/lib/pry/commands/list_prompts.rb +35 -0
  51. data/lib/pry/commands/ls.rb +114 -0
  52. data/lib/pry/commands/ls/constants.rb +47 -0
  53. data/lib/pry/commands/ls/formatter.rb +49 -0
  54. data/lib/pry/commands/ls/globals.rb +48 -0
  55. data/lib/pry/commands/ls/grep.rb +21 -0
  56. data/lib/pry/commands/ls/instance_vars.rb +39 -0
  57. data/lib/pry/commands/ls/interrogatable.rb +18 -0
  58. data/lib/pry/commands/ls/jruby_hacks.rb +49 -0
  59. data/lib/pry/commands/ls/local_names.rb +35 -0
  60. data/lib/pry/commands/ls/local_vars.rb +39 -0
  61. data/lib/pry/commands/ls/ls_entity.rb +70 -0
  62. data/lib/pry/commands/ls/methods.rb +57 -0
  63. data/lib/pry/commands/ls/methods_helper.rb +46 -0
  64. data/lib/pry/commands/ls/self_methods.rb +32 -0
  65. data/lib/pry/commands/nesting.rb +25 -0
  66. data/lib/pry/commands/play.rb +103 -0
  67. data/lib/pry/commands/pry_backtrace.rb +25 -0
  68. data/lib/pry/commands/pry_version.rb +17 -0
  69. data/lib/pry/commands/raise_up.rb +32 -0
  70. data/lib/pry/commands/reload_code.rb +62 -0
  71. data/lib/pry/commands/reset.rb +18 -0
  72. data/lib/pry/commands/ri.rb +60 -0
  73. data/lib/pry/commands/save_file.rb +61 -0
  74. data/lib/pry/commands/shell_command.rb +48 -0
  75. data/lib/pry/commands/shell_mode.rb +25 -0
  76. data/lib/pry/commands/show_doc.rb +83 -0
  77. data/lib/pry/commands/show_info.rb +195 -0
  78. data/lib/pry/commands/show_input.rb +17 -0
  79. data/lib/pry/commands/show_source.rb +50 -0
  80. data/lib/pry/commands/simple_prompt.rb +22 -0
  81. data/lib/pry/commands/stat.rb +40 -0
  82. data/lib/pry/commands/switch_to.rb +23 -0
  83. data/lib/pry/commands/toggle_color.rb +24 -0
  84. data/lib/pry/commands/watch_expression.rb +105 -0
  85. data/lib/pry/commands/watch_expression/expression.rb +38 -0
  86. data/lib/pry/commands/whereami.rb +190 -0
  87. data/lib/pry/commands/wtf.rb +57 -0
  88. data/lib/pry/config.rb +20 -229
  89. data/lib/pry/config/behavior.rb +139 -0
  90. data/lib/pry/config/convenience.rb +26 -0
  91. data/lib/pry/config/default.rb +165 -0
  92. data/lib/pry/core_extensions.rb +59 -38
  93. data/lib/pry/editor.rb +133 -0
  94. data/lib/pry/exceptions.rb +77 -0
  95. data/lib/pry/helpers.rb +1 -0
  96. data/lib/pry/helpers/base_helpers.rb +40 -154
  97. data/lib/pry/helpers/command_helpers.rb +19 -130
  98. data/lib/pry/helpers/documentation_helpers.rb +21 -11
  99. data/lib/pry/helpers/table.rb +109 -0
  100. data/lib/pry/helpers/text.rb +8 -9
  101. data/lib/pry/history.rb +61 -45
  102. data/lib/pry/history_array.rb +11 -1
  103. data/lib/pry/hooks.rb +10 -32
  104. data/lib/pry/indent.rb +110 -38
  105. data/lib/pry/input_completer.rb +242 -0
  106. data/lib/pry/input_lock.rb +132 -0
  107. data/lib/pry/inspector.rb +27 -0
  108. data/lib/pry/last_exception.rb +61 -0
  109. data/lib/pry/method.rb +199 -200
  110. data/lib/pry/method/disowned.rb +53 -0
  111. data/lib/pry/method/patcher.rb +125 -0
  112. data/lib/pry/method/weird_method_locator.rb +186 -0
  113. data/lib/pry/module_candidate.rb +39 -33
  114. data/lib/pry/object_path.rb +82 -0
  115. data/lib/pry/output.rb +50 -0
  116. data/lib/pry/pager.rb +234 -0
  117. data/lib/pry/plugins.rb +4 -3
  118. data/lib/pry/prompt.rb +26 -0
  119. data/lib/pry/pry_class.rb +199 -227
  120. data/lib/pry/pry_instance.rb +344 -403
  121. data/lib/pry/rbx_path.rb +1 -1
  122. data/lib/pry/repl.rb +202 -0
  123. data/lib/pry/repl_file_loader.rb +20 -26
  124. data/lib/pry/rubygem.rb +82 -0
  125. data/lib/pry/terminal.rb +79 -0
  126. data/lib/pry/test/helper.rb +170 -0
  127. data/lib/pry/version.rb +1 -1
  128. data/lib/pry/wrapped_module.rb +133 -48
  129. metadata +132 -197
  130. data/.document +0 -2
  131. data/.gemtest +0 -0
  132. data/.gitignore +0 -16
  133. data/.travis.yml +0 -17
  134. data/.yardopts +0 -1
  135. data/CHANGELOG +0 -387
  136. data/CONTRIBUTORS +0 -36
  137. data/Gemfile +0 -2
  138. data/Rakefile +0 -137
  139. data/TODO +0 -117
  140. data/examples/example_basic.rb +0 -15
  141. data/examples/example_command_override.rb +0 -32
  142. data/examples/example_commands.rb +0 -36
  143. data/examples/example_hooks.rb +0 -9
  144. data/examples/example_image_edit.rb +0 -67
  145. data/examples/example_input.rb +0 -7
  146. data/examples/example_input2.rb +0 -29
  147. data/examples/example_output.rb +0 -11
  148. data/examples/example_print.rb +0 -6
  149. data/examples/example_prompt.rb +0 -9
  150. data/examples/helper.rb +0 -6
  151. data/lib/pry/completion.rb +0 -221
  152. data/lib/pry/custom_completions.rb +0 -6
  153. data/lib/pry/default_commands/cd.rb +0 -81
  154. data/lib/pry/default_commands/commands.rb +0 -62
  155. data/lib/pry/default_commands/context.rb +0 -98
  156. data/lib/pry/default_commands/easter_eggs.rb +0 -95
  157. data/lib/pry/default_commands/editing.rb +0 -420
  158. data/lib/pry/default_commands/find_method.rb +0 -169
  159. data/lib/pry/default_commands/gems.rb +0 -84
  160. data/lib/pry/default_commands/gist.rb +0 -187
  161. data/lib/pry/default_commands/help.rb +0 -127
  162. data/lib/pry/default_commands/hist.rb +0 -120
  163. data/lib/pry/default_commands/input_and_output.rb +0 -306
  164. data/lib/pry/default_commands/introspection.rb +0 -410
  165. data/lib/pry/default_commands/ls.rb +0 -272
  166. data/lib/pry/default_commands/misc.rb +0 -38
  167. data/lib/pry/default_commands/navigating_pry.rb +0 -110
  168. data/lib/pry/default_commands/whereami.rb +0 -92
  169. data/lib/pry/extended_commands/experimental.rb +0 -7
  170. data/lib/pry/rbx_method.rb +0 -13
  171. data/man/pry.1 +0 -195
  172. data/man/pry.1.html +0 -204
  173. data/man/pry.1.ronn +0 -141
  174. data/pry.gemspec +0 -46
  175. data/test/candidate_helper1.rb +0 -11
  176. data/test/candidate_helper2.rb +0 -8
  177. data/test/helper.rb +0 -223
  178. data/test/test_cli.rb +0 -78
  179. data/test/test_code.rb +0 -201
  180. data/test/test_command.rb +0 -712
  181. data/test/test_command_helpers.rb +0 -9
  182. data/test/test_command_integration.rb +0 -668
  183. data/test/test_command_set.rb +0 -610
  184. data/test/test_completion.rb +0 -62
  185. data/test/test_control_d_handler.rb +0 -45
  186. data/test/test_default_commands/example.erb +0 -5
  187. data/test/test_default_commands/test_cd.rb +0 -318
  188. data/test/test_default_commands/test_context.rb +0 -280
  189. data/test/test_default_commands/test_documentation.rb +0 -314
  190. data/test/test_default_commands/test_find_method.rb +0 -50
  191. data/test/test_default_commands/test_gems.rb +0 -18
  192. data/test/test_default_commands/test_help.rb +0 -57
  193. data/test/test_default_commands/test_input.rb +0 -428
  194. data/test/test_default_commands/test_introspection.rb +0 -511
  195. data/test/test_default_commands/test_ls.rb +0 -151
  196. data/test/test_default_commands/test_shell.rb +0 -343
  197. data/test/test_default_commands/test_show_source.rb +0 -432
  198. data/test/test_exception_whitelist.rb +0 -21
  199. data/test/test_history_array.rb +0 -65
  200. data/test/test_hooks.rb +0 -521
  201. data/test/test_indent.rb +0 -277
  202. data/test/test_input_stack.rb +0 -86
  203. data/test/test_method.rb +0 -401
  204. data/test/test_pry.rb +0 -463
  205. data/test/test_pry_defaults.rb +0 -419
  206. data/test/test_pry_history.rb +0 -84
  207. data/test/test_pry_output.rb +0 -41
  208. data/test/test_sticky_locals.rb +0 -155
  209. data/test/test_syntax_checking.rb +0 -65
  210. data/test/test_wrapped_module.rb +0 -174
  211. data/test/testrc +0 -2
  212. data/test/testrcbad +0 -2
  213. data/wiki/Customizing-pry.md +0 -397
  214. data/wiki/Home.md +0 -4
@@ -0,0 +1,53 @@
1
+ class Pry
2
+ class Method
3
+ # A Disowned Method is one that's been removed from the class on which it was defined.
4
+ #
5
+ # e.g.
6
+ # class C
7
+ # def foo
8
+ # C.send(:undefine_method, :foo)
9
+ # Pry::Method.from_binding(binding)
10
+ # end
11
+ # end
12
+ #
13
+ # In this case we assume that the "owner" is the singleton class of the receiver.
14
+ #
15
+ # This occurs mainly in Sinatra applications.
16
+ class Disowned < Method
17
+ attr_reader :receiver, :name
18
+
19
+ # Create a new Disowned method.
20
+ #
21
+ # @param [Object] receiver
22
+ # @param [String] method_name
23
+ def initialize(receiver, method_name, binding=nil)
24
+ @receiver, @name = receiver, method_name
25
+ end
26
+
27
+ # Is the method undefined? (aka `Disowned`)
28
+ # @return [Boolean] true
29
+ def undefined?
30
+ true
31
+ end
32
+
33
+ # Can we get the source for this method?
34
+ # @return [Boolean] false
35
+ def source?
36
+ false
37
+ end
38
+
39
+ # Get the hypothesized owner of the method.
40
+ #
41
+ # @return [Object]
42
+ def owner
43
+ class << receiver; self; end
44
+ end
45
+
46
+ # Raise a more useful error message instead of trying to forward to nil.
47
+ def method_missing(meth_name, *args, &block)
48
+ raise "Cannot call '#{meth_name}' on an undef'd method." if method(:name).respond_to?(meth_name)
49
+ Object.instance_method(:method_missing).bind(self).call(meth_name, *args, &block)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,125 @@
1
+ class Pry
2
+ class Method
3
+ class Patcher
4
+ attr_accessor :method
5
+
6
+ @@source_cache = {}
7
+
8
+ def initialize(method)
9
+ @method = method
10
+ end
11
+
12
+ def self.code_for(filename)
13
+ @@source_cache[filename]
14
+ end
15
+
16
+ # perform the patch
17
+ def patch_in_ram(source)
18
+ if method.alias?
19
+ with_method_transaction do
20
+ redefine source
21
+ end
22
+ else
23
+ redefine source
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def redefine(source)
30
+ @@source_cache[cache_key] = source
31
+ TOPLEVEL_BINDING.eval wrap(source), cache_key
32
+ end
33
+
34
+ def cache_key
35
+ "pry-redefined(0x#{method.owner.object_id.to_s(16)}##{method.name})"
36
+ end
37
+
38
+ # Run some code ensuring that at the end target#meth_name will not have changed.
39
+ #
40
+ # When we're redefining aliased methods we will overwrite the method at the
41
+ # unaliased name (so that super continues to work). By wrapping that code in a
42
+ # transation we make that not happen, which means that alias_method_chains, etc.
43
+ # continue to work.
44
+ #
45
+ # @param [String] meth_name The method name before aliasing
46
+ # @param [Module] target The owner of the method
47
+
48
+ def with_method_transaction
49
+ temp_name = "__pry_#{method.original_name}__"
50
+ method = self.method
51
+ method.owner.class_eval do
52
+ alias_method temp_name, method.original_name
53
+ yield
54
+ alias_method method.name, method.original_name
55
+ alias_method method.original_name, temp_name
56
+ end
57
+
58
+ ensure
59
+ method.send(:remove_method, temp_name) rescue nil
60
+ end
61
+
62
+ # Update the definition line so that it can be eval'd directly on the Method's
63
+ # owner instead of from the original context.
64
+ #
65
+ # In particular this takes `def self.foo` and turns it into `def foo` so that we
66
+ # don't end up creating the method on the singleton class of the singleton class
67
+ # by accident.
68
+ #
69
+ # This is necessarily done by String manipulation because we can't find out what
70
+ # syntax is needed for the argument list by ruby-level introspection.
71
+ #
72
+ # @param [String] line The original definition line. e.g. def self.foo(bar, baz=1)
73
+ # @return [String] The new definition line. e.g. def foo(bar, baz=1)
74
+ def definition_for_owner(line)
75
+ if line =~ /\Adef (?:.*?\.)?#{Regexp.escape(method.original_name)}(?=[\(\s;]|$)/
76
+ "def #{method.original_name}#{$'}"
77
+ else
78
+ raise CommandError, "Could not find original `def #{method.original_name}` line to patch."
79
+ end
80
+ end
81
+
82
+ # Apply wrap_for_owner and wrap_for_nesting successively to `source`
83
+ # @param [String] source
84
+ # @return [String] The wrapped source.
85
+ def wrap(source)
86
+ wrap_for_nesting(wrap_for_owner(source))
87
+ end
88
+
89
+ # Update the source code so that when it has the right owner when eval'd.
90
+ #
91
+ # This (combined with definition_for_owner) is backup for the case that
92
+ # wrap_for_nesting fails, to ensure that the method will stil be defined in
93
+ # the correct place.
94
+ #
95
+ # @param [String] source The source to wrap
96
+ # @return [String]
97
+ def wrap_for_owner(source)
98
+ Pry.current[:pry_owner] = method.owner
99
+ owner_source = definition_for_owner(source)
100
+ visibility_fix = "#{method.visibility.to_s} #{method.name.to_sym.inspect}"
101
+ "Pry.current[:pry_owner].class_eval do; #{owner_source}\n#{visibility_fix}\nend"
102
+ end
103
+
104
+ # Update the new source code to have the correct Module.nesting.
105
+ #
106
+ # This method uses syntactic analysis of the original source file to determine
107
+ # the new nesting, so that we can tell the difference between:
108
+ #
109
+ # class A; def self.b; end; end
110
+ # class << A; def b; end; end
111
+ #
112
+ # The resulting code should be evaluated in the TOPLEVEL_BINDING.
113
+ #
114
+ # @param [String] source The source to wrap.
115
+ # @return [String]
116
+ def wrap_for_nesting(source)
117
+ nesting = Pry::Code.from_file(method.source_file).nesting_at(method.source_line)
118
+
119
+ (nesting + [source] + nesting.map{ "end" } + [""]).join(";")
120
+ rescue Pry::Indent::UnparseableNestingError
121
+ source
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,186 @@
1
+ class Pry
2
+ class Method
3
+
4
+ # This class is responsible for locating the *real* `Pry::Method`
5
+ # object captured by a binding.
6
+ #
7
+ # Given a `Binding` from inside a method and a 'seed' Pry::Method object,
8
+ # there are primarily two situations where the seed method doesn't match
9
+ # the Binding:
10
+ # 1. The Pry::Method is from a subclass 2. The Pry::Method represents a method of the same name
11
+ # while the original was renamed to something else. For 1. we
12
+ # search vertically up the inheritance chain,
13
+ # and for 2. we search laterally along the object's method table.
14
+ #
15
+ # When we locate the method that matches the Binding we wrap it in
16
+ # Pry::Method and return it, or return nil if we fail.
17
+ class WeirdMethodLocator
18
+ class << self
19
+
20
+ # Whether the given method object matches the associated binding.
21
+ # If the method object does not match the binding, then it's
22
+ # most likely not the method captured by the binding, and we
23
+ # must commence a search.
24
+ #
25
+ # @param [Pry::Method] method
26
+ # @param [Binding] b
27
+ # @return [Boolean]
28
+ def normal_method?(method, b)
29
+ method && (method.source_file && method.source_range rescue false) &&
30
+ File.expand_path(method.source_file) == File.expand_path(b.eval('__FILE__')) &&
31
+ method.source_range.include?(b.eval('__LINE__'))
32
+ end
33
+
34
+ def weird_method?(method, b)
35
+ !normal_method?(method, b)
36
+ end
37
+ end
38
+
39
+ attr_accessor :method
40
+ attr_accessor :target
41
+
42
+ # @param [Pry::Method] method The seed method.
43
+ # @param [Binding] target The Binding that captures the method
44
+ # we want to locate.
45
+ def initialize(method, target)
46
+ @method, @target = method, target
47
+ end
48
+
49
+ # @return [Pry::Method, nil] The Pry::Method that matches the
50
+ # given binding.
51
+ def get_method
52
+ find_method_in_superclass || find_renamed_method
53
+ end
54
+
55
+ # @return [Boolean] Whether the Pry::Method is unrecoverable
56
+ # This usually happens when the method captured by the Binding
57
+ # has been subsequently deleted.
58
+ def lost_method?
59
+ !!(get_method.nil? && renamed_method_source_location)
60
+ end
61
+
62
+ private
63
+
64
+ def normal_method?(method)
65
+ self.class.normal_method?(method, target)
66
+ end
67
+
68
+ def target_self
69
+ target.eval('self')
70
+ end
71
+
72
+ def target_file
73
+ pry_file? ? target.eval('__FILE__') : File.expand_path(target.eval('__FILE__'))
74
+ end
75
+
76
+ def target_line
77
+ target.eval('__LINE__')
78
+ end
79
+
80
+ def pry_file?
81
+ Pry.eval_path == target.eval('__FILE__')
82
+ end
83
+
84
+ # it's possible in some cases that the method we find by this approach is a sub-method of
85
+ # the one we're currently in, consider:
86
+ #
87
+ # class A; def b; binding.pry; end; end
88
+ # class B < A; def b; super; end; end
89
+ #
90
+ # Given that we can normally find the source_range of methods, and that we know which
91
+ # __FILE__ and __LINE__ the binding is at, we can hope to disambiguate these cases.
92
+ #
93
+ # This obviously won't work if the source is unavaiable for some reason, or if both
94
+ # methods have the same __FILE__ and __LINE__, or if we're in rbx where b.eval('__LINE__')
95
+ # is broken.
96
+ #
97
+ # @return [Pry::Method, nil] The Pry::Method representing the
98
+ # superclass method.
99
+ def find_method_in_superclass
100
+ guess = method
101
+
102
+ while guess
103
+ # needs rescue if this is a Disowned method or a C method or something...
104
+ # TODO: Fix up the exception handling so we don't need a bare rescue
105
+ if normal_method?(guess)
106
+ return guess
107
+ else
108
+ guess = guess.super
109
+ end
110
+ end
111
+
112
+ # Uhoh... none of the methods in the chain had the right __FILE__ and __LINE__
113
+ # This may be caused by rbx https://github.com/rubinius/rubinius/issues/953,
114
+ # or other unknown circumstances (TODO: we should warn the user when this happens)
115
+ nil
116
+ end
117
+
118
+ # This is the case where the name of a method has changed
119
+ # (via alias_method) so we locate the Method object for the
120
+ # renamed method.
121
+ #
122
+ # @return [Pry::Method, nil] The Pry::Method representing the
123
+ # renamed method
124
+ def find_renamed_method
125
+ return if !valid_file?(target_file)
126
+ alias_name = all_methods_for(target_self).find do |v|
127
+ expanded_source_location(target_self.method(v).source_location) == renamed_method_source_location
128
+ end
129
+
130
+ alias_name && Pry::Method(target_self.method(alias_name))
131
+ end
132
+
133
+ def expanded_source_location(sl)
134
+ return if !sl
135
+
136
+ if pry_file?
137
+ sl
138
+ else
139
+ [File.expand_path(sl.first), sl.last]
140
+ end
141
+ end
142
+
143
+ # Use static analysis to locate the start of the method definition.
144
+ # We have the `__FILE__` and `__LINE__` from the binding and the
145
+ # original name of the method so we search up until we find a
146
+ # def/define_method, etc defining a method of the appropriate name.
147
+ #
148
+ # @return [Array<String, Fixnum>] The `source_location` of the
149
+ # renamed method
150
+ def renamed_method_source_location
151
+ return @original_method_source_location if defined?(@original_method_source_location)
152
+
153
+ source_index = lines_for_file(target_file)[0..(target_line - 1)].rindex do |v|
154
+ Pry::Method.method_definition?(method.name, v)
155
+ end
156
+
157
+ @original_method_source_location = source_index &&
158
+ [target_file, index_to_line_number(source_index)]
159
+ end
160
+
161
+ def index_to_line_number(index)
162
+ # Pry.line_buffer is 0-indexed
163
+ pry_file? ? index : index + 1
164
+ end
165
+
166
+ def valid_file?(file)
167
+ (File.exists?(file) && !File.directory?(file)) || Pry.eval_path == file
168
+ end
169
+
170
+ def lines_for_file(file)
171
+ @lines_for_file ||= {}
172
+ @lines_for_file[file] ||= if Pry.eval_path == file
173
+ Pry.line_buffer
174
+ else
175
+ File.readlines(file)
176
+ end
177
+ end
178
+
179
+ def all_methods_for(obj)
180
+ obj.public_methods(false) +
181
+ obj.private_methods(false) +
182
+ obj.protected_methods(false)
183
+ end
184
+ end
185
+ end
186
+ end
@@ -8,21 +8,29 @@ class Pry
8
8
  # It provides access to the source, documentation, line and file
9
9
  # for a monkeypatch (reopening) of a class/module.
10
10
  class Candidate
11
+ include Pry::Helpers::DocumentationHelpers
12
+ include Pry::CodeObject::Helpers
11
13
  extend Forwardable
12
14
 
13
15
  # @return [String] The file where the module definition is located.
14
16
  attr_reader :file
17
+ alias_method :source_file, :file
15
18
 
16
19
  # @return [Fixnum] The line where the module definition is located.
17
20
  attr_reader :line
21
+ alias_method :source_line, :line
18
22
 
19
- # Methods to delegate to associated `Pry::WrappedModule instance`.
20
- to_delegate = [:lines_for_file, :method_candidates, :name, :wrapped,
21
- :yard_docs?, :number_of_candidates, :process_doc,
22
- :strip_leading_whitespace]
23
+ # Methods to delegate to associated `Pry::WrappedModule
24
+ # instance`.
25
+ private_delegates = [:lines_for_file, :method_candidates,
26
+ :yard_docs?]
23
27
 
24
- def_delegators :@wrapper, *to_delegate
25
- private(*to_delegate)
28
+ public_delegates = [:wrapped, :module?, :class?, :name, :nonblank_name,
29
+ :number_of_candidates]
30
+
31
+ def_delegators :@wrapper, *(private_delegates + public_delegates)
32
+ private(*private_delegates)
33
+ public(*public_delegates)
26
34
 
27
35
  # @raise [Pry::CommandError] If `rank` is out of bounds.
28
36
  # @param [Pry::WrappedModule] wrapper The associated
@@ -49,8 +57,8 @@ class Pry
49
57
  # @return [String] The source for the candidate, i.e the
50
58
  # complete module/class definition.
51
59
  def source
60
+ return nil if file.nil?
52
61
  return @source if @source
53
- raise CommandError, "Could not locate source for #{wrapped}!" if file.nil?
54
62
 
55
63
  @source = strip_leading_whitespace(Pry::Code.from_file(file).expression_at(line, number_of_lines_in_first_chunk))
56
64
  end
@@ -58,10 +66,10 @@ class Pry
58
66
  # @raise [Pry::CommandError] If documentation cannot be found.
59
67
  # @return [String] The documentation for the candidate.
60
68
  def doc
69
+ return nil if file.nil?
61
70
  return @doc if @doc
62
- raise CommandError, "Could not locate doc for #{wrapped}!" if file.nil?
63
71
 
64
- @doc = process_doc(Pry::Code.from_file(file).comment_describing(line))
72
+ @doc = get_comment_content(Pry::Code.from_file(file).comment_describing(line))
65
73
  end
66
74
 
67
75
  # @return [Array, nil] A `[String, Fixnum]` pair representing the
@@ -70,39 +78,47 @@ class Pry
70
78
  def source_location
71
79
  return @source_location if @source_location
72
80
 
73
- mod_type_string = wrapped.class.to_s.downcase
74
81
  file, line = first_method_source_location
75
-
76
82
  return nil if !file.is_a?(String)
77
83
 
78
- class_regexes = [/^\s*#{mod_type_string}\s*(\w*)(::)?#{wrapped.name.split(/::/).last}/,
79
- /^\s*(::)?#{wrapped.name.split(/::/).last}\s*?=\s*?#{wrapped.class}/,
80
- /^\s*(::)?#{wrapped.name.split(/::/).last}\.(class|instance)_eval/]
81
-
82
- host_file_lines = lines_for_file(file)
83
-
84
- search_lines = host_file_lines[0..(line - 2)]
85
- idx = search_lines.rindex { |v| class_regexes.any? { |r| r =~ v } }
86
-
87
- @source_location = [file, idx + 1]
84
+ @source_location = [file, first_line_of_module_definition(file, line)]
88
85
  rescue Pry::RescuableException
89
86
  nil
90
87
  end
91
88
 
92
89
  private
93
90
 
91
+ # Locate the first line of the module definition.
92
+ # @param [String] file The file that contains the module
93
+ # definition (somewhere).
94
+ # @param [Fixnum] line The module definition should appear
95
+ # before this line (if it exists).
96
+ # @return [Fixnum] The line where the module is defined. This
97
+ # line number is one-indexed.
98
+ def first_line_of_module_definition(file, line)
99
+ searchable_lines = lines_for_file(file)[0..(line - 2)]
100
+ searchable_lines.rindex { |v| class_regexes.any? { |r| r =~ v } } + 1
101
+ end
102
+
103
+ def class_regexes
104
+ mod_type_string = wrapped.class.to_s.downcase
105
+ [/^\s*#{mod_type_string}\s+(?:(?:\w*)::)*?#{wrapped.name.split(/::/).last}/,
106
+ /^\s*(::)?#{wrapped.name.split(/::/).last}\s*?=\s*?#{wrapped.class}/,
107
+ /^\s*(::)?#{wrapped.name.split(/::/).last}\.(class|instance)_eval/]
108
+ end
109
+
94
110
  # This method is used by `Candidate#source_location` as a
95
111
  # starting point for the search for the candidate's definition.
96
112
  # @return [Array] The source location of the base method used to
97
113
  # calculate the source location of the candidate.
98
114
  def first_method_source_location
99
- @first_method_source_location ||= adjusted_source_location(method_candidates[@rank].first.source_location)
115
+ @first_method_source_location ||= method_candidates[@rank].first.source_location
100
116
  end
101
117
 
102
118
  # @return [Array] The source location of the last method in this
103
119
  # candidate's module definition.
104
120
  def last_method_source_location
105
- @end_method_source_location ||= adjusted_source_location(method_candidates[@rank].last.source_location)
121
+ @end_method_source_location ||= method_candidates[@rank].last.source_location
106
122
  end
107
123
 
108
124
  # Return the number of lines between the start of the class definition
@@ -115,16 +131,6 @@ class Pry
115
131
 
116
132
  end_method_line - line
117
133
  end
118
-
119
- def adjusted_source_location(sl)
120
- file, line = sl
121
-
122
- if file && RbxPath.is_core_path?(file)
123
- file = RbxPath.convert_path_to_full(file)
124
- end
125
-
126
- [file, line]
127
- end
128
134
  end
129
135
  end
130
136
  end