yard 0.8.1 → 0.8.2

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.

Files changed (65) hide show
  1. data/ChangeLog +192 -0
  2. data/README.md +9 -2
  3. data/Rakefile +8 -14
  4. data/lib/yard.rb +1 -1
  5. data/lib/yard/autoload.rb +3 -2
  6. data/lib/yard/cli/graph.rb +28 -10
  7. data/lib/yard/cli/yardoc.rb +4 -1
  8. data/lib/yard/code_objects/proxy.rb +22 -17
  9. data/lib/yard/docstring_parser.rb +7 -7
  10. data/lib/yard/globals.rb +2 -2
  11. data/lib/yard/handlers/base.rb +3 -2
  12. data/lib/yard/handlers/c/handler_methods.rb +1 -0
  13. data/lib/yard/handlers/c/init_handler.rb +7 -5
  14. data/lib/yard/handlers/c/override_comment_handler.rb +9 -1
  15. data/lib/yard/handlers/ruby/class_condition_handler.rb +4 -2
  16. data/lib/yard/handlers/ruby/legacy/class_condition_handler.rb +4 -2
  17. data/lib/yard/handlers/ruby/legacy/mixin_handler.rb +4 -6
  18. data/lib/yard/handlers/ruby/mixin_handler.rb +3 -3
  19. data/lib/yard/handlers/ruby/visibility_handler.rb +1 -1
  20. data/lib/yard/i18n/locale.rb +50 -0
  21. data/lib/yard/i18n/text.rb +110 -9
  22. data/lib/yard/logging.rb +99 -8
  23. data/lib/yard/parser/c/c_parser.rb +1 -1
  24. data/lib/yard/parser/source_parser.rb +5 -4
  25. data/lib/yard/registry.rb +20 -12
  26. data/lib/yard/registry_store.rb +6 -1
  27. data/lib/yard/rubygems/doc_manager.rb +9 -5
  28. data/lib/yard/serializers/yardoc_serializer.rb +1 -0
  29. data/lib/yard/server/commands/base.rb +3 -2
  30. data/lib/yard/server/doc_server_serializer.rb +2 -0
  31. data/lib/yard/server/templates/default/method_details/html/permalink.erb +4 -0
  32. data/lib/yard/server/templates/default/method_details/html/setup.rb +4 -0
  33. data/lib/yard/tags/default_factory.rb +12 -4
  34. data/lib/yard/tags/directives.rb +1 -0
  35. data/lib/yard/templates/engine.rb +13 -6
  36. data/lib/yard/templates/template_options.rb +8 -1
  37. data/spec/cli/graph_spec.rb +10 -0
  38. data/spec/cli/yri_spec.rb +12 -2
  39. data/spec/code_objects/proxy_spec.rb +19 -3
  40. data/spec/handlers/c/class_handler_spec.rb +1 -2
  41. data/spec/handlers/c/init_handler_spec.rb +11 -0
  42. data/spec/handlers/c/override_comment_handler_spec.rb +3 -0
  43. data/spec/handlers/class_condition_handler_spec.rb +5 -0
  44. data/spec/handlers/dsl_handler_spec.rb +1 -0
  45. data/spec/handlers/examples/class_condition_handler_001.rb.txt +8 -0
  46. data/spec/handlers/mixin_handler_spec.rb +2 -1
  47. data/spec/i18n/locale_spec.rb +62 -0
  48. data/spec/i18n/text_spec.rb +144 -35
  49. data/spec/logging_spec.rb +21 -0
  50. data/spec/parser/c_parser_spec.rb +36 -0
  51. data/spec/parser/source_parser_spec.rb +11 -8
  52. data/spec/registry_spec.rb +26 -0
  53. data/spec/rubygems/doc_manager_spec.rb +112 -0
  54. data/spec/tags/default_factory_spec.rb +8 -2
  55. data/spec/tags/directives_spec.rb +7 -0
  56. data/spec/templates/examples/module001.html +0 -4
  57. data/spec/templates/examples/module002.html +0 -1
  58. data/spec/templates/examples/module003.html +0 -1
  59. data/spec/templates/examples/module004.html +171 -172
  60. data/spec/templates/module_spec.rb +4 -0
  61. data/templates/default/fulldoc/html/js/app.js +24 -18
  62. data/templates/default/fulldoc/html/setup.rb +5 -1
  63. data/templates/default/module/html/attribute_details.erb +1 -2
  64. metadata +9 -4
  65. data/lib/yard/server/templates/default/fulldoc/html/js/live.js +0 -17
@@ -55,7 +55,7 @@ module YARD
55
55
  end
56
56
 
57
57
  def consume_directive
58
- return unless @newline
58
+ return(advance) unless @newline
59
59
  @last_comment = nil
60
60
  @last_statement = nil
61
61
  advance_loop do
@@ -40,8 +40,9 @@ module YARD
40
40
  # @see Processor#parse_remaining_files
41
41
  def parse
42
42
  while file = files.shift
43
- log.debug("Processing #{file}...")
44
- SourceParser.new(SourceParser.parser_type, @global_state).parse(file)
43
+ log.capture("Parsing #{file}") do
44
+ SourceParser.new(SourceParser.parser_type, @global_state).parse(file)
45
+ end
45
46
  end
46
47
  end
47
48
  end
@@ -446,10 +447,10 @@ module YARD
446
447
  @parser
447
448
  rescue ArgumentError, NotImplementedError => e
448
449
  log.warn("Cannot parse `#{file}': #{e.message}")
449
- log.backtrace(e) if log.level >= Logger::DEBUG
450
+ log.backtrace(e, :warn)
450
451
  rescue ParserSyntaxError => e
451
452
  log.warn(e.message.capitalize)
452
- log.backtrace(e) if log.level >= Logger::DEBUG
453
+ log.backtrace(e, :warn)
453
454
  end
454
455
 
455
456
  # Tokenizes but does not parse the block of code using the current {#parser_type}
@@ -20,13 +20,14 @@ module YARD
20
20
  # the Registry thread local. This means all access to a registry for a specific
21
21
  # object set must occur in the originating thread.
22
22
  #
23
- # @example Loading a Registry
23
+ # @example Loading the Registry
24
24
  # Registry.load!('/path/to/yardocfile') # loads all objects into memory
25
25
  # Registry.at('YARD::CodeObjects::Base').docstring
26
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
- # # => <
27
+ # @example Getting an object by a specific path
28
+ # Registry.at('YARD::CodeObjects::Base#docstring')
29
+ # @example Performing a lookup on a method anywhere in the inheritance tree
30
+ # Registry.resolve(P('YARD::CodeObjects::Base'), '#docstring', true)
30
31
  module Registry
31
32
  DEFAULT_YARDOC_FILE = ".yardoc"
32
33
  LOCAL_YARDOC_INDEX = File.expand_path('~/.yard/gem_index')
@@ -259,14 +260,16 @@ module YARD
259
260
  # when performing name resolution if set to +true+.
260
261
  # @param [Boolean] proxy_fallback If +true+, returns a proxy representing
261
262
  # the unresolved path (namespace + name) if no object is found.
263
+ # @param [Symbol, nil] type the {CodeObjects::Base#type} that the resolved
264
+ # object must be equal to. No type checking if nil.
262
265
  # @return [CodeObjects::Base] the object if it is found
263
266
  # @return [CodeObjects::Proxy] a Proxy representing the object if
264
267
  # +proxy_fallback+ is +true+.
265
268
  # @return [nil] if +proxy_fallback+ is +false+ and no object was found.
266
269
  # @see P
267
- def resolve(namespace, name, inheritance = false, proxy_fallback = false)
270
+ def resolve(namespace, name, inheritance = false, proxy_fallback = false, type = nil)
268
271
  if namespace.is_a?(CodeObjects::Proxy)
269
- return proxy_fallback ? CodeObjects::Proxy.new(namespace, name) : nil
272
+ return proxy_fallback ? CodeObjects::Proxy.new(namespace, name, type) : nil
270
273
  end
271
274
 
272
275
  if namespace == :root || !namespace
@@ -279,7 +282,8 @@ module YARD
279
282
  name = name.to_s
280
283
  if name =~ /^#{CodeObjects::NSEPQ}/
281
284
  [name, name[2..-1]].each do |n|
282
- return at(n) if at(n)
285
+ found = at(n)
286
+ return found if found && (type.nil? || found.type == type)
283
287
  end
284
288
  else
285
289
  while namespace
@@ -297,14 +301,14 @@ module YARD
297
301
  end
298
302
  nss.each do |ns|
299
303
  next if ns.is_a?(CodeObjects::Proxy)
300
- found = partial_resolve(ns, name)
304
+ found = partial_resolve(ns, name, type)
301
305
  return found if found
302
306
  end
303
307
  end
304
308
  namespace = namespace.parent
305
309
  end
306
310
  end
307
- proxy_fallback ? CodeObjects::Proxy.new(orignamespace, name) : nil
311
+ proxy_fallback ? CodeObjects::Proxy.new(orignamespace, name, type) : nil
308
312
  end
309
313
 
310
314
  # @group Managing Source File Checksums
@@ -338,6 +342,7 @@ module YARD
338
342
  # The assumed types of a list of paths. This method is used by CodeObjects::Base
339
343
  # @return [{String => Symbol}] a set of unresolved paths and their assumed type
340
344
  # @private
345
+ # @deprecated The registry no longer globally tracks proxy types.
341
346
  def proxy_types
342
347
  thread_local_store.proxy_types
343
348
  end
@@ -358,8 +363,11 @@ module YARD
358
363
  #
359
364
  # @param [CodeObjects::NamespaceObject] namespace the starting namespace
360
365
  # @param [String] name the name to look for
361
- def partial_resolve(namespace, name)
362
- return at(name) || at('#' + name) if namespace.root?
366
+ # @param [Symbol, nil] type the {CodeObjects::Base#type} that the resolved
367
+ # object must be equal to
368
+ def partial_resolve(namespace, name, type = nil)
369
+ obj = at(name) || at('#' + name) if namespace.root?
370
+ return obj if obj && (type.nil? || obj.type == type)
363
371
  [CodeObjects::NSEP, CodeObjects::CSEP, ''].each do |s|
364
372
  next if s.empty? && name =~ /^\w/
365
373
  path = name
@@ -367,7 +375,7 @@ module YARD
367
375
  path = [namespace.path, name].join(s)
368
376
  end
369
377
  found = at(path)
370
- return found if found
378
+ return found if found && (type.nil? || found.type == type)
371
379
  end
372
380
  nil
373
381
  end
@@ -6,7 +6,9 @@ module YARD
6
6
  # @see Registry
7
7
  # @see Serializers::YardocSerializer
8
8
  class RegistryStore
9
- attr_reader :proxy_types, :file, :checksums
9
+ # @deprecated The registry no longer tracks proxy types
10
+ attr_reader :proxy_types
11
+ attr_reader :file, :checksums
10
12
 
11
13
  def initialize
12
14
  @file = nil
@@ -207,6 +209,7 @@ module YARD
207
209
  @serializer.objects_path
208
210
  end
209
211
 
212
+ # @deprecated The registry no longer tracks proxy types
210
213
  def proxy_types_path
211
214
  @serializer.proxy_types_path
212
215
  end
@@ -243,6 +246,7 @@ module YARD
243
246
  @store, @proxy_types = *Marshal.load(File.read_binary(@file))
244
247
  end
245
248
 
249
+ # @deprecated The registry no longer tracks proxy types
246
250
  def load_proxy_types
247
251
  return unless File.file?(proxy_types_path)
248
252
  @proxy_types = Marshal.load(File.read_binary(proxy_types_path))
@@ -283,6 +287,7 @@ module YARD
283
287
  Dir.glob(File.join(objects_path, '**/*')).select {|f| File.file?(f) }
284
288
  end
285
289
 
290
+ # @deprecated The registry no longer tracks proxy types
286
291
  def write_proxy_types
287
292
  File.open!(proxy_types_path, 'wb') {|f| f.write(Marshal.dump(@proxy_types)) }
288
293
  end
@@ -1,3 +1,4 @@
1
+ require 'rubygems/user_interaction'
1
2
  require 'rubygems/doc_manager'
2
3
 
3
4
  class Gem::DocManager
@@ -7,10 +8,13 @@ class Gem::DocManager
7
8
 
8
9
  def run_yardoc(*args)
9
10
  args << '--quiet'
10
- args << @spec.require_paths
11
- if @spec.extra_rdoc_files.size > 0
12
- args << '-'
13
- args += @spec.extra_rdoc_files
11
+ args << '--backtrace' if Gem.configuration.backtrace
12
+ unless File.file?(File.join(@spec.full_gem_path, '.yardopts'))
13
+ args << @spec.require_paths
14
+ if @spec.extra_rdoc_files.size > 0
15
+ args << '-'
16
+ args += @spec.extra_rdoc_files
17
+ end
14
18
  end
15
19
  args = args.flatten.map {|arg| arg.to_s }
16
20
 
@@ -23,7 +27,7 @@ class Gem::DocManager
23
27
  rescue => ex
24
28
  alert_error "While generating documentation for #{@spec.full_name}"
25
29
  ui.errs.puts "... MESSAGE: #{ex}"
26
- ui.errs.puts "... YARDDOC args: #{args.join(' ')}"
30
+ ui.errs.puts "... YARDOC args: #{args.join(' ')}"
27
31
  ui.errs.puts "\t#{ex.backtrace.join("\n\t")}" if Gem.configuration.backtrace
28
32
  ui.errs.puts "(continuing with the rest of the installation)"
29
33
  ensure
@@ -32,6 +32,7 @@ module YARD
32
32
  end
33
33
 
34
34
  def objects_path; File.join(basepath, 'objects') end
35
+ # @deprecated The registry no longer tracks proxy types
35
36
  def proxy_types_path; File.join(basepath, 'proxy_types') end
36
37
  def checksums_path; File.join(basepath, 'checksums') end
37
38
  def object_types_path; File.join(basepath, 'object_types') end
@@ -136,11 +136,12 @@ module YARD
136
136
  # receive +#options+ as an argument.
137
137
  # @return [String] the resulting output to display
138
138
  def render(object = nil)
139
+ opts = options.merge(:serialize => false)
139
140
  case object
140
141
  when CodeObjects::Base
141
- cache object.format(options)
142
+ cache object.format(opts)
142
143
  when nil
143
- cache Templates::Engine.render(options)
144
+ cache Templates::Engine.render(opts)
144
145
  else
145
146
  cache object
146
147
  end
@@ -15,6 +15,8 @@ module YARD
15
15
  case object
16
16
  when CodeObjects::RootObject
17
17
  "toplevel"
18
+ when CodeObjects::ExtendedMethodObject
19
+ serialized_path(object.namespace) + ':' + escape(object.name.to_s)
18
20
  when CodeObjects::MethodObject
19
21
  serialized_path(object.namespace) +
20
22
  (object.scope == :instance ? ":" : ".") + escape(object.name.to_s)
@@ -0,0 +1,4 @@
1
+ <script>
2
+ $("#<%= anchor_for(object) %>").prepend(
3
+ '<a class="permalink" href="/<%= base_path(router.docs_prefix) %>/<%= serializer.serialized_path(object) %>">permalink</a>');
4
+ </script>
@@ -0,0 +1,4 @@
1
+ def init
2
+ super
3
+ sections.place(:permalink).after_any(:method_signature)
4
+ end
@@ -134,14 +134,20 @@ module YARD
134
134
  def extract_types_and_name_from_text_unstripped(text, opening_types = TYPELIST_OPENING_CHARS, closing_types = TYPELIST_CLOSING_CHARS)
135
135
  s, e = 0, 0
136
136
  before = ''
137
- list, level, seen_space = [''], 0, false
138
- text.split(//).each_with_index do |c, i|
139
- if opening_types.include?(c)
137
+ list, level, seen_space, i = [''], 0, false, 0
138
+ last_seen = ''
139
+ while i < text.length
140
+ c = text[i, 1]
141
+ if level > 0 && c == '#' && text[i+1..-1] =~ CodeObjects::METHODNAMEMATCH
142
+ list.last << c + $&
143
+ i += $&.length + 1
144
+ next
145
+ elsif opening_types.include?(c)
140
146
  list.last << c if level > 0
141
147
  s = i if level == 0
142
148
  level += 1
143
149
  elsif closing_types.include?(c)
144
- level -= 1 unless list.last[-1,1] == '=' && c == '>'
150
+ level -= 1 unless last_seen == '=' && c == '>'
145
151
  break e = i if level == 0
146
152
  list.last << c
147
153
  elsif c == ',' && level == 1
@@ -154,6 +160,8 @@ module YARD
154
160
  elsif level >= 1
155
161
  list.last << c
156
162
  end
163
+ last_seen = c
164
+ i += 1
157
165
  end
158
166
 
159
167
  before = before.empty? ? nil : before
@@ -401,6 +401,7 @@ module YARD
401
401
  handler.register_visibility(obj, visibility)
402
402
  handler.register_group(obj)
403
403
  obj.signature = method_signature
404
+ obj.parameters = OverloadTag.new(:overload, method_signature).parameters
404
405
  obj.docstring = Docstring.new!(parser.text, parser.tags, obj,
405
406
  parser.raw_text)
406
407
  handler.register_module_function(obj)
@@ -82,7 +82,7 @@ module YARD
82
82
  options = set_default_options(options)
83
83
  mod = template(options.template, options.type, options.format)
84
84
 
85
- if options.serialize != false
85
+ if options.serializer && options.serialize != false
86
86
  with_serializer(options.object, options.serializer) { mod.run(options) }
87
87
  else
88
88
  mod.run(options)
@@ -112,11 +112,18 @@ module YARD
112
112
  # @yieldreturn [String] the contents to serialize
113
113
  # @see Serializers::Base
114
114
  def with_serializer(object, serializer, &block)
115
- serializer.before_serialize if serializer
116
- output = yield
117
- if serializer
118
- serializer.serialize(object, output)
119
- serializer.after_serialize(output)
115
+ output = nil
116
+ filename = serializer.serialized_path(object)
117
+ if serializer.respond_to?(:basepath)
118
+ filename = File.join(serializer.basepath, filename)
119
+ end
120
+ log.capture("Generating #{filename}", nil) do
121
+ serializer.before_serialize if serializer
122
+ output = yield
123
+ if serializer
124
+ serializer.serialize(object, output)
125
+ serializer.after_serialize(output)
126
+ end
120
127
  end
121
128
  output
122
129
  end
@@ -36,11 +36,14 @@ module YARD
36
36
  # @return [CodeObjects::Base] the main object being generated in the template
37
37
  attr_accessor :object
38
38
 
39
+ # @return [CodeObjects::Base] the owner of the generated object
40
+ attr_accessor :owner
41
+
39
42
  # @return [Symbol] the template type used to generate output
40
43
  attr_accessor :type
41
44
 
42
45
  # @return [Boolean] whether serialization should be performed
43
- default_attr :serialize, false
46
+ default_attr :serialize, true
44
47
 
45
48
  # @return [Serializers::Base] the serializer used to generate links and serialize
46
49
  # output. Serialization output only occurs if {#serialize} is +true+.
@@ -70,12 +73,16 @@ module YARD
70
73
  # @return [nil] if the mixin is not a module object
71
74
  def embed_mixins_match?(mixin)
72
75
  return nil unless mixin.is_a?(CodeObjects::ModuleObject)
76
+ return nil if mixin == object # the method is not inherited
73
77
  embed_mixins.any? do |embed_mixin|
74
78
  re = /\A#{Regexp.quote(embed_mixin).gsub('\*', '.*')}\Z/
75
79
  matchstr = embed_mixin.include?("::") ? mixin.path : mixin.name
76
80
  re.match(matchstr.to_s)
77
81
  end
78
82
  end
83
+
84
+ # @return [Verifier] the verifier object
85
+ attr_accessor :verifier
79
86
  end
80
87
  end
81
88
  end
@@ -0,0 +1,10 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe YARD::CLI::Yardoc do
4
+ it "should serialize output" do
5
+ Registry.should_receive(:load)
6
+ @graph = YARD::CLI::Graph.new
7
+ @graph.options.serializer.should_receive(:serialize).once
8
+ @graph.run
9
+ end
10
+ end
@@ -1,12 +1,14 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
2
 
3
- class YARD::CLI::YRI
3
+ class TestYRI < YARD::CLI::YRI
4
4
  public :optparse, :find_object, :cache_object
5
+ def test_stub; end
6
+ def print_object(*args) test_stub; super end
5
7
  end
6
8
 
7
9
  describe YARD::CLI::YRI do
8
10
  before do
9
- @yri = YARD::CLI::YRI.new
11
+ @yri = TestYRI.new
10
12
  Registry.stub!(:load)
11
13
  end
12
14
 
@@ -85,5 +87,13 @@ describe YARD::CLI::YRI do
85
87
  @yri.should_receive(:exit).with(1)
86
88
  @yri.run('Foo')
87
89
  end
90
+
91
+ it "should ensure output is serialized" do
92
+ obj = YARD::CodeObjects::ClassObject.new(:root, 'Foo')
93
+ class << @yri
94
+ def test_stub; @serializer.should_receive(:serialize).once end
95
+ end
96
+ @yri.run('Foo')
97
+ end
88
98
  end
89
99
  end
@@ -78,9 +78,26 @@ describe YARD::CodeObjects::Proxy do
78
78
  obj.type.should == :class
79
79
  end
80
80
 
81
- it "should retain a type change between Proxy objects" do
81
+ it "should NOT retain a type change between Proxy objects" do
82
82
  P("InvalidClass").type = :class
83
- P("InvalidClass").type.should == :class
83
+ P("InvalidClass").type.should == :proxy
84
+ end
85
+
86
+ it "should use type to ensure resolved object is of intended type" do
87
+ YARD.parse_string <<-eof
88
+ module Foo
89
+ class Bar; end
90
+ def self.Bar; end
91
+ end
92
+ eof
93
+ proxy = Proxy.new(P('Foo'), 'Bar')
94
+ proxy.type = :method
95
+ proxy.path.should == 'Foo.Bar'
96
+ end
97
+
98
+ it "should allow type in initializer" do
99
+ Proxy.new(Registry.root, 'Foo', :method).type.should == :method
100
+ P(Registry.root, 'Foo', :method).type.should == :method
84
101
  end
85
102
 
86
103
  it "should never equal Registry.root" do
@@ -113,7 +130,6 @@ describe YARD::CodeObjects::Proxy do
113
130
  proxy.type.should == :module
114
131
  end
115
132
 
116
-
117
133
  it "should handle constant names in namespaces" do
118
134
  YARD.parse_string <<-eof
119
135
  module A; end; B = A
@@ -58,7 +58,6 @@ describe YARD::Handlers::C::ClassHandler do
58
58
  eof
59
59
  Registry.at('Foo::Bar').type.should == :class
60
60
  Registry.at('Foo::Bar').superclass.should == P('Bar')
61
- P('Bar').should be_a(CodeObjects::Proxy)
62
- P('Bar').type.should == :class
61
+ Registry.at('Foo::Bar').superclass.type.should == :class
63
62
  end
64
63
  end
@@ -33,4 +33,15 @@ describe YARD::Handlers::C::InitHandler do
33
33
  eof
34
34
  Registry.at('A').docstring.should == 'Foo!'
35
35
  end
36
+
37
+ it "should check non-Init methods for declarations too" do
38
+ parse(<<-eof)
39
+ void foo(int x, int y, char *name) {
40
+ rb_cB = rb_define_class("B", rb_cObject);
41
+ rb_define_method(rb_cB, "foo", foo_impl, 0);
42
+ }
43
+ eof
44
+ Registry.at('B').should be_a(CodeObjects::ClassObject)
45
+ Registry.at('B#foo').should be_a(CodeObjects::MethodObject)
46
+ end
36
47
  end