pry-doc 0.9.0 → 0.10.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -3
- data/CHANGELOG.md +7 -1
- data/README.md +2 -8
- data/Rakefile +11 -9
- data/lib/pry-doc.rb +11 -227
- data/lib/pry-doc/{core_docs_19 → docs/19}/checksums +0 -0
- data/lib/pry-doc/{core_docs_19 → docs/19}/object_types +0 -0
- data/lib/pry-doc/{core_docs_19 → docs/19}/objects/root.dat +0 -0
- data/lib/pry-doc/{core_docs_19 → docs/19}/proxy_types +0 -0
- data/lib/pry-doc/{core_docs_20 → docs/20}/checksums +0 -0
- data/lib/pry-doc/{core_docs_20 → docs/20}/object_types +0 -0
- data/lib/pry-doc/{core_docs_20 → docs/20}/objects/root.dat +0 -0
- data/lib/pry-doc/{core_docs_20 → docs/20}/proxy_types +0 -0
- data/lib/pry-doc/{core_docs_21 → docs/21}/checksums +0 -0
- data/lib/pry-doc/{core_docs_21 → docs/21}/object_types +0 -0
- data/lib/pry-doc/{core_docs_21 → docs/21}/objects/root.dat +0 -0
- data/lib/pry-doc/{core_docs_21 → docs/21}/proxy_types +0 -0
- data/lib/pry-doc/{core_docs_22 → docs/22}/checksums +0 -0
- data/lib/pry-doc/{core_docs_22 → docs/22}/object_types +0 -0
- data/lib/pry-doc/{core_docs_22 → docs/22}/objects/root.dat +0 -0
- data/lib/pry-doc/{core_docs_22 → docs/22}/proxy_types +0 -0
- data/lib/pry-doc/{core_docs_23 → docs/23}/checksums +0 -0
- data/lib/pry-doc/{core_docs_23 → docs/23}/object_types +0 -0
- data/lib/pry-doc/{core_docs_23 → docs/23}/objects/root.dat +0 -0
- data/lib/pry-doc/{core_docs_23 → docs/23}/proxy_types +0 -0
- data/lib/pry-doc/docs/24/checksums +486 -0
- data/lib/pry-doc/docs/24/complete +0 -0
- data/lib/pry-doc/docs/24/object_types +0 -0
- data/lib/pry-doc/docs/24/objects/root.dat +0 -0
- data/lib/pry-doc/docs/24/proxy_types +0 -0
- data/lib/pry-doc/pry_ext/method_info.rb +188 -0
- data/lib/pry-doc/version.rb +1 -1
- data/pry-doc.gemspec +3 -3
- data/spec/helper.rb +8 -1
- data/spec/pry-doc_spec.rb +36 -39
- metadata +34 -28
File without changes
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,188 @@
|
|
1
|
+
class Pry
|
2
|
+
module MethodInfo
|
3
|
+
class << self
|
4
|
+
##
|
5
|
+
# Retrieve the YARD object that contains the method data.
|
6
|
+
#
|
7
|
+
# @param [Method, UnboundMethod] meth The method object
|
8
|
+
# @return [YARD::CodeObjects::MethodObject] the YARD data for the method
|
9
|
+
def info_for(meth)
|
10
|
+
cache(meth)
|
11
|
+
registry_lookup(meth)
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Retrieves aliases of the given method.
|
16
|
+
#
|
17
|
+
# @param [Method, UnboundMethod] meth The method object
|
18
|
+
# @return [Array<UnboundMethod>] the aliases of the given method if they
|
19
|
+
# exist, otherwise an empty array
|
20
|
+
def aliases(meth)
|
21
|
+
owner = meth.owner
|
22
|
+
name = meth.name
|
23
|
+
|
24
|
+
(owner.instance_methods + owner.private_instance_methods).uniq.map do |m|
|
25
|
+
aliased_method = owner.__send__(:instance_method, m)
|
26
|
+
|
27
|
+
next unless aliased_method == owner.__send__(:instance_method, name)
|
28
|
+
next if m == name
|
29
|
+
aliased_method
|
30
|
+
end.compact!
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# FIXME: this is unnecessarily limited to ext/ and lib/ directories.
|
35
|
+
#
|
36
|
+
# @return [String] the root directory of a given gem directory
|
37
|
+
def gem_root(dir)
|
38
|
+
return unless (index = dir.rindex(%r(/(?:lib|ext)(?:/|$))))
|
39
|
+
dir[0..index-1]
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
##
|
45
|
+
# Convert a method object into the `Class#method` string notation.
|
46
|
+
#
|
47
|
+
# @param [Method, UnboundMethod] meth
|
48
|
+
# @return [String] the method in string receiver notation
|
49
|
+
# @note This mess is needed to support all the modern Rubies. Somebody has
|
50
|
+
# to figure out a better way to distinguish between class methods and
|
51
|
+
# instance methods.
|
52
|
+
def receiver_notation_for(meth)
|
53
|
+
match = meth.inspect.match(/\A#<(?:Unbound)?Method: (.+)([#\.].+?)(?:\(.+\))?>\z/)
|
54
|
+
owner = meth.owner.to_s.sub(/#<.+?:(.+?)>/, '\1')
|
55
|
+
name = match[2]
|
56
|
+
name.sub!('#', '.') if match[1] =~ /\A#<Class:/
|
57
|
+
owner + name
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Checks whether `meth` is a class method.
|
62
|
+
#
|
63
|
+
# @param [Method, UnboundMethod] meth The method to check
|
64
|
+
# @return [Boolean] true if singleton, otherwise false
|
65
|
+
def is_singleton?(meth)
|
66
|
+
receiver_notation_for(meth).include?('.')
|
67
|
+
end
|
68
|
+
|
69
|
+
def registry_lookup(meth)
|
70
|
+
if (obj = YARD::Registry.at(receiver_notation_for(meth)))
|
71
|
+
return obj
|
72
|
+
end
|
73
|
+
|
74
|
+
if (aliases = aliases(meth)).any?
|
75
|
+
YARD::Registry.at(receiver_notation_for(aliases.first))
|
76
|
+
elsif meth.owner == Kernel
|
77
|
+
# YARD thinks that some methods are on Object when
|
78
|
+
# they're actually on Kernel; so try again on Object if Kernel fails.
|
79
|
+
YARD::Registry.at("Object##{meth.name}")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Attempts to find the C source files if method belongs to a gem and use
|
85
|
+
# YARD to parse and cache the source files for display.
|
86
|
+
#
|
87
|
+
# @param [Method, UnboundMethod] meth The method object
|
88
|
+
def parse_and_cache_if_gem_cext(meth)
|
89
|
+
return unless (gem_dir = find_gem_dir(meth))
|
90
|
+
|
91
|
+
path = "#{gem_dir}/**/*.c"
|
92
|
+
return if Dir.glob(path).none?
|
93
|
+
|
94
|
+
puts "Scanning and caching *.c files..."
|
95
|
+
YARD.parse(path)
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# @return [Object] the host of the method (receiver or owner)
|
100
|
+
def method_host(meth)
|
101
|
+
is_singleton?(meth) && Module === meth.receiver ? meth.receiver : meth.owner
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# @param [Method, UnboundMethod] meth The method object
|
106
|
+
# @return [String, nil] root directory path of gem that method belongs to
|
107
|
+
# or nil if could not be found
|
108
|
+
def find_gem_dir(meth)
|
109
|
+
host = method_host(meth)
|
110
|
+
|
111
|
+
begin
|
112
|
+
host_source_location, _ = WrappedModule.new(host).source_location
|
113
|
+
break if host_source_location != nil
|
114
|
+
return unless host.name
|
115
|
+
host = eval(host.namespace_name)
|
116
|
+
end while host
|
117
|
+
|
118
|
+
# We want to exclude all source_locations that aren't gems (i.e
|
119
|
+
# stdlib).
|
120
|
+
if host_source_location && host_source_location =~ %r{/gems/}
|
121
|
+
gem_root(host_source_location)
|
122
|
+
else
|
123
|
+
# The WrappedModule approach failed, so try our backup approach.
|
124
|
+
gem_dir_from_method(meth)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
##
|
129
|
+
# Try to guess what the gem name will be based on the name of the module.
|
130
|
+
#
|
131
|
+
# @param [String] name The name of the module
|
132
|
+
# @return [Enumerator] the enumerator which enumerates on possible names
|
133
|
+
# we try to guess
|
134
|
+
def guess_gem_name(name)
|
135
|
+
scanned_name = name.scan(/[A-z]+/).map(&:downcase)
|
136
|
+
|
137
|
+
Enumerator.new do |y|
|
138
|
+
y << name.downcase
|
139
|
+
y << scanned_name.join('_')
|
140
|
+
y << scanned_name.join('_').sub('_', '-')
|
141
|
+
y << scanned_name.join('-')
|
142
|
+
y << name
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
##
|
147
|
+
# Try to recover the gem directory of a gem based on a method object.
|
148
|
+
#
|
149
|
+
# @param [Method, UnboundMethod] meth The method object
|
150
|
+
# @return [String, nil] the located gem directory
|
151
|
+
def gem_dir_from_method(meth)
|
152
|
+
return unless (host = method_host(meth)).name
|
153
|
+
|
154
|
+
guess_gem_name(host.name.split('::').first).each do |guess|
|
155
|
+
matches = $LOAD_PATH.grep(%r(/gems/#{guess}))
|
156
|
+
return gem_root(matches.first) if matches.any?
|
157
|
+
end
|
158
|
+
|
159
|
+
nil
|
160
|
+
end
|
161
|
+
|
162
|
+
##
|
163
|
+
# Caches the file that holds the method.
|
164
|
+
#
|
165
|
+
# Cannot cache C stdlib and eval methods.
|
166
|
+
#
|
167
|
+
# @param [Method, UnboundMethod] meth The method object.
|
168
|
+
def cache(meth)
|
169
|
+
file, _ = meth.source_location
|
170
|
+
|
171
|
+
# Eval methods can't be cached.
|
172
|
+
return if file =~ /(\(.*\))|<.*>/
|
173
|
+
|
174
|
+
# No need to cache already cached methods.
|
175
|
+
return if registry_lookup(meth)
|
176
|
+
|
177
|
+
unless file
|
178
|
+
parse_and_cache_if_gem_cext(meth)
|
179
|
+
return
|
180
|
+
end
|
181
|
+
|
182
|
+
log.enter_level(Logger::FATAL) do
|
183
|
+
YARD.parse(file)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
data/lib/pry-doc/version.rb
CHANGED
data/pry-doc.gemspec
CHANGED
@@ -20,9 +20,9 @@ DESCR
|
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
s.files = `git ls-files`.split("\n")
|
22
22
|
|
23
|
-
s.add_dependency 'yard', "~> 0.
|
23
|
+
s.add_dependency 'yard', "~> 0.9"
|
24
24
|
s.add_dependency 'pry', "~> 0.9"
|
25
|
-
s.add_development_dependency 'latest_ruby',
|
26
|
-
s.add_development_dependency '
|
25
|
+
s.add_development_dependency 'latest_ruby', '~> 0.0'
|
26
|
+
s.add_development_dependency 'rspec', '~> 3.5'
|
27
27
|
s.add_development_dependency 'rake', "~> 10.0"
|
28
28
|
end
|
data/spec/helper.rb
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
require 'pry-doc'
|
2
|
+
|
3
|
+
RSpec.configure do |c|
|
4
|
+
c.order = 'random'
|
5
|
+
c.color = true
|
6
|
+
c.disable_monkey_patching!
|
7
|
+
end
|
8
|
+
|
1
9
|
direc = File.dirname(__FILE__)
|
2
10
|
|
3
11
|
class C
|
@@ -8,4 +16,3 @@ puts
|
|
8
16
|
puts "Building Sample Gem with C Extensions for testing.."
|
9
17
|
system("cd #{direc}/gem_with_cext/gems/ext/ && ruby extconf.rb && make")
|
10
18
|
puts
|
11
|
-
|
data/spec/pry-doc_spec.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
direc = File.dirname(__FILE__)
|
2
2
|
|
3
|
-
require 'rubygems'
|
4
3
|
require 'pry'
|
5
4
|
require "#{direc}/../lib/pry-doc"
|
6
5
|
require "#{direc}/helper"
|
7
6
|
require "#{direc}/gem_with_cext/gems/sample"
|
8
|
-
require 'bacon'
|
9
7
|
require 'set'
|
10
8
|
require 'fileutils'
|
11
9
|
require 'readline'
|
@@ -13,33 +11,33 @@ require 'readline'
|
|
13
11
|
puts "Testing pry-doc version #{PryDoc::VERSION}..."
|
14
12
|
puts "Ruby version: #{RUBY_VERSION}"
|
15
13
|
|
16
|
-
describe PryDoc do
|
14
|
+
RSpec.describe PryDoc do
|
17
15
|
|
18
16
|
describe "core C methods" do
|
19
17
|
it 'should look up core (C) methods' do
|
20
18
|
obj = Pry::MethodInfo.info_for(method(:puts))
|
21
|
-
obj.source.
|
19
|
+
expect(obj.source).not_to be_nil
|
22
20
|
end
|
23
21
|
|
24
22
|
it 'should look up core (C) instance methods' do
|
25
|
-
Module.module_eval do
|
26
|
-
|
27
|
-
obj.source.should.not == nil
|
23
|
+
obj = Module.module_eval do
|
24
|
+
Pry::MethodInfo.info_for(instance_method(:include))
|
28
25
|
end
|
26
|
+
expect(obj.source).not_to be_nil
|
29
27
|
end
|
30
28
|
|
31
29
|
it 'should look up core (C) class method (by Method object)' do
|
32
|
-
Module.module_eval do
|
33
|
-
|
34
|
-
obj.source.should.not == nil
|
30
|
+
obj = Module.module_eval do
|
31
|
+
Pry::MethodInfo.info_for(Dir.method(:glob))
|
35
32
|
end
|
33
|
+
expect(obj.source).not_to be_nil
|
36
34
|
end
|
37
35
|
|
38
36
|
it 'should look up core (C) class method (by UnboundMethod object)' do
|
39
|
-
Module.module_eval do
|
40
|
-
|
41
|
-
obj.source.should.not == nil
|
37
|
+
obj = Module.module_eval do
|
38
|
+
Pry::MethodInfo.info_for(class << Dir; instance_method(:glob); end)
|
42
39
|
end
|
40
|
+
expect(obj.source).not_to be_nil
|
43
41
|
end
|
44
42
|
end
|
45
43
|
|
@@ -47,26 +45,26 @@ describe PryDoc do
|
|
47
45
|
it 'should return nil for eval methods' do
|
48
46
|
TOPLEVEL_BINDING.eval("def hello; end")
|
49
47
|
obj = Pry::MethodInfo.info_for(method(:hello))
|
50
|
-
obj.
|
48
|
+
expect(obj).to be_nil
|
51
49
|
end
|
52
50
|
end
|
53
51
|
|
54
52
|
describe "pure ruby methods" do
|
55
53
|
it 'should look up ruby methods' do
|
56
54
|
obj = Pry::MethodInfo.info_for(C.new.method(:message))
|
57
|
-
obj.
|
55
|
+
expect(obj).not_to be_nil
|
58
56
|
end
|
59
57
|
|
60
58
|
it 'should look up ruby instance methods' do
|
61
59
|
obj = Pry::MethodInfo.info_for(C.instance_method(:message))
|
62
|
-
obj.
|
60
|
+
expect(obj).not_to be_nil
|
63
61
|
end
|
64
62
|
end
|
65
63
|
|
66
64
|
describe "Ruby stdlib methods" do
|
67
65
|
it "should look up ruby stdlib method" do
|
68
66
|
obj = Pry::MethodInfo.info_for(Set.instance_method(:union))
|
69
|
-
obj.
|
67
|
+
expect(obj).not_to be_nil
|
70
68
|
end
|
71
69
|
end
|
72
70
|
|
@@ -74,42 +72,42 @@ describe PryDoc do
|
|
74
72
|
|
75
73
|
it "should lookup C ext methods" do
|
76
74
|
obj = Pry::MethodInfo.info_for(Sample.instance_method(:gleezor))
|
77
|
-
obj.
|
75
|
+
expect(obj).not_to be_nil
|
78
76
|
end
|
79
77
|
|
80
78
|
it "should lookup aliased C ext methods" do
|
81
79
|
obj = Pry::MethodInfo.info_for(Sample.instance_method(:remove))
|
82
|
-
obj.
|
80
|
+
expect(obj).not_to be_nil
|
83
81
|
end
|
84
82
|
|
85
83
|
it "should lookup C ext instance methods even when its owners don't have any ruby methods" do
|
86
84
|
obj = Pry::MethodInfo.info_for(Sample::A::B.instance_method(:gleezor))
|
87
|
-
obj.
|
85
|
+
expect(obj).not_to be_nil
|
88
86
|
end
|
89
87
|
|
90
88
|
it "should lookup C ext class methods even when its owners don't have any ruby methods" do
|
91
89
|
obj = Pry::MethodInfo.info_for(Sample::A::B.method(:gleezor))
|
92
|
-
obj.
|
90
|
+
expect(obj).not_to be_nil
|
93
91
|
end
|
94
92
|
end
|
95
93
|
|
96
94
|
describe "C stdlib methods" do
|
97
95
|
it "finds them" do
|
98
96
|
obj = Pry::MethodInfo.info_for(Readline.method(:readline))
|
99
|
-
obj.
|
97
|
+
expect(obj).not_to be_nil
|
100
98
|
end
|
101
99
|
|
102
100
|
it "finds well hidden docs like BigDecimal docs" do
|
103
101
|
require 'bigdecimal'
|
104
102
|
obj = Pry::MethodInfo.info_for(BigDecimal.instance_method(:finite?))
|
105
|
-
obj.
|
103
|
+
expect(obj).not_to be_nil
|
106
104
|
end
|
107
105
|
end
|
108
106
|
|
109
107
|
describe ".aliases" do
|
110
108
|
it "should return empty array if method does not have any alias" do
|
111
109
|
aliases = Pry::MethodInfo.aliases(Sample.instance_method(:some_meth))
|
112
|
-
aliases.
|
110
|
+
expect(aliases).to be_empty
|
113
111
|
end
|
114
112
|
|
115
113
|
it "should return aliases of a (C) method" do
|
@@ -117,10 +115,10 @@ describe PryDoc do
|
|
117
115
|
copy = Sample.instance_method(:remove)
|
118
116
|
|
119
117
|
aliases = Pry::MethodInfo.aliases(orig)
|
120
|
-
aliases.
|
118
|
+
expect(aliases).to eq([copy])
|
121
119
|
|
122
120
|
aliases = Pry::MethodInfo.aliases(copy)
|
123
|
-
aliases.
|
121
|
+
expect(aliases).to eq([orig])
|
124
122
|
end
|
125
123
|
|
126
124
|
it "should return aliases of a ruby method" do
|
@@ -130,10 +128,10 @@ describe PryDoc do
|
|
130
128
|
copy = C.instance_method(:msg)
|
131
129
|
|
132
130
|
aliases = Pry::MethodInfo.aliases(orig)
|
133
|
-
aliases.
|
131
|
+
expect(aliases).to eq([copy])
|
134
132
|
|
135
133
|
aliases = Pry::MethodInfo.aliases(copy)
|
136
|
-
aliases.
|
134
|
+
expect(aliases).to eq([orig])
|
137
135
|
end
|
138
136
|
|
139
137
|
it "should return aliases of protected method" do
|
@@ -141,7 +139,7 @@ describe PryDoc do
|
|
141
139
|
copy = Sample.instance_method(:remove_1)
|
142
140
|
|
143
141
|
aliases = Pry::MethodInfo.aliases(orig)
|
144
|
-
aliases.
|
142
|
+
expect(aliases).to eq([copy])
|
145
143
|
end
|
146
144
|
|
147
145
|
it "should return aliases of private method" do
|
@@ -149,7 +147,7 @@ describe PryDoc do
|
|
149
147
|
copy = Sample.instance_method(:remove_2)
|
150
148
|
|
151
149
|
aliases = Pry::MethodInfo.aliases(orig)
|
152
|
-
aliases.
|
150
|
+
expect(aliases).to eq([copy])
|
153
151
|
end
|
154
152
|
|
155
153
|
it 'does not error when given a singleton method' do
|
@@ -157,16 +155,15 @@ describe PryDoc do
|
|
157
155
|
def self.my_method; end
|
158
156
|
end
|
159
157
|
|
160
|
-
|
158
|
+
expect { Pry::MethodInfo.aliases(c.method(:my_method)) }.not_to raise_error
|
161
159
|
end
|
162
160
|
end
|
163
161
|
|
164
162
|
describe ".gem_root" do
|
165
163
|
it "should return the path to the gem" do
|
166
164
|
path = Pry::WrappedModule.new(Sample).source_location[0]
|
167
|
-
|
168
|
-
|
169
|
-
File.expand_path("gem_with_cext/gems", direc)
|
165
|
+
expect(Pry::MethodInfo.gem_root(path)).
|
166
|
+
to eq(File.expand_path("gem_with_cext/gems", direc))
|
170
167
|
end
|
171
168
|
|
172
169
|
it "should not be fooled by a parent 'lib' or 'ext' dir" do
|
@@ -174,16 +171,16 @@ describe PryDoc do
|
|
174
171
|
"1.9.1/gems/activesupport-4.0.2/lib/active_support/"\
|
175
172
|
"core_ext/kernel/reporting.rb"
|
176
173
|
|
177
|
-
Pry::MethodInfo.gem_root(path)
|
178
|
-
|
179
|
-
|
174
|
+
expect(Pry::MethodInfo.gem_root(path))
|
175
|
+
.to eq('/foo/.rbenv/versions/1.9.3-p429/lib/ruby/' \
|
176
|
+
'gems/1.9.1/gems/activesupport-4.0.2')
|
180
177
|
end
|
181
178
|
end
|
182
179
|
|
183
180
|
describe "1.9 and higher specific docs" do
|
184
181
|
it "finds Kernel#require_relative" do
|
185
182
|
obj = Pry::MethodInfo.info_for(Kernel.instance_method(:require_relative))
|
186
|
-
obj.
|
183
|
+
expect(obj).not_to be_nil
|
187
184
|
end
|
188
185
|
end
|
189
186
|
|
@@ -192,7 +189,7 @@ describe PryDoc do
|
|
192
189
|
describe "2.0 specific docs" do
|
193
190
|
it "finds Module#refine" do
|
194
191
|
obj = Pry::MethodInfo.info_for(Module.instance_method(:refine))
|
195
|
-
obj.
|
192
|
+
expect(obj).not_to be_nil
|
196
193
|
end
|
197
194
|
end
|
198
195
|
end
|