core_docs 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ef9c9b9dc66c55c7cfa891c263014f2c2e76d7eb
4
+ data.tar.gz: 987df53f273c819846120fcc6f09b8274cc1cbec
5
+ SHA512:
6
+ metadata.gz: db62934c09ab1be4ca56cc44a93a95e1f1908a3cc41259cd49044d4cc5d72e8a5ce8d263ba94691ef76aef61db6c8259e81fb04aeb1eaef20a4f7c10b7752d5e
7
+ data.tar.gz: b23f4960d820ab46968dca9d17bb8ab6ff2644ee9e393f569df1228ea1a61e6282194ce847c2571ccdbece946f95dce8965863680409be0cfba81c5de1dbff5d
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ Makefile
2
+ *.so
3
+ *.o
4
+ *.def
5
+ doc/
6
+ pkg/
7
+ .yardoc/
8
+ *.gem
9
+ Gemfile.lock
10
+ *~
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ rvm:
2
+ - 1.9.3
3
+ - 2.0.0
4
+ - 2.1.0
5
+ - 2.1.1
6
+ - ruby-head
7
+
8
+ script:
9
+ - rake spec
10
+
11
+ branches:
12
+ only:
13
+ - master
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup markdown
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ Core Docs changelog
2
+ ===================
3
+
4
+ ### v0.9.0
5
+
6
+ * Ported from pry-doc
7
+ * Remove 1.9, add 2.2, and rebuild 2.1, 2.0 docs
8
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
data/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ License
2
+ -------
3
+
4
+ (The MIT License)
5
+
6
+ Copyright (c) 2013 John Mair (banisterfiend)
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining
9
+ a copy of this software and associated documentation files (the
10
+ 'Software'), to deal in the Software without restriction, including
11
+ without limitation the rights to use, copy, modify, merge, publish,
12
+ distribute, sublicense, and/or sell copies of the Software, and to
13
+ permit persons to whom the Software is furnished to do so, subject to
14
+ the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be
17
+ included in all copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
20
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,18 @@
1
+ MRI Core Docs
2
+ =============
3
+
4
+ Core Docs is a fork from [pry-doc](https://github.com/pry/pry-doc) that separates its functionality from the pry repl.
5
+
6
+ Experimental, don't consider this battle-proof.
7
+
8
+
9
+ TODO
10
+ ----
11
+
12
+ Polish and get specs to run.
13
+
14
+
15
+ License
16
+ -------
17
+
18
+ The project uses the MIT Licencse. See LICENSE file for more information.
data/Rakefile ADDED
@@ -0,0 +1,107 @@
1
+ dlext = RbConfig::CONFIG['DLEXT']
2
+ direc = File.dirname(__FILE__)
3
+
4
+ PROJECT_NAME = "core_docs"
5
+
6
+ require 'latest_ruby'
7
+ require 'rake/clean'
8
+ require "#{direc}/lib/#{PROJECT_NAME}/version"
9
+
10
+ desc "run tests"
11
+ task :test do
12
+ sh "bacon -k #{direc}/spec/core_docs_spec.rb"
13
+ end
14
+ task :spec => :test
15
+
16
+ task :default => :test
17
+
18
+ desc "reinstall gem"
19
+ task :reinstall => :gems do
20
+ sh "gem uninstall core_docs" rescue nil
21
+ sh "gem install #{direc}/pkg/core_docs-#{CoreDocs::VERSION}.gem"
22
+ end
23
+
24
+ desc "build all platform gems at once"
25
+ task :gems => :rmgems do
26
+ mkdir_p "pkg"
27
+ sh 'gem build *.gemspec'
28
+ mv "core_docs-#{CoreDocs::VERSION}.gem", "pkg"
29
+ end
30
+
31
+ desc "remove all platform gems"
32
+ task :rmgems do
33
+ rm_rf 'pkg'
34
+ end
35
+
36
+ desc "Build gemspec"
37
+ task :gemspec => "ruby:gemspec"
38
+
39
+ desc "Show version"
40
+ task :version do
41
+ puts "CoreDocs version: #{CoreDocs::VERSION}"
42
+ end
43
+
44
+ desc "build and push latest gems"
45
+ task :pushgems => :gems do
46
+ chdir("#{direc}/pkg") do
47
+ Dir["*.gem"].each do |gemfile|
48
+ sh "gem push #{gemfile}"
49
+ end
50
+ end
51
+ end
52
+
53
+ def download_ruby(ruby)
54
+ system "mkdir rubies"
55
+ system "wget #{ ruby.link } --directory-prefix=rubies --no-clobber"
56
+ File.join('rubies', ruby.filename)
57
+ end
58
+
59
+ def unpackage_ruby(path)
60
+ system "mkdir rubies/ruby"
61
+ system "tar xzvf #{ path } --directory=rubies/ruby"
62
+ end
63
+
64
+ def cd_into_ruby
65
+ Dir.chdir(Dir['rubies/ruby/*'].first)
66
+ end
67
+
68
+ def generate_yard
69
+ system %{
70
+ bash -c "paste <(find . -maxdepth 1 -name '*.c') <(find ext -name '*.c') |
71
+ xargs yardoc --no-output"
72
+ }
73
+ end
74
+
75
+ def replace_existing_docs(ver)
76
+ target_dir = "../../../lib/core_docs/core_docs_#{ ver }"
77
+ system %|mkdir -p #{ target_dir } && cp -r .yardoc/* #{ target_dir }|
78
+ Dir.chdir(File.expand_path(File.dirname(__FILE__)))
79
+ end
80
+
81
+ def clean_up
82
+ system "rm -rf rubies"
83
+ end
84
+
85
+ def generate_docs_for(ruby_ver, latest_ruby)
86
+ path = download_ruby(latest_ruby)
87
+ unpackage_ruby(path)
88
+ cd_into_ruby
89
+ generate_yard
90
+ replace_existing_docs(ruby_ver)
91
+ clean_up
92
+ end
93
+
94
+ desc "Generate the latest Ruby 2.0 docs"
95
+ task "gen20" do
96
+ generate_docs_for('20', Latest.ruby20)
97
+ end
98
+
99
+ desc "Generate the latest Ruby 2.1 docs"
100
+ task "gen21" do
101
+ generate_docs_for('21', Latest.ruby21)
102
+ end
103
+
104
+ desc "Generate the latest Ruby 2.2 docs"
105
+ task "gen22" do
106
+ generate_docs_for('22', Latest.ruby22)
107
+ end
data/core_docs.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ require './lib/core_docs/version.rb'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "core_docs"
5
+ s.version = CoreDocs::VERSION
6
+
7
+ s.authors = ["John Mair (banisterfiend)", "Jan Lelis (non-pry version)"]
8
+ s.email = ["jrmair@gmail.com", "mail@janlelis.de"]
9
+ s.summary = 'Provides YARD and extended documentation support for Pry'
10
+ s.description = <<DESCR
11
+ Pry Doc is a Pry REPL plugin. It provides extended documentation support for the
12
+ REPL by means of improving the `show-doc` and `show-source` commands. With help
13
+ of the plugin the commands are be able to display the source code and the docs
14
+ of Ruby methods and classes implemented in C.
15
+ documentation
16
+ DESCR
17
+ s.homepage = "https://github.com/janlelis/core_docs"
18
+ s.license = 'MIT'
19
+
20
+ s.require_paths = ["lib"]
21
+ s.files = `git ls-files`.split("\n")
22
+
23
+ s.required_ruby_version = "~> 2.0"
24
+ s.add_dependency 'yard', "~> 0.8"
25
+ s.add_development_dependency 'latest_ruby', "~> 0.0"
26
+ s.add_development_dependency 'bacon', "~> 1.1"
27
+ end
data/lib/core_docs.rb ADDED
@@ -0,0 +1,228 @@
1
+ # based on pry-doc.rb
2
+ # (C) John Mair (banisterfiend); MIT license
3
+
4
+ direc = File.dirname(__FILE__)
5
+
6
+ require "#{direc}/core_docs/version"
7
+ require "yard"
8
+
9
+ module CoreDocs
10
+ def self.load_yardoc(version)
11
+ path = "#{File.dirname(__FILE__)}/core_docs/core_docs_#{ version }"
12
+ YARD::Registry.load_yardoc(path)
13
+ end
14
+ end
15
+
16
+ case RUBY_VERSION
17
+ when /\A2\.1/
18
+ CoreDocs.load_yardoc('21')
19
+ else
20
+ CoreDocs.load_yardoc('20')
21
+ end
22
+
23
+ # do not use pry-doc if rbx is active
24
+ # if !Object.const_defined?(:RUBY_ENGINE) || RUBY_ENGINE !~ /rbx/
25
+ # self.config.has_pry_doc = true
26
+ # end
27
+
28
+ module CoreDocs
29
+ module MethodInfo
30
+
31
+ # Convert a method object into the `Class#method` string notation.
32
+ # @param [Method, UnboundMethod] meth
33
+ # @return [String] The method in string receiver notation.
34
+ # @note This mess is needed in order to support all the modern Rubies. YOU
35
+ # must figure out a better way to distinguish between class methods and
36
+ # instance methods.
37
+ def self.receiver_notation_for(meth)
38
+ match = meth.inspect.match(/\A#<(?:Unbound)?Method: (.+)([#\.].+)>\z/)
39
+ owner = meth.owner.to_s.sub(/#<.+?:(.+?)>/, '\1')
40
+ name = match[2]
41
+ name.sub!('#', '.') if match[1] =~ /\A#<Class:/
42
+ owner + name
43
+ end
44
+
45
+ # Retrives aliases of a method
46
+ # @param [Method, UnboundMethod] meth The method object.
47
+ # @return [Array] The aliases of a method if it exists
48
+ # otherwise, return empty array
49
+ def self.aliases(meth)
50
+ # host = is_singleton?(meth) ? meth.receiver : meth.owner
51
+ # method_type = is_singleton?(meth) ? :method : :instance_method
52
+
53
+ # methods = Pry::Method.send(:all_from_common, host, method_type, false).
54
+ # map { |m| m.instance_variable_get(:@method) }
55
+
56
+ # methods.select { |m| host.send(method_type,m.name) == host.send(method_type,meth.name) }.
57
+ # reject { |m| m.name == meth.name }.
58
+ # map { |m| host.send(method_type,m.name) }
59
+ []
60
+ end
61
+
62
+ # Checks whether method is a singleton (i.e class method)
63
+ # @param [Method, UnboundMethod] meth
64
+ # @param [Boolean] true if singleton
65
+ def self.is_singleton?(meth)
66
+ receiver_notation_for(meth).include?('.')
67
+ end
68
+
69
+ # Check whether the file containing the method is already cached.
70
+ # @param [Method, UnboundMethod] meth The method object.
71
+ # @return [Boolean] Whether the method is cached.
72
+ def self.cached?(meth)
73
+ !!registry_lookup(meth)
74
+ end
75
+
76
+ def self.registry_lookup(meth)
77
+ obj = YARD::Registry.at(receiver_notation_for(meth))
78
+ if obj.nil?
79
+ if !(aliases = aliases(meth)).empty?
80
+ obj = YARD::Registry.at(receiver_notation_for(aliases.first))
81
+ elsif meth.owner == Kernel
82
+ # YARD thinks that some methods are on Object when
83
+ # they're actually on Kernel; so try again on Object if Kernel fails.
84
+ obj = YARD::Registry.at("Object##{meth.name}")
85
+ end
86
+ end
87
+ obj
88
+ end
89
+
90
+ # Retrieve the YARD object that contains the method data.
91
+ # @param [Method, UnboundMethod] meth The method object.
92
+ # @return [YARD::CodeObjects::MethodObject] The YARD data for the method.
93
+ def self.info_for(meth)
94
+ cache(meth)
95
+ registry_lookup(meth)
96
+ end
97
+
98
+ # Determine whether a method is an eval method.
99
+ # @return [Boolean] Whether the method is an eval method.
100
+ def self.is_eval_method?(meth)
101
+ file, _ = meth.source_location
102
+ if file =~ /(\(.*\))|<.*>/
103
+ true
104
+ else
105
+ false
106
+ end
107
+ end
108
+
109
+ # Attempts to find the c source files if method belongs to a gem
110
+ # and use YARD to parse and cache the source files for display
111
+ #
112
+ # @param [Method, UnboundMethod] meth The method object.
113
+ def self.parse_and_cache_if_gem_cext(meth)
114
+ if gem_dir = find_gem_dir(meth)
115
+ if c_files_found?(gem_dir)
116
+ warn "Scanning and caching *.c files..."
117
+ YARD.parse("#{gem_dir}/**/*.c")
118
+ end
119
+ end
120
+ end
121
+
122
+ # @param [String] root directory path of gem that method belongs to
123
+ # @return [Boolean] true if c files exist?
124
+ def self.c_files_found?(gem_dir)
125
+ Dir.glob("#{gem_dir}/**/*.c").count > 0
126
+ end
127
+
128
+ # @return [Object] The host of the method (receiver or owner).
129
+ def self.method_host(meth)
130
+ is_singleton?(meth) && Module === meth.receiver ? meth.receiver : meth.owner
131
+ end
132
+
133
+ # FIXME: this is unnecessarily limited to ext/ and lib/ folders
134
+ # @return [String] The root folder of a given gem directory.
135
+ def self.gem_root(dir)
136
+ if index = dir.rindex(/\/(?:lib|ext)(?:\/|$)/)
137
+ dir[0..index-1]
138
+ end
139
+ end
140
+
141
+ # @param [Method, UnboundMethod] meth The method object.
142
+ # @return [String] root directory path of gem that method belongs to,
143
+ # nil if could not be found
144
+ def self.find_gem_dir(meth)
145
+ # host = method_host(meth)
146
+
147
+ # begin
148
+ # host_source_location, _ = WrappedModule.new(host).source_location
149
+ # break if host_source_location != nil
150
+ # return unless host.name
151
+ # host = eval(host.namespace_name)
152
+ # end while host
153
+
154
+ # # we want to exclude all source_locations that aren't gems (i.e
155
+ # # stdlib)
156
+ # if host_source_location && host_source_location =~ %r{/gems/}
157
+ # gem_root(host_source_location)
158
+ # else
159
+
160
+ # the WrappedModule approach failed, so try our backup approach
161
+ gem_dir_from_method(meth)
162
+ # end
163
+ end
164
+
165
+ # Try to guess what the gem name will be based on the name of the module.
166
+ # We try a few approaches here depending on the `guess` parameter.
167
+ # @param [String] name The name of the module.
168
+ # @param [Fixnum] guess The current guessing approach to use.
169
+ # @return [String, nil] The guessed gem name, or `nil` if out of guesses.
170
+ def self.guess_gem_name_from_module_name(name, guess)
171
+ case guess
172
+ when 0
173
+ name.downcase
174
+ when 1
175
+ name.scan(/[A-Z][a-z]+/).map(&:downcase).join('_')
176
+ when 2
177
+ name.scan(/[A-Z][a-z]+/).map(&:downcase).join('_').sub("_", "-")
178
+ when 3
179
+ name.scan(/[A-Z][a-z]+/).map(&:downcase).join('-')
180
+ when 4
181
+ name
182
+ else
183
+ nil
184
+ end
185
+ end
186
+
187
+ # Try to recover the gem directory of a gem based on a method object.
188
+ # @param [Method, UnboundMethod] meth The method object.
189
+ # @return [String, nil] The located gem directory.
190
+ def self.gem_dir_from_method(meth)
191
+ guess = 0
192
+
193
+ host = method_host(meth)
194
+ return unless host.name
195
+ root_module_name = host.name.split("::").first
196
+ while gem_name = guess_gem_name_from_module_name(root_module_name, guess)
197
+ matches = $LOAD_PATH.grep %r{/gems/#{gem_name}} if !gem_name.empty?
198
+ if matches && matches.any?
199
+ return gem_root(matches.first)
200
+ else
201
+ guess += 1
202
+ end
203
+ end
204
+
205
+ nil
206
+ end
207
+
208
+ # Cache the file that holds the method or return immediately if file is
209
+ # already cached. Return if the method cannot be cached -
210
+ # i.e is a C stdlib method.
211
+ # @param [Method, UnboundMethod] meth The method object.
212
+ def self.cache(meth)
213
+ file, _ = meth.source_location
214
+
215
+ return if is_eval_method?(meth)
216
+ return if cached?(meth)
217
+
218
+ if !file
219
+ parse_and_cache_if_gem_cext(meth)
220
+ return
221
+ end
222
+
223
+ log.enter_level(Logger::FATAL) do
224
+ YARD.parse(file)
225
+ end
226
+ end
227
+ end
228
+ end