yard 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of yard might be problematic. Click here for more details.
- data/ChangeLog +585 -1
- data/README.md +10 -2
- data/benchmarks/yri_cache.rb +19 -0
- data/bin/yri +1 -26
- data/docs/WhatsNew.md +99 -0
- data/lib/rubygems_plugin.rb +2 -0
- data/lib/yard.rb +2 -2
- data/lib/yard/autoload.rb +9 -4
- data/lib/yard/cli/base.rb +26 -0
- data/lib/yard/cli/yard_graph.rb +2 -9
- data/lib/yard/cli/yardoc.rb +93 -33
- data/lib/yard/cli/yri.rb +128 -0
- data/lib/yard/code_objects/base.rb +16 -5
- data/lib/yard/code_objects/class_object.rb +11 -4
- data/lib/yard/code_objects/method_object.rb +11 -1
- data/lib/yard/code_objects/proxy.rb +5 -2
- data/lib/yard/code_objects/root_object.rb +1 -0
- data/lib/yard/core_ext/file.rb +1 -1
- data/lib/yard/core_ext/hash.rb +15 -0
- data/lib/yard/core_ext/module.rb +2 -2
- data/lib/yard/core_ext/string.rb +66 -0
- data/lib/yard/core_ext/symbol_hash.rb +1 -1
- data/lib/yard/docstring.rb +5 -5
- data/lib/yard/handlers/base.rb +10 -4
- data/lib/yard/handlers/processor.rb +3 -4
- data/lib/yard/handlers/ruby/attribute_handler.rb +3 -2
- data/lib/yard/handlers/ruby/legacy/attribute_handler.rb +2 -2
- data/lib/yard/handlers/ruby/legacy/method_handler.rb +7 -1
- data/lib/yard/handlers/ruby/method_handler.rb +7 -1
- data/lib/yard/logging.rb +11 -1
- data/lib/yard/parser/c_parser.rb +407 -0
- data/lib/yard/parser/ruby/ast_node.rb +2 -2
- data/lib/yard/parser/ruby/legacy/ruby_lex.rb +3 -4
- data/lib/yard/parser/source_parser.rb +18 -7
- data/lib/yard/rake/yardoc_task.rb +1 -1
- data/lib/yard/registry.rb +83 -29
- data/lib/yard/registry_store.rb +213 -0
- data/lib/yard/serializers/base.rb +1 -1
- data/lib/yard/serializers/yardoc_serializer.rb +113 -0
- data/lib/yard/tags/library.rb +4 -0
- data/lib/yard/tags/overload_tag.rb +16 -5
- data/lib/yard/tags/tag.rb +1 -2
- data/lib/yard/templates/engine.rb +3 -3
- data/lib/yard/templates/helpers/html_helper.rb +50 -16
- data/lib/yard/templates/helpers/html_syntax_highlight_helper.rb +1 -3
- data/lib/yard/templates/helpers/html_syntax_highlight_helper18.rb +1 -3
- data/lib/yard/templates/helpers/method_helper.rb +11 -4
- data/lib/yard/templates/helpers/text_helper.rb +24 -2
- data/lib/yard/verifier.rb +3 -3
- data/spec/cli/yardoc_spec.rb +33 -6
- data/spec/cli/yri_spec.rb +30 -0
- data/spec/code_objects/base_spec.rb +7 -0
- data/spec/code_objects/class_object_spec.rb +6 -1
- data/spec/code_objects/method_object_spec.rb +25 -0
- data/spec/core_ext/hash_spec.rb +10 -0
- data/spec/core_ext/module_spec.rb +1 -1
- data/spec/core_ext/string_spec.rb +50 -12
- data/spec/handlers/attribute_handler_spec.rb +4 -0
- data/spec/handlers/examples/method_handler_001.rb.txt +9 -0
- data/spec/handlers/method_handler_spec.rb +22 -4
- data/spec/parser/c_parser_spec.rb +22 -0
- data/spec/parser/examples/array.c.txt +3887 -0
- data/spec/parser/source_parser_spec.rb +29 -7
- data/spec/registry_spec.rb +93 -72
- data/spec/registry_store_spec.rb +184 -0
- data/spec/serializers/file_system_serializer_spec.rb +96 -75
- data/spec/spec_helper.rb +2 -2
- data/spec/tags/overload_tag_spec.rb +18 -0
- data/spec/templates/examples/class001.html +32 -30
- data/spec/templates/examples/method001.html +4 -1
- data/spec/templates/examples/method002.html +7 -2
- data/spec/templates/examples/method002.txt +1 -1
- data/spec/templates/examples/method003.html +30 -8
- data/spec/templates/examples/method003.txt +4 -4
- data/spec/templates/examples/method004.html +44 -0
- data/spec/templates/examples/method004.txt +10 -0
- data/spec/templates/examples/method005.html +99 -0
- data/spec/templates/examples/method005.txt +33 -0
- data/spec/templates/examples/module001.dot +1 -1
- data/spec/templates/examples/module001.html +391 -37
- data/spec/templates/examples/module001.txt +1 -1
- data/spec/templates/helpers/base_helper_spec.rb +2 -2
- data/spec/templates/helpers/html_helper_spec.rb +83 -0
- data/spec/templates/helpers/method_helper_spec.rb +47 -0
- data/spec/templates/helpers/shared_signature_examples.rb +102 -0
- data/spec/templates/helpers/text_helper_spec.rb +31 -0
- data/spec/templates/method_spec.rb +43 -18
- data/spec/templates/module_spec.rb +22 -1
- data/spec/templates/spec_helper.rb +10 -1
- data/spec/yard_spec.rb +4 -3
- data/templates/default/class/html/constructor_details.erb +1 -1
- data/templates/default/docstring/html/returns_void.erb +1 -0
- data/templates/default/docstring/setup.rb +9 -4
- data/templates/default/docstring/text/returns_void.erb +1 -0
- data/templates/default/fulldoc/html/css/style.css +4 -2
- data/templates/default/fulldoc/html/full_list.erb +2 -2
- data/templates/default/fulldoc/html/js/app.js +1 -1
- data/templates/default/fulldoc/html/setup.rb +14 -6
- data/templates/default/layout/dot/setup.rb +1 -1
- data/templates/default/layout/html/breadcrumb.erb +2 -2
- data/templates/default/layout/html/index.erb +2 -2
- data/templates/default/layout/html/setup.rb +5 -5
- data/templates/default/method/html/header.erb +6 -4
- data/templates/default/method_details/html/method_signature.erb +2 -1
- data/templates/default/method_details/html/source.erb +1 -1
- data/templates/default/method_details/setup.rb +2 -1
- data/templates/default/method_details/text/setup.rb +1 -1
- data/templates/default/module/html/attribute_details.erb +4 -4
- data/templates/default/module/html/attribute_summary.erb +3 -3
- data/templates/default/module/html/box_info.erb +2 -2
- data/templates/default/module/html/defines.erb +1 -1
- data/templates/default/module/html/inherited_constants.erb +1 -1
- data/templates/default/module/html/inherited_methods.erb +1 -1
- data/templates/default/module/html/item_summary.erb +13 -4
- data/templates/default/module/html/method_details_list.erb +5 -4
- data/templates/default/module/html/method_summary.erb +5 -4
- data/templates/default/module/html/methodmissing.erb +1 -1
- data/templates/default/module/setup.rb +14 -5
- data/templates/default/tags/html/overload.erb +3 -2
- data/templates/default/tags/setup.rb +4 -0
- metadata +23 -2
@@ -261,7 +261,7 @@ module YARD
|
|
261
261
|
#
|
262
262
|
# @yield each descendent node in order
|
263
263
|
# @yieldparam [AstNode] self, or a child/descendent node
|
264
|
-
# @return [
|
264
|
+
# @return [void]
|
265
265
|
def traverse
|
266
266
|
nodes = [self]
|
267
267
|
nodes.each.with_index do |node, index|
|
@@ -273,7 +273,7 @@ module YARD
|
|
273
273
|
private
|
274
274
|
|
275
275
|
# Resets line information
|
276
|
-
# @return [
|
276
|
+
# @return [void]
|
277
277
|
def reset_line_info
|
278
278
|
if size == 0
|
279
279
|
self.line_range = @fallback_line
|
@@ -14,7 +14,6 @@ module YARD
|
|
14
14
|
|
15
15
|
class Token
|
16
16
|
NO_TEXT = "??".freeze
|
17
|
-
attr :text
|
18
17
|
|
19
18
|
def initialize(line_no, char_no)
|
20
19
|
@line_no = line_no
|
@@ -457,9 +456,9 @@ module YARD
|
|
457
456
|
@exception_on_syntax_error = true
|
458
457
|
end
|
459
458
|
|
460
|
-
|
461
|
-
|
462
|
-
|
459
|
+
attr_accessor :skip_space
|
460
|
+
attr_accessor :read_auto_clean_up
|
461
|
+
attr_accessor :exception_on_syntax_error
|
463
462
|
|
464
463
|
attr :indent
|
465
464
|
|
@@ -32,11 +32,12 @@ module YARD
|
|
32
32
|
#
|
33
33
|
# @return [Symbol] the parser type
|
34
34
|
attr_accessor :parser_type
|
35
|
+
undef parser_type=
|
35
36
|
|
36
37
|
# Sets the parser and makes sure it's a valid type
|
37
38
|
#
|
38
39
|
# @param [Symbol] value the new parser type
|
39
|
-
# @return [
|
40
|
+
# @return [void]
|
40
41
|
def parser_type=(value)
|
41
42
|
@parser_type = validated_parser_type(value)
|
42
43
|
end
|
@@ -48,9 +49,12 @@ module YARD
|
|
48
49
|
# @param [Fixnum] level the logger level to use during parsing. See
|
49
50
|
# {YARD::Logger}
|
50
51
|
# @return the parser object that was used to parse the source.
|
51
|
-
def parse(paths = "lib/**/*.rb", level = log.level)
|
52
|
+
def parse(paths = ["lib/**/*.rb", "ext/**/*.c"], level = log.level)
|
52
53
|
log.debug("Parsing #{paths} with `#{parser_type}` parser")
|
53
|
-
files = [paths].flatten.
|
54
|
+
files = [paths].flatten.
|
55
|
+
map {|p| File.directory?(p) ? "#{p}/**/*.{rb,c}" : p }.
|
56
|
+
map {|p| p.include?("*") ? Dir[p] : p }.flatten.
|
57
|
+
reject {|p| !File.file?(p) }
|
54
58
|
|
55
59
|
log.enter_level(level) do
|
56
60
|
parse_in_order(*files.uniq)
|
@@ -91,7 +95,7 @@ module YARD
|
|
91
95
|
# that can continue processing the file.
|
92
96
|
#
|
93
97
|
# @param [Array<String>] files a list of files to queue for parsing
|
94
|
-
# @return [
|
98
|
+
# @return [void]
|
95
99
|
def parse_in_order(*files)
|
96
100
|
files = files.sort_by {|x| x.length if x }
|
97
101
|
while file = files.shift
|
@@ -134,12 +138,18 @@ module YARD
|
|
134
138
|
# use the class methods {parse} and {parse_string}.
|
135
139
|
#
|
136
140
|
# @param [String, #read, Object] content the source file to parse
|
137
|
-
# @return the parser object used to parse the source
|
141
|
+
# @return [Object, nil] the parser object used to parse the source
|
138
142
|
def parse(content = __FILE__)
|
139
143
|
case content
|
140
144
|
when String
|
141
145
|
@file = content
|
142
146
|
content = IO.read(content)
|
147
|
+
checksum = Registry.checksum_for(content)
|
148
|
+
if Registry.checksums[file] == checksum
|
149
|
+
log.info "File '#{file}' hasn't changed, skipping..."
|
150
|
+
return
|
151
|
+
end
|
152
|
+
Registry.checksums[@file] = checksum
|
143
153
|
self.parser_type = parser_type_for_filename(file)
|
144
154
|
else
|
145
155
|
content = content.read if content.respond_to? :read
|
@@ -174,8 +184,9 @@ module YARD
|
|
174
184
|
private
|
175
185
|
|
176
186
|
# Runs a {Handlers::Processor} object to post process the parsed statements.
|
177
|
-
# @return [
|
187
|
+
# @return [void]
|
178
188
|
def post_process
|
189
|
+
return unless @parser.respond_to? :enumerator
|
179
190
|
post = Handlers::Processor.new(@file, @load_order_errors, @parser_type)
|
180
191
|
post.process(@parser.enumerator)
|
181
192
|
end
|
@@ -204,7 +215,7 @@ module YARD
|
|
204
215
|
def parse_statements(content)
|
205
216
|
case parser_type
|
206
217
|
when :c
|
207
|
-
|
218
|
+
CParser.new(content, file).parse
|
208
219
|
when :ruby18
|
209
220
|
Ruby::Legacy::StatementList.new(content)
|
210
221
|
when :ruby
|
data/lib/yard/registry.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'singleton'
|
2
|
-
require '
|
2
|
+
require 'fileutils'
|
3
|
+
require 'digest/sha1'
|
3
4
|
|
4
5
|
module YARD
|
5
6
|
# The +Registry+ is the centralized data store for all {CodeObjects} created
|
@@ -16,6 +17,7 @@ module YARD
|
|
16
17
|
# delegated to the instance.
|
17
18
|
class Registry
|
18
19
|
DEFAULT_YARDOC_FILE = ".yardoc"
|
20
|
+
LOCAL_YARDOC_INDEX = File.expand_path('~/.yard/gem_index')
|
19
21
|
|
20
22
|
include Singleton
|
21
23
|
|
@@ -28,11 +30,57 @@ module YARD
|
|
28
30
|
attr_reader :objects
|
29
31
|
|
30
32
|
# Clears the registry and cache
|
31
|
-
# @return [
|
33
|
+
# @return [void]
|
32
34
|
def clear
|
33
35
|
instance.clear
|
34
36
|
objects.clear
|
35
37
|
end
|
38
|
+
|
39
|
+
# Returns the .yardoc file associated with a gem.
|
40
|
+
#
|
41
|
+
# @param [String] gem the name of the gem to search for
|
42
|
+
# @param [String] ver_require an optional Gem version requirement
|
43
|
+
# @param [Boolean] for_writing whether or not the method should search
|
44
|
+
# for writable locations
|
45
|
+
# @return [String] if +for_writing+ is set to +true+, returns the best
|
46
|
+
# location suitable to write the .yardoc file. Otherwise, the first
|
47
|
+
# existing location associated with the gem's .yardoc file.
|
48
|
+
# @return [nil] if +for_writing+ is set to false and no yardoc file
|
49
|
+
# is found, returns nil.
|
50
|
+
def yardoc_file_for_gem(gem, ver_require = ">= 0", for_writing = false)
|
51
|
+
spec = Gem.source_index.find_name(gem, ver_require).first
|
52
|
+
|
53
|
+
if for_writing
|
54
|
+
global_yardoc_file(spec, for_writing) ||
|
55
|
+
local_yardoc_file(spec, for_writing)
|
56
|
+
else
|
57
|
+
local_yardoc_file(spec, for_writing) ||
|
58
|
+
global_yardoc_file(spec, for_writing)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def global_yardoc_file(spec, for_writing = false)
|
65
|
+
path = spec.full_gem_path
|
66
|
+
yfile = File.join(path, DEFAULT_YARDOC_FILE)
|
67
|
+
if for_writing && File.writable?(path)
|
68
|
+
return yfile
|
69
|
+
elsif !for_writing && File.exist?(yfile)
|
70
|
+
return yfile
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def local_yardoc_file(spec, for_writing = false)
|
75
|
+
path = Registry::LOCAL_YARDOC_INDEX
|
76
|
+
FileUtils.mkdir_p(path) if for_writing
|
77
|
+
path = File.join(path, "#{spec.full_name}.yardoc")
|
78
|
+
if for_writing
|
79
|
+
path
|
80
|
+
else
|
81
|
+
File.exist?(path) ? path : nil
|
82
|
+
end
|
83
|
+
end
|
36
84
|
end
|
37
85
|
|
38
86
|
# Gets/sets the yardoc filename
|
@@ -42,7 +90,9 @@ module YARD
|
|
42
90
|
|
43
91
|
# The assumed types of a list of paths
|
44
92
|
# @return [{String => Symbol}] a set of unresolved paths and their assumed type
|
45
|
-
|
93
|
+
def proxy_types
|
94
|
+
@store.proxy_types
|
95
|
+
end
|
46
96
|
|
47
97
|
# Loads the registry and/or parses a list of files
|
48
98
|
#
|
@@ -64,9 +114,9 @@ module YARD
|
|
64
114
|
if File.exists?(yardoc_file) && !reload
|
65
115
|
load_yardoc
|
66
116
|
else
|
67
|
-
size =
|
117
|
+
size = @store.keys.size
|
68
118
|
YARD.parse(files)
|
69
|
-
save if
|
119
|
+
save if @store.keys.size > size
|
70
120
|
end
|
71
121
|
true
|
72
122
|
elsif files.is_a?(String)
|
@@ -80,21 +130,30 @@ module YARD
|
|
80
130
|
# Loads a yardoc file directly
|
81
131
|
#
|
82
132
|
# @param [String] file the yardoc file to load.
|
83
|
-
# @return [
|
133
|
+
# @return [void]
|
84
134
|
def load_yardoc(file = yardoc_file)
|
85
|
-
|
86
|
-
|
87
|
-
namespace.update(ns)
|
88
|
-
proxy_types.update(pt)
|
135
|
+
clear
|
136
|
+
@store.load(file)
|
89
137
|
end
|
90
138
|
|
91
139
|
# Saves the registry to +file+
|
92
140
|
#
|
93
141
|
# @param [String] file the yardoc file to save to
|
94
142
|
# @return [Boolean] true if the file was saved
|
95
|
-
def save(file = yardoc_file)
|
96
|
-
|
97
|
-
|
143
|
+
def save(merge = false, file = yardoc_file)
|
144
|
+
@store.save(merge, file)
|
145
|
+
end
|
146
|
+
|
147
|
+
def checksums
|
148
|
+
@store.checksums
|
149
|
+
end
|
150
|
+
|
151
|
+
def checksum_for(data)
|
152
|
+
Digest::SHA1.hexdigest(data)
|
153
|
+
end
|
154
|
+
|
155
|
+
def delete_from_disk
|
156
|
+
@store.destroy
|
98
157
|
end
|
99
158
|
|
100
159
|
# Returns all objects in the registry that match one of the types provided
|
@@ -110,7 +169,7 @@ module YARD
|
|
110
169
|
# @return [Array<CodeObjects::Base>] the list of objects found
|
111
170
|
# @see CodeObjects::Base#type
|
112
171
|
def all(*types)
|
113
|
-
|
172
|
+
@store.values.select do |obj|
|
114
173
|
if types.empty?
|
115
174
|
obj != root
|
116
175
|
else
|
@@ -123,9 +182,10 @@ module YARD
|
|
123
182
|
end
|
124
183
|
|
125
184
|
# Returns the paths of all of the objects in the registry.
|
185
|
+
# @param [Boolean] reload whether to load entire database
|
126
186
|
# @return [Array<String>] all of the paths in the registry.
|
127
|
-
def paths
|
128
|
-
|
187
|
+
def paths(reload = true)
|
188
|
+
@store.keys(reload).map {|k| k.to_s }
|
129
189
|
end
|
130
190
|
|
131
191
|
# Returns the object at a specific path.
|
@@ -133,27 +193,25 @@ module YARD
|
|
133
193
|
# returns the {#root} object.
|
134
194
|
# @return [CodeObjects::Base] the object at path
|
135
195
|
# @return [nil] if no object is found
|
136
|
-
def at(path)
|
196
|
+
def at(path) @store[path] end
|
137
197
|
alias_method :[], :at
|
138
198
|
|
139
199
|
# The root namespace object.
|
140
200
|
# @return [CodeObjects::RootObject] the root object in the namespace
|
141
|
-
def root;
|
201
|
+
def root; @store[:root] end
|
142
202
|
|
143
203
|
# Deletes an object from the registry
|
144
204
|
# @param [CodeObjects::Base] object the object to remove
|
145
|
-
# @return [
|
205
|
+
# @return [void]
|
146
206
|
def delete(object)
|
147
|
-
|
207
|
+
@store.delete(object.path)
|
148
208
|
self.class.objects.delete(object.path)
|
149
209
|
end
|
150
210
|
|
151
211
|
# Clears the registry
|
152
|
-
# @return [
|
212
|
+
# @return [void]
|
153
213
|
def clear
|
154
|
-
@
|
155
|
-
@namespace[:root] = CodeObjects::RootObject.new(nil, :root)
|
156
|
-
@proxy_types = {}
|
214
|
+
@store = RegistryStore.new
|
157
215
|
end
|
158
216
|
|
159
217
|
# Creates the Registry
|
@@ -170,7 +228,7 @@ module YARD
|
|
170
228
|
def register(object)
|
171
229
|
self.class.objects[object.path] = object
|
172
230
|
return if object.is_a?(CodeObjects::Proxy)
|
173
|
-
|
231
|
+
@store[object.path] = object
|
174
232
|
end
|
175
233
|
|
176
234
|
# Attempts to find an object by name starting at +namespace+, performing
|
@@ -246,10 +304,6 @@ module YARD
|
|
246
304
|
end
|
247
305
|
|
248
306
|
private
|
249
|
-
|
250
|
-
# The internal namespace hash
|
251
|
-
# @return [Hash{String => CodeObjects::Base}] the path/object hash
|
252
|
-
attr_accessor :namespace
|
253
307
|
|
254
308
|
# Attempts to resolve a name in a namespace
|
255
309
|
#
|
@@ -0,0 +1,213 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module YARD
|
4
|
+
# The data store for the {Registry}.
|
5
|
+
#
|
6
|
+
# @see Registry
|
7
|
+
# @see Serializers::YardocSerializer
|
8
|
+
class RegistryStore
|
9
|
+
attr_reader :proxy_types, :file, :checksums
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@file = nil
|
13
|
+
@checksums = {}
|
14
|
+
@store = { :root => CodeObjects::RootObject.new(nil, :root) }
|
15
|
+
@proxy_types = {}
|
16
|
+
@loaded_objects = 0
|
17
|
+
@available_objects = 0
|
18
|
+
end
|
19
|
+
|
20
|
+
# Gets a {CodeObjects::Base} from the store
|
21
|
+
#
|
22
|
+
# @param [String, Symbol] key the path name of the object to look for.
|
23
|
+
# If it is empty or :root, returns the {#root} object.
|
24
|
+
# @return [CodeObjects::Base, nil] a code object or nil if none is found
|
25
|
+
def get(key)
|
26
|
+
key = :root if key == ''
|
27
|
+
key = key.to_sym
|
28
|
+
return @store[key] if @store[key]
|
29
|
+
return nil if @loaded_objects >= @available_objects
|
30
|
+
|
31
|
+
# check disk
|
32
|
+
if obj = @serializer.deserialize(key)
|
33
|
+
@loaded_objects += 1
|
34
|
+
put(key, obj)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Associates an object with a path
|
39
|
+
# @param [String, Symbol] key the path name (:root or '' for root object)
|
40
|
+
# @param [CodeObjects::Base] value the object to store
|
41
|
+
# @return [CodeObjects::Base] returns +value+
|
42
|
+
def put(key, value)
|
43
|
+
if key == ''
|
44
|
+
@store[:root] = value
|
45
|
+
else
|
46
|
+
@store[key.to_sym] = value
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
alias [] get
|
51
|
+
alias []= put
|
52
|
+
|
53
|
+
def delete(key) @store.delete(key.to_sym) end
|
54
|
+
|
55
|
+
# Gets all path names from the store. Loads the entire database
|
56
|
+
# if +reload+ is +true+
|
57
|
+
#
|
58
|
+
# @param [Boolean] reload if false, does not load the entire database
|
59
|
+
# before a lookup.
|
60
|
+
# @return [Array<Symbol>] the path names of all the code objects
|
61
|
+
def keys(reload = true) load_all if reload; @store.keys end
|
62
|
+
|
63
|
+
# Gets all code objects from the store. Loads the entire database
|
64
|
+
# if +reload+ is +true+
|
65
|
+
#
|
66
|
+
# @param [Boolean] reload if false, does not load the entire database
|
67
|
+
# before a lookup.
|
68
|
+
# @return [Array<CodeObjects::Base>] all the code objects
|
69
|
+
def values(reload = true) load_all if reload; @store.values end
|
70
|
+
|
71
|
+
# @return [CodeObjects::RootObject] the root object
|
72
|
+
def root; @store[:root] end
|
73
|
+
|
74
|
+
# @param [String, nil] file the name of the yardoc db to load
|
75
|
+
# @return [Boolean] whether the database was loaded
|
76
|
+
def load(file = nil)
|
77
|
+
@file = file
|
78
|
+
@store = {}
|
79
|
+
@proxy_types = {}
|
80
|
+
@serializer = Serializers::YardocSerializer.new(@file)
|
81
|
+
load_yardoc
|
82
|
+
end
|
83
|
+
|
84
|
+
# Saves the database to disk
|
85
|
+
# @param [Boolean] merge if true, merges the data in memory with the
|
86
|
+
# data on disk, otherwise the data on disk is deleted.
|
87
|
+
# @param [String, nil] file if supplied, the name of the file to save to
|
88
|
+
# @return [Boolean] whether the database was saved
|
89
|
+
def save(merge = true, file = nil)
|
90
|
+
if file && file != @file
|
91
|
+
@file = file
|
92
|
+
@serializer = Serializers::YardocSerializer.new(@file)
|
93
|
+
end
|
94
|
+
destroy unless merge
|
95
|
+
values(false).each do |object|
|
96
|
+
@serializer.serialize(object)
|
97
|
+
end
|
98
|
+
write_proxy_types
|
99
|
+
write_checksums
|
100
|
+
true
|
101
|
+
end
|
102
|
+
|
103
|
+
# Deletes the .yardoc database on disk
|
104
|
+
#
|
105
|
+
# @param [Boolean] force if force is not set to true, the file/directory
|
106
|
+
# will only be removed if it ends with .yardoc. This helps with
|
107
|
+
# cases where the directory might have been named incorrectly.
|
108
|
+
# @return [Boolean] true if the .yardoc database was deleted, false
|
109
|
+
# otherwise.
|
110
|
+
def destroy(force = false)
|
111
|
+
if (!force && file =~ /\.yardoc$/) || force
|
112
|
+
if File.file?(@file)
|
113
|
+
# Handle silent upgrade of old .yardoc format
|
114
|
+
File.unlink(@file)
|
115
|
+
elsif File.directory?(@file)
|
116
|
+
FileUtils.rm_rf(@file)
|
117
|
+
end
|
118
|
+
true
|
119
|
+
else
|
120
|
+
false
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
protected
|
125
|
+
|
126
|
+
def objects_path
|
127
|
+
@serializer.objects_path
|
128
|
+
end
|
129
|
+
|
130
|
+
def proxy_types_path
|
131
|
+
@serializer.proxy_types_path
|
132
|
+
end
|
133
|
+
|
134
|
+
def checksums_path
|
135
|
+
@serializer.checksums_path
|
136
|
+
end
|
137
|
+
|
138
|
+
def load_yardoc
|
139
|
+
return false unless @file
|
140
|
+
if File.directory?(@file) # new format
|
141
|
+
Registry.objects.replace({})
|
142
|
+
@loaded_objects = 0
|
143
|
+
@available_objects = all_disk_objects.size
|
144
|
+
load_proxy_types
|
145
|
+
load_checksums
|
146
|
+
load_root
|
147
|
+
true
|
148
|
+
elsif File.file?(@file) # old format
|
149
|
+
load_yardoc_old
|
150
|
+
true
|
151
|
+
else
|
152
|
+
false
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def load_yardoc_old
|
157
|
+
@store, @proxy_types = *Marshal.load(File.read(@file))
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
def load_proxy_types
|
163
|
+
return unless File.file?(proxy_types_path)
|
164
|
+
@proxy_types = Marshal.load(File.read(proxy_types_path))
|
165
|
+
end
|
166
|
+
|
167
|
+
def load_checksums
|
168
|
+
return unless File.file?(checksums_path)
|
169
|
+
lines = File.readlines(checksums_path).map do |line|
|
170
|
+
line.strip.split(/\s+/)
|
171
|
+
end
|
172
|
+
@checksums = Hash[lines]
|
173
|
+
end
|
174
|
+
|
175
|
+
def load_root
|
176
|
+
if root = @serializer.deserialize('root')
|
177
|
+
@store[:root] = root
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def load_all
|
182
|
+
return unless @file
|
183
|
+
return if @loaded_objects >= @available_objects
|
184
|
+
log.debug "Loading entire database: #{@file} ..."
|
185
|
+
objects = []
|
186
|
+
|
187
|
+
all_disk_objects.sort_by {|x| x.size }.each do |path|
|
188
|
+
if obj = @serializer.deserialize(path, true)
|
189
|
+
objects << obj
|
190
|
+
end
|
191
|
+
end
|
192
|
+
objects.each do |obj|
|
193
|
+
put(obj.path, obj)
|
194
|
+
end
|
195
|
+
@loaded_objects += objects.size
|
196
|
+
log.debug "Loaded database (file='#{@file}' count=#{objects.size} total=#{@available_objects})"
|
197
|
+
end
|
198
|
+
|
199
|
+
def all_disk_objects
|
200
|
+
Dir.glob(File.join(objects_path, '**/*')).select {|f| File.file?(f) }
|
201
|
+
end
|
202
|
+
|
203
|
+
def write_proxy_types
|
204
|
+
File.open(proxy_types_path, 'wb') {|f| f.write(Marshal.dump(@proxy_types)) }
|
205
|
+
end
|
206
|
+
|
207
|
+
def write_checksums
|
208
|
+
File.open(checksums_path, 'w') do |f|
|
209
|
+
@checksums.each {|k, v| f.puts("#{k} #{v}") }
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|