yard 0.6.4 → 0.6.5
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 +341 -0
- data/LICENSE +1 -1
- data/README.md +31 -6
- data/Rakefile +22 -3
- data/docs/Tags.md +5 -1
- data/docs/WhatsNew.md +18 -1
- data/lib/rubygems_plugin.rb +3 -99
- data/lib/yard.rb +1 -1
- data/lib/yard/autoload.rb +37 -35
- data/lib/yard/cli/config.rb +25 -2
- data/lib/yard/cli/graph.rb +1 -1
- data/lib/yard/cli/yardoc.rb +4 -0
- data/lib/yard/code_objects/base.rb +17 -9
- data/lib/yard/code_objects/method_object.rb +0 -9
- data/lib/yard/code_objects/proxy.rb +6 -0
- data/lib/yard/docstring.rb +5 -0
- data/lib/yard/handlers/base.rb +3 -1
- data/lib/yard/handlers/processor.rb +1 -1
- data/lib/yard/handlers/ruby/alias_handler.rb +9 -8
- data/lib/yard/handlers/ruby/class_handler.rb +3 -3
- data/lib/yard/handlers/ruby/legacy/alias_handler.rb +9 -7
- data/lib/yard/handlers/ruby/legacy/method_handler.rb +7 -0
- data/lib/yard/handlers/ruby/legacy/private_constant_handler.rb +21 -0
- data/lib/yard/handlers/ruby/method_condition_handler.rb +1 -1
- data/lib/yard/handlers/ruby/method_handler.rb +7 -0
- data/lib/yard/handlers/ruby/private_constant_handler.rb +36 -0
- data/lib/yard/parser/ruby/ast_node.rb +41 -24
- data/lib/yard/parser/ruby/legacy/ruby_parser.rb +3 -0
- data/lib/yard/parser/ruby/legacy/statement.rb +2 -0
- data/lib/yard/parser/ruby/legacy/statement_list.rb +27 -4
- data/lib/yard/parser/ruby/ruby_parser.rb +71 -36
- data/lib/yard/parser/source_parser.rb +11 -10
- data/lib/yard/registry.rb +62 -24
- data/lib/yard/registry_store.rb +18 -5
- data/lib/yard/rubygems/doc_manager.rb +75 -0
- data/lib/yard/rubygems/specification.rb +23 -0
- data/lib/yard/serializers/process_serializer.rb +1 -1
- data/lib/yard/serializers/yardoc_serializer.rb +7 -2
- data/lib/yard/server/commands/display_object_command.rb +1 -1
- data/lib/yard/server/commands/library_command.rb +2 -2
- data/lib/yard/tags/default_factory.rb +1 -1
- data/lib/yard/tags/library.rb +2 -2
- data/lib/yard/templates/helpers/base_helper.rb +19 -0
- data/lib/yard/templates/helpers/html_helper.rb +22 -9
- data/lib/yard/templates/helpers/html_syntax_highlight_helper.rb +28 -0
- data/lib/yard/templates/helpers/markup_helper.rb +14 -22
- data/lib/yard/templates/template.rb +1 -1
- data/spec/cli/config_spec.rb +20 -0
- data/spec/cli/yardoc_spec.rb +12 -0
- data/spec/code_objects/base_spec.rb +13 -0
- data/spec/code_objects/proxy_spec.rb +9 -0
- data/spec/config_spec.rb +4 -1
- data/spec/docstring_spec.rb +5 -0
- data/spec/handlers/alias_handler_spec.rb +14 -1
- data/spec/handlers/attribute_handler_spec.rb +1 -1
- data/spec/handlers/base_spec.rb +21 -21
- data/spec/handlers/class_condition_handler_spec.rb +1 -1
- data/spec/handlers/class_handler_spec.rb +1 -1
- data/spec/handlers/class_variable_handler_spec.rb +1 -1
- data/spec/handlers/constant_handler_spec.rb +2 -2
- data/spec/handlers/examples/alias_handler_001.rb.txt +14 -0
- data/spec/handlers/examples/method_handler_001.rb.txt +6 -0
- data/spec/handlers/examples/module_handler_001.rb.txt +4 -0
- data/spec/handlers/examples/private_constant_handler_001.rb.txt +8 -0
- data/spec/handlers/exception_handler_spec.rb +1 -1
- data/spec/handlers/extend_handler_spec.rb +1 -1
- data/spec/handlers/method_condition_handler_spec.rb +1 -1
- data/spec/handlers/method_handler_spec.rb +7 -1
- data/spec/handlers/mixin_handler_spec.rb +1 -1
- data/spec/handlers/module_handler_spec.rb +5 -1
- data/spec/handlers/private_constant_handler_spec.rb +24 -0
- data/spec/handlers/process_handler_spec.rb +1 -1
- data/spec/handlers/ruby/base_spec.rb +4 -4
- data/spec/handlers/visibility_handler_spec.rb +1 -1
- data/spec/handlers/yield_handler_spec.rb +1 -1
- data/spec/parser/base_spec.rb +3 -5
- data/spec/parser/c_parser_spec.rb +1 -1
- data/spec/parser/ruby/ast_node_spec.rb +23 -26
- data/spec/parser/ruby/legacy/statement_list_spec.rb +9 -0
- data/spec/parser/ruby/ruby_parser_spec.rb +179 -177
- data/spec/parser/source_parser_spec.rb +41 -7
- data/spec/rake/yardoc_task_spec.rb +3 -3
- data/spec/registry_spec.rb +52 -0
- data/spec/registry_store_spec.rb +71 -1
- data/spec/serializers/yardoc_serializer_spec.rb +18 -7
- data/spec/server/rack_adapter_spec.rb +2 -2
- data/spec/spec_helper.rb +10 -0
- data/spec/tags/default_factory_spec.rb +122 -120
- data/spec/templates/helpers/base_helper_spec.rb +38 -14
- data/spec/templates/helpers/html_helper_spec.rb +19 -0
- data/spec/templates/helpers/html_syntax_highlight_helper_spec.rb +10 -6
- data/spec/templates/helpers/markup_helper_spec.rb +21 -5
- data/templates/default/class/dot/superklass.erb +1 -1
- data/templates/default/docstring/setup.rb +1 -1
- data/templates/default/fulldoc/html/css/style.css +12 -4
- data/templates/default/fulldoc/html/js/app.js +1 -1
- data/templates/default/fulldoc/html/js/jquery.js +5 -143
- data/templates/default/layout/html/files.erb +11 -0
- data/templates/default/layout/html/headers.erb +1 -1
- data/templates/default/layout/html/index.erb +2 -49
- data/templates/default/layout/html/listing.erb +4 -0
- data/templates/default/layout/html/objects.erb +32 -0
- data/templates/default/layout/html/setup.rb +1 -1
- data/templates/default/module/dot/info.erb +1 -1
- data/templates/default/module/dot/setup.rb +1 -1
- metadata +15 -6
- data/lib/yard/templates/helpers/html_syntax_highlight_helper18.rb +0 -25
@@ -1,9 +1,12 @@
|
|
1
|
-
require 'ripper'
|
1
|
+
begin require 'ripper'; rescue LoadError; end
|
2
2
|
|
3
3
|
module YARD
|
4
4
|
module Parser
|
5
5
|
module Ruby
|
6
6
|
# Ruby 1.9 parser
|
7
|
+
# @attr_reader encoding_line
|
8
|
+
# @attr_reader shebang_line
|
9
|
+
# @attr_reader enumerator
|
7
10
|
class RubyParser < Parser::Base
|
8
11
|
def initialize(source, filename)
|
9
12
|
@parser = RipperParser.new(source, filename)
|
@@ -12,12 +15,15 @@ module YARD
|
|
12
15
|
def parse; @parser.parse end
|
13
16
|
def tokenize; @parser.tokens end
|
14
17
|
def enumerator; @parser.enumerator end
|
18
|
+
def shebang_line; @parser.shebang_line end
|
19
|
+
def encoding_line; @parser.encoding_line end
|
15
20
|
end
|
16
21
|
|
17
22
|
# Internal parser class
|
18
23
|
# @since 0.5.6
|
19
24
|
class RipperParser < Ripper
|
20
25
|
attr_reader :ast, :charno, :comments, :file, :tokens
|
26
|
+
attr_reader :shebang_line, :encoding_line
|
21
27
|
alias root ast
|
22
28
|
|
23
29
|
def initialize(source, filename, *args)
|
@@ -27,12 +33,15 @@ module YARD
|
|
27
33
|
@source = source
|
28
34
|
@tokens = []
|
29
35
|
@comments = {}
|
36
|
+
@comments_flags = {}
|
30
37
|
@heredoc_tokens = []
|
31
38
|
@map = {}
|
32
39
|
@ns_charno = 0
|
33
40
|
@list = []
|
34
41
|
@charno = 0
|
35
42
|
@groups = []
|
43
|
+
@shebang_line = nil
|
44
|
+
@encoding_line = nil
|
36
45
|
end
|
37
46
|
|
38
47
|
def parse
|
@@ -116,15 +125,15 @@ module YARD
|
|
116
125
|
PARSER_EVENT_TABLE.each do |event, arity|
|
117
126
|
node_class = AstNode.node_class_for(event)
|
118
127
|
|
119
|
-
if /_new\z/ =~ event and arity == 0
|
128
|
+
if /_new\z/ =~ event.to_s and arity == 0
|
120
129
|
module_eval(<<-eof, __FILE__, __LINE__ + 1)
|
121
130
|
def on_#{event}(*args)
|
122
|
-
#{node_class}.new(:list, args, listchar
|
131
|
+
#{node_class}.new(:list, args, :listchar => charno...charno, :listline => lineno..lineno)
|
123
132
|
end
|
124
133
|
eof
|
125
|
-
elsif /_add(_.+)?\z/ =~ event
|
134
|
+
elsif /_add(_.+)?\z/ =~ event.to_s
|
126
135
|
module_eval(<<-eof, __FILE__, __LINE__ + 1)
|
127
|
-
undef on_#{event}
|
136
|
+
begin; undef on_#{event}; rescue NameError; end
|
128
137
|
def on_#{event}(list, item)
|
129
138
|
list.push(item)
|
130
139
|
list
|
@@ -132,16 +141,16 @@ module YARD
|
|
132
141
|
eof
|
133
142
|
elsif MAPPINGS.has_key?(event)
|
134
143
|
module_eval(<<-eof, __FILE__, __LINE__ + 1)
|
135
|
-
undef on_#{event}
|
144
|
+
begin; undef on_#{event}; rescue NameError; end
|
136
145
|
def on_#{event}(*args)
|
137
146
|
visit_event #{node_class}.new(:#{event}, args)
|
138
147
|
end
|
139
148
|
eof
|
140
149
|
else
|
141
150
|
module_eval(<<-eof, __FILE__, __LINE__ + 1)
|
142
|
-
undef on_#{event}
|
151
|
+
begin; undef on_#{event}; rescue NameError; end
|
143
152
|
def on_#{event}(*args)
|
144
|
-
#{node_class}.new(:#{event}, args, listline
|
153
|
+
#{node_class}.new(:#{event}, args, :listline => lineno..lineno, :listchar => charno...charno)
|
145
154
|
end
|
146
155
|
eof
|
147
156
|
end
|
@@ -150,17 +159,18 @@ module YARD
|
|
150
159
|
SCANNER_EVENTS.each do |event|
|
151
160
|
ast_token = AST_TOKENS.include?(event)
|
152
161
|
module_eval(<<-eof, __FILE__, __LINE__ + 1)
|
153
|
-
undef on_#{event}
|
162
|
+
begin; undef on_#{event}; rescue NameError; end
|
154
163
|
def on_#{event}(tok)
|
155
164
|
visit_ns_token(:#{event}, tok, #{ast_token.inspect})
|
156
165
|
end
|
157
166
|
eof
|
158
167
|
end
|
159
168
|
|
160
|
-
REV_MAPPINGS.select {|k| k.is_a?(Symbol) }.each do |
|
169
|
+
REV_MAPPINGS.select {|k,v| k.is_a?(Symbol) }.each do |pair|
|
170
|
+
event, value = *pair
|
161
171
|
ast_token = AST_TOKENS.include?(event)
|
162
172
|
module_eval(<<-eof, __FILE__, __LINE__ + 1)
|
163
|
-
undef on_#{event}
|
173
|
+
begin; undef on_#{event}; rescue NameError; end
|
164
174
|
def on_#{event}(tok)
|
165
175
|
(@map[:#{event}] ||= []) << [lineno, charno]
|
166
176
|
visit_ns_token(:#{event}, tok, #{ast_token.inspect})
|
@@ -170,7 +180,7 @@ module YARD
|
|
170
180
|
|
171
181
|
[:kw, :op].each do |event|
|
172
182
|
module_eval(<<-eof, __FILE__, __LINE__ + 1)
|
173
|
-
undef on_#{event}
|
183
|
+
begin; undef on_#{event}; rescue NameError; end
|
174
184
|
def on_#{event}(tok)
|
175
185
|
unless @last_ns_token == [:kw, "def"] ||
|
176
186
|
(@tokens.last && @tokens.last[0] == :symbeg)
|
@@ -183,7 +193,7 @@ module YARD
|
|
183
193
|
|
184
194
|
[:sp, :nl, :ignored_nl].each do |event|
|
185
195
|
module_eval(<<-eof, __FILE__, __LINE__ + 1)
|
186
|
-
undef on_#{event}
|
196
|
+
begin; undef on_#{event}; rescue NameError; end
|
187
197
|
def on_#{event}(tok)
|
188
198
|
add_token(:#{event}, tok)
|
189
199
|
@charno += tok.length
|
@@ -192,7 +202,8 @@ module YARD
|
|
192
202
|
end
|
193
203
|
|
194
204
|
def visit_event(node)
|
195
|
-
|
205
|
+
map = @map[MAPPINGS[node.type]]
|
206
|
+
lstart, sstart = *(map ? map.pop : [lineno, lineno])
|
196
207
|
node.source_range = Range.new(sstart, @ns_charno - 1)
|
197
208
|
node.line_range = Range.new(lstart, lineno)
|
198
209
|
node
|
@@ -213,7 +224,7 @@ module YARD
|
|
213
224
|
@charno += data.length
|
214
225
|
@ns_charno = charno
|
215
226
|
if ast_token
|
216
|
-
AstNode.new(token, [data], line
|
227
|
+
AstNode.new(token, [data], :line => lineno..lineno, :char => ch..charno-1, :token => true)
|
217
228
|
end
|
218
229
|
end
|
219
230
|
|
@@ -280,7 +291,7 @@ module YARD
|
|
280
291
|
ll, lc = *@map[:aref].pop
|
281
292
|
sr = args.first.source_range.first..lc
|
282
293
|
lr = args.first.line_range.first..ll
|
283
|
-
AstNode.new(:aref, args, char
|
294
|
+
AstNode.new(:aref, args, :char => sr, :line => lr)
|
284
295
|
end
|
285
296
|
|
286
297
|
def on_rbracket(tok)
|
@@ -301,31 +312,34 @@ module YARD
|
|
301
312
|
end
|
302
313
|
|
303
314
|
def on_const_path_ref(*args)
|
304
|
-
|
305
|
-
klass.new(:const_path_ref, args, listline: lineno..lineno, listchar: charno..charno)
|
315
|
+
ReferenceNode.new(:const_path_ref, args, :listline => lineno..lineno, :listchar => charno..charno)
|
306
316
|
end
|
307
317
|
|
308
318
|
[:if_mod, :unless_mod, :while_mod].each do |kw|
|
309
319
|
node_class = AstNode.node_class_for(kw)
|
310
320
|
module_eval(<<-eof, __FILE__, __LINE__ + 1)
|
311
|
-
undef on_#{kw}
|
321
|
+
begin; undef on_#{kw}; rescue NameError; end
|
312
322
|
def on_#{kw}(*args)
|
313
323
|
sr = args.last.source_range.first..args.first.source_range.last
|
314
324
|
lr = args.last.line_range.first..args.first.line_range.last
|
315
|
-
#{node_class}.new(:#{kw}, args, line
|
325
|
+
#{node_class}.new(:#{kw}, args, :line => lr, :char => sr)
|
316
326
|
end
|
317
327
|
eof
|
318
328
|
end
|
319
329
|
|
320
330
|
def on_qwords_new
|
321
|
-
visit_event
|
331
|
+
visit_event LiteralNode.new(:qwords_literal, [])
|
322
332
|
end
|
323
333
|
|
324
334
|
def on_string_literal(*args)
|
325
|
-
node = visit_event_arr(
|
326
|
-
if
|
327
|
-
|
328
|
-
node.source_range
|
335
|
+
node = visit_event_arr(LiteralNode.new(:string_literal, args))
|
336
|
+
if args.size == 1
|
337
|
+
r = args[0].source_range
|
338
|
+
if node.source_range != Range.new(r.first - 1, r.last + 1)
|
339
|
+
klass = AstNode.node_class_for(node[0].type)
|
340
|
+
r = Range.new(node.source_range.first + 1, node.source_range.last - 1)
|
341
|
+
node[0] = klass.new(node[0].type, [@source[r]], :line => node.line_range, :char => r)
|
342
|
+
end
|
329
343
|
end
|
330
344
|
node
|
331
345
|
end
|
@@ -335,7 +349,7 @@ module YARD
|
|
335
349
|
end
|
336
350
|
|
337
351
|
def on_string_content(*args)
|
338
|
-
AstNode.new(:string_content, args, listline
|
352
|
+
AstNode.new(:string_content, args, :listline => lineno..lineno, :listchar => charno..charno)
|
339
353
|
end
|
340
354
|
|
341
355
|
def on_rescue(exc, *args)
|
@@ -344,7 +358,7 @@ module YARD
|
|
344
358
|
end
|
345
359
|
|
346
360
|
def on_void_stmt
|
347
|
-
AstNode.new(:void_stmt, [], line
|
361
|
+
AstNode.new(:void_stmt, [], :line => lineno..lineno, :char => charno...charno)
|
348
362
|
end
|
349
363
|
|
350
364
|
def on_params(*args)
|
@@ -353,18 +367,18 @@ module YARD
|
|
353
367
|
if arg.first.class == Array
|
354
368
|
arg.map! do |sub_arg|
|
355
369
|
if sub_arg.class == Array
|
356
|
-
AstNode.new(:default_arg, sub_arg, listline
|
370
|
+
AstNode.new(:default_arg, sub_arg, :listline => lineno..lineno, :listchar => charno..charno)
|
357
371
|
else
|
358
372
|
sub_arg
|
359
373
|
end
|
360
374
|
end
|
361
375
|
end
|
362
|
-
AstNode.new(:list, arg, listline
|
376
|
+
AstNode.new(:list, arg, :listline => lineno..lineno, :listchar => charno..charno)
|
363
377
|
else
|
364
378
|
arg
|
365
379
|
end
|
366
380
|
end
|
367
|
-
ParameterNode.new(:params, args, listline
|
381
|
+
ParameterNode.new(:params, args, :listline => lineno..lineno, :listchar => charno..charno)
|
368
382
|
end
|
369
383
|
|
370
384
|
def on_label(data)
|
@@ -372,11 +386,26 @@ module YARD
|
|
372
386
|
ch = charno
|
373
387
|
@charno += data.length
|
374
388
|
@ns_charno = charno
|
375
|
-
AstNode.new(:label, [data[0...-1]], line
|
389
|
+
AstNode.new(:label, [data[0...-1]], :line => lineno..lineno, :char => ch..charno-1, :token => true)
|
376
390
|
end
|
377
391
|
|
378
392
|
def on_comment(comment)
|
393
|
+
not_comment = false
|
394
|
+
if @last_ns_token.nil? || @last_ns_token.size == 0
|
395
|
+
if comment =~ SourceParser::SHEBANG_LINE && !@encoding_line
|
396
|
+
@shebang_line = comment
|
397
|
+
not_comment = true
|
398
|
+
elsif comment =~ SourceParser::ENCODING_LINE
|
399
|
+
@encoding_line = comment
|
400
|
+
not_comment = true
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
379
404
|
visit_ns_token(:comment, comment)
|
405
|
+
if not_comment
|
406
|
+
@last_ns_token = nil
|
407
|
+
return
|
408
|
+
end
|
380
409
|
case comment
|
381
410
|
when /\A# @group\s+(.+)\s*\Z/
|
382
411
|
@groups.unshift [lineno, $1]
|
@@ -385,16 +414,20 @@ module YARD
|
|
385
414
|
@groups.unshift [lineno, nil]
|
386
415
|
return
|
387
416
|
end
|
388
|
-
|
389
|
-
comment = comment.gsub(/^\#{1,2}\s{0,1}/, '').chomp
|
390
|
-
append_comment = @comments[lineno - 1]
|
391
417
|
|
418
|
+
comment = comment.gsub(/^(\#{1,2})\s{0,1}/, '').chomp
|
419
|
+
append_comment = @comments[lineno - 1]
|
420
|
+
hash_flag = $1 == '##' ? true : false
|
421
|
+
|
392
422
|
if append_comment && @comments_last_column == column
|
393
423
|
@comments.delete(lineno - 1)
|
424
|
+
@comments_flags[lineno] = @comments_flags[lineno - 1]
|
425
|
+
@comments_flags.delete(lineno - 1)
|
394
426
|
comment = append_comment + "\n" + comment
|
395
427
|
end
|
396
428
|
|
397
429
|
@comments[lineno] = comment
|
430
|
+
@comments_flags[lineno] = hash_flag if !append_comment
|
398
431
|
@comments_last_column = column
|
399
432
|
end
|
400
433
|
|
@@ -424,9 +457,11 @@ module YARD
|
|
424
457
|
(node.line - 2).upto(node.line) do |line|
|
425
458
|
comment = @comments[line]
|
426
459
|
if comment && !comment.empty?
|
460
|
+
node.docstring_hash_flag = @comments_flags[line]
|
427
461
|
node.docstring = comment
|
428
462
|
node.docstring_range = ((line - comment.count("\n"))..line)
|
429
|
-
comments.delete(line)
|
463
|
+
@comments.delete(line)
|
464
|
+
@comments_flags.delete(line)
|
430
465
|
break
|
431
466
|
end
|
432
467
|
end
|
@@ -447,7 +482,7 @@ module YARD
|
|
447
482
|
freeze_tree(child)
|
448
483
|
end
|
449
484
|
end
|
450
|
-
end
|
485
|
+
end if defined?(::Ripper)
|
451
486
|
end
|
452
487
|
end
|
453
488
|
end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
require 'stringio'
|
2
2
|
|
3
|
-
begin
|
4
|
-
require 'continuation'
|
5
|
-
rescue LoadError; end
|
3
|
+
begin require 'continuation'; rescue LoadError; end
|
6
4
|
|
7
5
|
module YARD
|
8
6
|
module Parser
|
@@ -34,6 +32,9 @@ module YARD
|
|
34
32
|
# @see Handlers::Base
|
35
33
|
# @see CodeObjects::Base
|
36
34
|
class SourceParser
|
35
|
+
SHEBANG_LINE = /\A\s*#!\S+/
|
36
|
+
ENCODING_LINE = /\A(?:\s*#*!.*\r?\n)?\s*#+.*coding\s*[:=]{1,2}\s*(\S+)/i
|
37
|
+
|
37
38
|
class << self
|
38
39
|
# @return [Symbol] the default parser type (defaults to :ruby)
|
39
40
|
attr_reader :parser_type
|
@@ -133,13 +134,13 @@ module YARD
|
|
133
134
|
end
|
134
135
|
|
135
136
|
# Returns the validated parser type. Basically, enforces that :ruby
|
136
|
-
# type is never set
|
137
|
+
# type is never set if the Ripper library is not available
|
137
138
|
#
|
138
139
|
# @param [Symbol] type the parser type to set
|
139
140
|
# @return [Symbol] the validated parser type
|
140
141
|
# @private
|
141
142
|
def validated_parser_type(type)
|
142
|
-
|
143
|
+
!defined?(::Ripper) && type == :ruby ? :ruby18 : type
|
143
144
|
end
|
144
145
|
|
145
146
|
private
|
@@ -169,11 +170,11 @@ module YARD
|
|
169
170
|
end
|
170
171
|
end
|
171
172
|
|
172
|
-
|
173
|
-
|
174
|
-
register_parser_type :ruby, Ruby::RubyParser if RUBY19
|
173
|
+
register_parser_type :ruby, Ruby::RubyParser
|
175
174
|
register_parser_type :ruby18, Ruby::Legacy::RubyParser
|
176
175
|
register_parser_type :c, CParser, ['c', 'cc', 'cxx', 'cpp']
|
176
|
+
|
177
|
+
self.parser_type = :ruby
|
177
178
|
|
178
179
|
# The filename being parsed by the parser.
|
179
180
|
attr_reader :file
|
@@ -238,8 +239,8 @@ module YARD
|
|
238
239
|
# Searches for encoding line and forces encoding
|
239
240
|
# @since 0.5.3
|
240
241
|
def convert_encoding(content)
|
241
|
-
return content
|
242
|
-
if content =~
|
242
|
+
return content unless content.respond_to?(:force_encoding)
|
243
|
+
if content =~ ENCODING_LINE
|
243
244
|
content.force_encoding($1)
|
244
245
|
else
|
245
246
|
content
|
data/lib/yard/registry.rb
CHANGED
@@ -9,15 +9,27 @@ module YARD
|
|
9
9
|
# objects are done on the singleton Registry instance using the {Registry.at}
|
10
10
|
# or {Registry.resolve} methods.
|
11
11
|
#
|
12
|
-
#
|
13
|
-
#
|
12
|
+
# == Saving / Loading a Registry
|
13
|
+
# The registry is saved to a "yardoc file" (actually a directory), which can
|
14
|
+
# be loaded back to perform any lookups. See {Registry.load!} and
|
15
|
+
# {Registry.save} for information on saving and loading of a yardoc file.
|
14
16
|
#
|
15
|
-
#
|
16
|
-
#
|
17
|
+
# == Threading Notes
|
18
|
+
# The registry class is a singleton class that is accessed directly in many
|
19
|
+
# places across YARD. To mitigate threading issues, YARD (0.6.5+) makes
|
20
|
+
# the Registry thread local. This means all access to a registry for a specific
|
21
|
+
# object set must occur in the originating thread.
|
22
|
+
#
|
23
|
+
# @example Loading a Registry
|
24
|
+
# Registry.load!('/path/to/yardocfile') # loads all objects into memory
|
25
|
+
# Registry.at('YARD::CodeObjects::Base').docstring
|
26
|
+
# # => "+Base+ is the superclass of all code objects ..."
|
27
|
+
# @example Performing a Search on a Registry
|
28
|
+
# Registry.resolve(P('YARD::CodeObjects::Base'), '#docstring')
|
29
|
+
# # => <
|
17
30
|
module Registry
|
18
31
|
DEFAULT_YARDOC_FILE = ".yardoc"
|
19
32
|
LOCAL_YARDOC_INDEX = File.expand_path('~/.yard/gem_index')
|
20
|
-
@yardoc_file = DEFAULT_YARDOC_FILE
|
21
33
|
|
22
34
|
extend Enumerable
|
23
35
|
|
@@ -58,6 +70,10 @@ module YARD
|
|
58
70
|
# @return [String] the yardoc filename
|
59
71
|
# @see DEFAULT_YARDOC_FILE
|
60
72
|
attr_accessor :yardoc_file
|
73
|
+
def yardoc_file=(v) Thread.current[:__yard_yardoc_file__] = v end
|
74
|
+
def yardoc_file
|
75
|
+
Thread.current[:__yard_yardoc_file__] ||= DEFAULT_YARDOC_FILE
|
76
|
+
end
|
61
77
|
|
62
78
|
# @group Loading Data from Disk
|
63
79
|
|
@@ -81,9 +97,9 @@ module YARD
|
|
81
97
|
if File.exists?(yardoc_file) && !reparse
|
82
98
|
load_yardoc
|
83
99
|
else
|
84
|
-
size =
|
100
|
+
size = thread_local_store.keys.size
|
85
101
|
YARD.parse(files)
|
86
|
-
save if
|
102
|
+
save if thread_local_store.keys.size > size
|
87
103
|
end
|
88
104
|
elsif files.is_a?(String)
|
89
105
|
load_yardoc(files)
|
@@ -99,7 +115,7 @@ module YARD
|
|
99
115
|
# @return [Registry] the registry object (for chaining)
|
100
116
|
def load_yardoc(file = yardoc_file)
|
101
117
|
clear
|
102
|
-
|
118
|
+
thread_local_store.load(file)
|
103
119
|
self
|
104
120
|
end
|
105
121
|
|
@@ -113,7 +129,7 @@ module YARD
|
|
113
129
|
# @since 0.5.1
|
114
130
|
def load!(file = yardoc_file)
|
115
131
|
clear
|
116
|
-
|
132
|
+
thread_local_store.load!(file)
|
117
133
|
self
|
118
134
|
end
|
119
135
|
|
@@ -127,7 +143,7 @@ module YARD
|
|
127
143
|
# @return [Registry] the registry object (for chaining)
|
128
144
|
# @since 0.5.1
|
129
145
|
def load_all
|
130
|
-
|
146
|
+
thread_local_store.load_all
|
131
147
|
self
|
132
148
|
end
|
133
149
|
|
@@ -138,13 +154,13 @@ module YARD
|
|
138
154
|
# @param [String] file the yardoc file to save to
|
139
155
|
# @return [Boolean] true if the file was saved
|
140
156
|
def save(merge = false, file = yardoc_file)
|
141
|
-
|
157
|
+
thread_local_store.save(merge, file)
|
142
158
|
end
|
143
159
|
|
144
160
|
# Deletes the yardoc file from disk
|
145
161
|
# @return [void]
|
146
162
|
def delete_from_disk
|
147
|
-
|
163
|
+
thread_local_store.destroy
|
148
164
|
end
|
149
165
|
|
150
166
|
# @group Adding and Deleting Objects from the Registry
|
@@ -155,20 +171,20 @@ module YARD
|
|
155
171
|
# @return [CodeObjects::Base] the registered object
|
156
172
|
def register(object)
|
157
173
|
return if object.is_a?(CodeObjects::Proxy)
|
158
|
-
|
174
|
+
thread_local_store[object.path] = object
|
159
175
|
end
|
160
176
|
|
161
177
|
# Deletes an object from the registry
|
162
178
|
# @param [CodeObjects::Base] object the object to remove
|
163
179
|
# @return [void]
|
164
180
|
def delete(object)
|
165
|
-
|
181
|
+
thread_local_store.delete(object.path)
|
166
182
|
end
|
167
183
|
|
168
184
|
# Clears the registry
|
169
185
|
# @return [void]
|
170
186
|
def clear
|
171
|
-
|
187
|
+
self.thread_local_store = RegistryStore.new
|
172
188
|
end
|
173
189
|
|
174
190
|
# @group Accessing Objects in the Registry
|
@@ -191,7 +207,7 @@ module YARD
|
|
191
207
|
# @return [Array<CodeObjects::Base>] the list of objects found
|
192
208
|
# @see CodeObjects::Base#type
|
193
209
|
def all(*types)
|
194
|
-
|
210
|
+
thread_local_store.values.select do |obj|
|
195
211
|
if types.empty?
|
196
212
|
obj != root
|
197
213
|
else
|
@@ -207,7 +223,7 @@ module YARD
|
|
207
223
|
# @param [Boolean] reload whether to load entire database
|
208
224
|
# @return [Array<String>] all of the paths in the registry.
|
209
225
|
def paths(reload = false)
|
210
|
-
|
226
|
+
thread_local_store.keys(reload).map {|k| k.to_s }
|
211
227
|
end
|
212
228
|
|
213
229
|
# Returns the object at a specific path.
|
@@ -215,12 +231,12 @@ module YARD
|
|
215
231
|
# returns the {root} object.
|
216
232
|
# @return [CodeObjects::Base] the object at path
|
217
233
|
# @return [nil] if no object is found
|
218
|
-
def at(path) path ?
|
234
|
+
def at(path) path ? thread_local_store[path] : nil end
|
219
235
|
alias_method :[], :at
|
220
236
|
|
221
237
|
# The root namespace object.
|
222
238
|
# @return [CodeObjects::RootObject] the root object in the namespace
|
223
|
-
def root;
|
239
|
+
def root; thread_local_store[:root] end
|
224
240
|
|
225
241
|
# Attempts to find an object by name starting at +namespace+, performing
|
226
242
|
# a lookup similar to Ruby's method of resolving a constant in a namespace.
|
@@ -285,7 +301,7 @@ module YARD
|
|
285
301
|
|
286
302
|
# @return [Hash{String => String}] a set of checksums for files
|
287
303
|
def checksums
|
288
|
-
|
304
|
+
thread_local_store.checksums
|
289
305
|
end
|
290
306
|
|
291
307
|
# @param [String] data data to checksum
|
@@ -294,13 +310,25 @@ module YARD
|
|
294
310
|
Digest::SHA1.hexdigest(data)
|
295
311
|
end
|
296
312
|
|
297
|
-
# @group Managing Internal State (Testing Only)
|
313
|
+
# @group Managing Internal State (Advanced / Testing Only)
|
314
|
+
|
315
|
+
# Whether or not the Registry storage should load everything into a
|
316
|
+
# single object database (for disk efficiency), or spread them out
|
317
|
+
# (for load time efficiency).
|
318
|
+
#
|
319
|
+
# @note Setting this attribute to nil will offload the decision to
|
320
|
+
# the {RegistryStore storage adapter}.
|
321
|
+
# @return [Boolean, nil] if this value is set to nil, the storage
|
322
|
+
# adapter will decide how to store the data.
|
323
|
+
attr_accessor :single_object_db
|
324
|
+
def single_object_db=(v) Thread.current[:__yard_single_db__] = v end
|
325
|
+
def single_object_db; Thread.current[:__yard_single_db__] end
|
298
326
|
|
299
327
|
# The assumed types of a list of paths. This method is used by CodeObjects::Base
|
300
328
|
# @return [{String => Symbol}] a set of unresolved paths and their assumed type
|
301
329
|
# @private
|
302
330
|
def proxy_types
|
303
|
-
|
331
|
+
thread_local_store.proxy_types
|
304
332
|
end
|
305
333
|
|
306
334
|
# @group Legacy Methods
|
@@ -355,8 +383,18 @@ module YARD
|
|
355
383
|
File.exist?(path) ? path : nil
|
356
384
|
end
|
357
385
|
end
|
386
|
+
|
387
|
+
# @group Threading support
|
388
|
+
|
389
|
+
# @since 0.6.5
|
390
|
+
def thread_local_store
|
391
|
+
Thread.current[:__yard_registry__] ||= clear
|
392
|
+
end
|
393
|
+
|
394
|
+
# @since 0.6.5
|
395
|
+
def thread_local_store=(value)
|
396
|
+
Thread.current[:__yard_registry__] = value
|
397
|
+
end
|
358
398
|
end
|
359
|
-
|
360
|
-
clear
|
361
399
|
end
|
362
400
|
end
|