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

Sign up to get free protection for your applications and to get access to all the features.
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