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