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.

Files changed (107) hide show
  1. data/ChangeLog +341 -0
  2. data/LICENSE +1 -1
  3. data/README.md +31 -6
  4. data/Rakefile +22 -3
  5. data/docs/Tags.md +5 -1
  6. data/docs/WhatsNew.md +18 -1
  7. data/lib/rubygems_plugin.rb +3 -99
  8. data/lib/yard.rb +1 -1
  9. data/lib/yard/autoload.rb +37 -35
  10. data/lib/yard/cli/config.rb +25 -2
  11. data/lib/yard/cli/graph.rb +1 -1
  12. data/lib/yard/cli/yardoc.rb +4 -0
  13. data/lib/yard/code_objects/base.rb +17 -9
  14. data/lib/yard/code_objects/method_object.rb +0 -9
  15. data/lib/yard/code_objects/proxy.rb +6 -0
  16. data/lib/yard/docstring.rb +5 -0
  17. data/lib/yard/handlers/base.rb +3 -1
  18. data/lib/yard/handlers/processor.rb +1 -1
  19. data/lib/yard/handlers/ruby/alias_handler.rb +9 -8
  20. data/lib/yard/handlers/ruby/class_handler.rb +3 -3
  21. data/lib/yard/handlers/ruby/legacy/alias_handler.rb +9 -7
  22. data/lib/yard/handlers/ruby/legacy/method_handler.rb +7 -0
  23. data/lib/yard/handlers/ruby/legacy/private_constant_handler.rb +21 -0
  24. data/lib/yard/handlers/ruby/method_condition_handler.rb +1 -1
  25. data/lib/yard/handlers/ruby/method_handler.rb +7 -0
  26. data/lib/yard/handlers/ruby/private_constant_handler.rb +36 -0
  27. data/lib/yard/parser/ruby/ast_node.rb +41 -24
  28. data/lib/yard/parser/ruby/legacy/ruby_parser.rb +3 -0
  29. data/lib/yard/parser/ruby/legacy/statement.rb +2 -0
  30. data/lib/yard/parser/ruby/legacy/statement_list.rb +27 -4
  31. data/lib/yard/parser/ruby/ruby_parser.rb +71 -36
  32. data/lib/yard/parser/source_parser.rb +11 -10
  33. data/lib/yard/registry.rb +62 -24
  34. data/lib/yard/registry_store.rb +18 -5
  35. data/lib/yard/rubygems/doc_manager.rb +75 -0
  36. data/lib/yard/rubygems/specification.rb +23 -0
  37. data/lib/yard/serializers/process_serializer.rb +1 -1
  38. data/lib/yard/serializers/yardoc_serializer.rb +7 -2
  39. data/lib/yard/server/commands/display_object_command.rb +1 -1
  40. data/lib/yard/server/commands/library_command.rb +2 -2
  41. data/lib/yard/tags/default_factory.rb +1 -1
  42. data/lib/yard/tags/library.rb +2 -2
  43. data/lib/yard/templates/helpers/base_helper.rb +19 -0
  44. data/lib/yard/templates/helpers/html_helper.rb +22 -9
  45. data/lib/yard/templates/helpers/html_syntax_highlight_helper.rb +28 -0
  46. data/lib/yard/templates/helpers/markup_helper.rb +14 -22
  47. data/lib/yard/templates/template.rb +1 -1
  48. data/spec/cli/config_spec.rb +20 -0
  49. data/spec/cli/yardoc_spec.rb +12 -0
  50. data/spec/code_objects/base_spec.rb +13 -0
  51. data/spec/code_objects/proxy_spec.rb +9 -0
  52. data/spec/config_spec.rb +4 -1
  53. data/spec/docstring_spec.rb +5 -0
  54. data/spec/handlers/alias_handler_spec.rb +14 -1
  55. data/spec/handlers/attribute_handler_spec.rb +1 -1
  56. data/spec/handlers/base_spec.rb +21 -21
  57. data/spec/handlers/class_condition_handler_spec.rb +1 -1
  58. data/spec/handlers/class_handler_spec.rb +1 -1
  59. data/spec/handlers/class_variable_handler_spec.rb +1 -1
  60. data/spec/handlers/constant_handler_spec.rb +2 -2
  61. data/spec/handlers/examples/alias_handler_001.rb.txt +14 -0
  62. data/spec/handlers/examples/method_handler_001.rb.txt +6 -0
  63. data/spec/handlers/examples/module_handler_001.rb.txt +4 -0
  64. data/spec/handlers/examples/private_constant_handler_001.rb.txt +8 -0
  65. data/spec/handlers/exception_handler_spec.rb +1 -1
  66. data/spec/handlers/extend_handler_spec.rb +1 -1
  67. data/spec/handlers/method_condition_handler_spec.rb +1 -1
  68. data/spec/handlers/method_handler_spec.rb +7 -1
  69. data/spec/handlers/mixin_handler_spec.rb +1 -1
  70. data/spec/handlers/module_handler_spec.rb +5 -1
  71. data/spec/handlers/private_constant_handler_spec.rb +24 -0
  72. data/spec/handlers/process_handler_spec.rb +1 -1
  73. data/spec/handlers/ruby/base_spec.rb +4 -4
  74. data/spec/handlers/visibility_handler_spec.rb +1 -1
  75. data/spec/handlers/yield_handler_spec.rb +1 -1
  76. data/spec/parser/base_spec.rb +3 -5
  77. data/spec/parser/c_parser_spec.rb +1 -1
  78. data/spec/parser/ruby/ast_node_spec.rb +23 -26
  79. data/spec/parser/ruby/legacy/statement_list_spec.rb +9 -0
  80. data/spec/parser/ruby/ruby_parser_spec.rb +179 -177
  81. data/spec/parser/source_parser_spec.rb +41 -7
  82. data/spec/rake/yardoc_task_spec.rb +3 -3
  83. data/spec/registry_spec.rb +52 -0
  84. data/spec/registry_store_spec.rb +71 -1
  85. data/spec/serializers/yardoc_serializer_spec.rb +18 -7
  86. data/spec/server/rack_adapter_spec.rb +2 -2
  87. data/spec/spec_helper.rb +10 -0
  88. data/spec/tags/default_factory_spec.rb +122 -120
  89. data/spec/templates/helpers/base_helper_spec.rb +38 -14
  90. data/spec/templates/helpers/html_helper_spec.rb +19 -0
  91. data/spec/templates/helpers/html_syntax_highlight_helper_spec.rb +10 -6
  92. data/spec/templates/helpers/markup_helper_spec.rb +21 -5
  93. data/templates/default/class/dot/superklass.erb +1 -1
  94. data/templates/default/docstring/setup.rb +1 -1
  95. data/templates/default/fulldoc/html/css/style.css +12 -4
  96. data/templates/default/fulldoc/html/js/app.js +1 -1
  97. data/templates/default/fulldoc/html/js/jquery.js +5 -143
  98. data/templates/default/layout/html/files.erb +11 -0
  99. data/templates/default/layout/html/headers.erb +1 -1
  100. data/templates/default/layout/html/index.erb +2 -49
  101. data/templates/default/layout/html/listing.erb +4 -0
  102. data/templates/default/layout/html/objects.erb +32 -0
  103. data/templates/default/layout/html/setup.rb +1 -1
  104. data/templates/default/module/dot/info.erb +1 -1
  105. data/templates/default/module/dot/setup.rb +1 -1
  106. metadata +15 -6
  107. data/lib/yard/templates/helpers/html_syntax_highlight_helper18.rb +0 -25
@@ -1,10 +1,8 @@
1
1
  require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
2
 
3
+ class MyParser < Parser::Base; end
4
+
3
5
  shared_examples_for "parser type registration" do
4
- before do
5
- class MyParser < Parser::Base; end
6
- end
7
-
8
6
  after do
9
7
  Parser::SourceParser.parser_types.delete(:my_parser)
10
8
  Parser::SourceParser.parser_type_extensions.delete(:my_parser)
@@ -80,6 +78,22 @@ describe YARD::Parser::SourceParser do
80
78
  Registry.at("Hello::Hi#me").docstring.line_range.should == (3..4)
81
79
  end
82
80
 
81
+ it "should parse Ruby code with metaclasses" do
82
+ YARD.parse_string(<<-eof)
83
+ module Hello
84
+ class Hi
85
+ class <<self
86
+ # Docstring
87
+ def me; "VALUE" end
88
+ end
89
+ end
90
+ end
91
+ eof
92
+ Registry.at(:Hello).should_not == nil
93
+ Registry.at("Hello::Hi.me").should_not == nil
94
+ Registry.at("Hello::Hi.me").docstring.should == "Docstring"
95
+ end
96
+
83
97
  it "should only use prepended comments for an object" do
84
98
  YARD.parse_string(<<-eof)
85
99
  # Test
@@ -137,6 +151,23 @@ describe YARD::Parser::SourceParser do
137
151
  YARD.parse_string "=begin\nfoo\n\nbar\n=end\nclass Foo; end\n"
138
152
  Registry.at(:Foo).docstring.should == "foo\n\nbar"
139
153
  end
154
+
155
+ it "should know about docstrings starting with ##" do
156
+ {'#' => false, '##' => true}.each do |hash, expected|
157
+ YARD.parse_string "#{hash}\n# Foo bar\nclass Foo; end"
158
+ Registry.at(:Foo).docstring.hash_flag.should == expected
159
+ end
160
+ end
161
+
162
+ it "should remove shebang from initial file comments" do
163
+ YARD.parse_string "#!/bin/ruby\n# this is a comment\nclass Foo; end"
164
+ Registry.at(:Foo).docstring.should == "this is a comment"
165
+ end
166
+
167
+ it "should remove encoding line from initial file comments" do
168
+ YARD.parse_string "# encoding: utf-8\n# this is a comment\nclass Foo; end"
169
+ Registry.at(:Foo).docstring.should == "this is a comment"
170
+ end
140
171
  end
141
172
 
142
173
  describe '#parse' do
@@ -232,10 +263,13 @@ describe YARD::Parser::SourceParser do
232
263
  parser = Parser::SourceParser.new
233
264
  File.should_receive(:read_binary).with('tmpfile').and_return(src)
234
265
  result = parser.parse("tmpfile")
235
- result.enumerator[0].source.encoding.to_s.send(msg) == 'Shift_JIS'
266
+ if HAVE_RIPPER && RUBY19
267
+ result.enumerator[0].source.encoding.to_s.send(msg) == 'Shift_JIS'
268
+ end
269
+ result.encoding_line.send(msg) == src.split("\n").last
236
270
  end
237
271
  end
238
- end if RUBY19
272
+ end
239
273
  end
240
274
 
241
275
  describe '#parse_in_order' do
@@ -269,7 +303,7 @@ describe YARD::Parser::SourceParser do
269
303
  YARD::Parser::SourceParser.parse_string("int main() { }", :d)
270
304
  end
271
305
 
272
- if RUBY19
306
+ if HAVE_RIPPER
273
307
  it "should display a warning for a syntax error (with new parser)" do
274
308
  err_msg = "Syntax error in `(stdin)`:(1,3): syntax error, unexpected $undefined, expecting $end"
275
309
  log.should_receive(:warn).with(err_msg)
@@ -4,17 +4,17 @@ describe YARD::Rake::YardocTask do
4
4
  before do
5
5
  @yardoc = mock(:cli)
6
6
  YARD::CLI::Yardoc.stub!(:new).and_return(@yardoc)
7
- Rake.application.clear
7
+ ::Rake.application.clear
8
8
  end
9
9
 
10
10
  def run
11
- Rake.application.tasks[0].invoke
11
+ ::Rake.application.tasks[0].invoke
12
12
  end
13
13
 
14
14
  describe '#initialize' do
15
15
  it "should allow separate rake task name to be set" do
16
16
  YARD::Rake::YardocTask.new(:notyardoc)
17
- Rake.application.tasks[0].name.should == "notyardoc"
17
+ ::Rake.application.tasks[0].name.should == "notyardoc"
18
18
  end
19
19
  end
20
20
 
@@ -236,4 +236,56 @@ describe YARD::Registry do
236
236
  Registry.instance.should == Registry
237
237
  end
238
238
  end
239
+
240
+ describe '.single_object_db' do
241
+ it "should default to nil" do
242
+ Registry.single_object_db.should == nil
243
+ Thread.new { Registry.single_object_db.should == nil }.join
244
+ end
245
+ end
246
+
247
+ describe 'Thread local' do
248
+ it "should maintain two Registries in separate threads" do
249
+ barrier = 0
250
+ threads = []
251
+ threads << Thread.new do
252
+ Registry.clear
253
+ YARD.parse_string "# docstring 1\nclass Foo; end"
254
+ barrier += 1
255
+ while barrier < 2 do end
256
+ Registry.at('Foo').docstring.should == "docstring 1"
257
+ end
258
+ threads << Thread.new do
259
+ Registry.clear
260
+ YARD.parse_string "# docstring 2\nclass Foo; end"
261
+ barrier += 1
262
+ while barrier < 2 do end
263
+ Registry.at('Foo').docstring.should == "docstring 2"
264
+ end
265
+ threads.each {|t| t.join }
266
+ end
267
+
268
+ it "should allow setting of yardoc_file in separate threads" do
269
+ barrier = 0
270
+ threads = []
271
+ threads << Thread.new do
272
+ Registry.yardoc_file.should == '.yardoc'
273
+ Registry.yardoc_file = 'foo'
274
+ barrier += 1
275
+ while barrier == 1 do end
276
+ Registry.yardoc_file.should == 'foo'
277
+ end
278
+ threads << Thread.new do
279
+ while barrier == 0 do end
280
+ Registry.yardoc_file.should == '.yardoc'
281
+ barrier += 1
282
+ Registry.yardoc_file = 'foo2'
283
+ end
284
+ threads.each {|t| t.join }
285
+ end
286
+
287
+ it "should automatically clear in new threads" do
288
+ Thread.new { Registry.all.should be_empty }.join
289
+ end
290
+ end
239
291
  end
@@ -1,9 +1,23 @@
1
1
  require File.join(File.dirname(__FILE__), "spec_helper")
2
2
 
3
3
  describe YARD::RegistryStore do
4
- before { @store = RegistryStore.new }
4
+ before do
5
+ @store = RegistryStore.new
6
+ @serializer = Serializers::YardocSerializer.new('foo')
7
+ Serializers::YardocSerializer.stub!(:new).and_return(@serializer)
8
+ end
5
9
 
6
10
  describe '#load' do
11
+ it "should load root.dat as full object list if it is a Hash" do
12
+ File.should_receive(:directory?).with('foo').and_return(true)
13
+ File.should_receive(:file?).with('foo/checksums').and_return(false)
14
+ File.should_receive(:file?).with('foo/proxy_types').and_return(false)
15
+ @serializer.should_receive(:deserialize).with('root').and_return({:root => 'foo', :A => 'bar'})
16
+ @store.load('foo').should == true
17
+ @store.root.should == 'foo'
18
+ @store.get('A').should == 'bar'
19
+ end
20
+
7
21
  it "should load old yardoc format if .yardoc is a file" do
8
22
  File.should_receive(:directory?).with('foo').and_return(false)
9
23
  File.should_receive(:file?).with('foo').and_return(true)
@@ -78,6 +92,62 @@ describe YARD::RegistryStore do
78
92
  end
79
93
  end
80
94
 
95
+ describe '#save' do
96
+ before do
97
+ @store.stub!(:write_proxy_types)
98
+ @store.stub!(:write_checksums)
99
+ @store.stub!(:destroy)
100
+ end
101
+
102
+ after do
103
+ Registry.single_object_db = nil
104
+ end
105
+
106
+ def saves_to_singledb
107
+ @serializer.should_receive(:serialize).once.with(instance_of(Hash))
108
+ @store.save(true, 'foo')
109
+ end
110
+
111
+ def add_items(n)
112
+ n.times {|i| @store[i.to_s] = 'foo' }
113
+ end
114
+
115
+ def saves_to_multidb
116
+ times = @store.keys.size
117
+ @serializer.should_receive(:serialize).exactly(times).times
118
+ @store.save(true, 'foo')
119
+ @last = times
120
+ end
121
+
122
+ it "should save as single object db if single_object_db is nil and there are less than 3000 objects" do
123
+ Registry.single_object_db = nil
124
+ add_items(100)
125
+ saves_to_singledb
126
+ end
127
+
128
+ it "should not save as single object db if single_object_db is nil and there are more than 3000 objects" do
129
+ Registry.single_object_db = nil
130
+ add_items(5000)
131
+ saves_to_multidb
132
+ end
133
+
134
+ it "should save as single object db if single_object_db is true (and any amount of objects)" do
135
+ Registry.single_object_db = true
136
+ add_items(100)
137
+ saves_to_singledb
138
+ add_items(5000)
139
+ saves_to_singledb
140
+ end
141
+
142
+ it "should never save as single object db if single_object_db is false" do
143
+ Registry.single_object_db = false
144
+ add_items(100)
145
+ saves_to_multidb
146
+ add_items(5000)
147
+ saves_to_multidb
148
+ end
149
+ end
150
+
81
151
  describe '#put' do
82
152
  it "should assign values" do
83
153
  @store.put(:YARD, true)
@@ -8,15 +8,15 @@ instance_eval do
8
8
  end
9
9
 
10
10
  describe YARD::Serializers::YardocSerializer do
11
- describe '#dump' do
12
- before do
13
- @serializer = YARD::Serializers::YardocSerializer.new('.yardoc')
11
+ before do
12
+ @serializer = YARD::Serializers::YardocSerializer.new('.yardoc')
14
13
 
15
- Registry.clear
16
- @foo = CodeObjects::ClassObject.new(:root, :Foo)
17
- @bar = CodeObjects::MethodObject.new(@foo, :bar)
18
- end
14
+ Registry.clear
15
+ @foo = CodeObjects::ClassObject.new(:root, :Foo)
16
+ @bar = CodeObjects::MethodObject.new(@foo, :bar)
17
+ end
19
18
 
19
+ describe '#dump' do
20
20
  it "should maintain object equality when loading a dumped object" do
21
21
  newfoo = @serializer.internal_dump(@foo)
22
22
  newfoo.should equal(@foo)
@@ -32,4 +32,15 @@ describe YARD::Serializers::YardocSerializer do
32
32
  {newfoo => 1}.should have_key(@foo)
33
33
  end
34
34
  end
35
+
36
+ describe '#serialize' do
37
+ it "should accept a hash of codeobjects (and write to root)" do
38
+ data = {:root => Registry.root}
39
+ marshaldata = Marshal.dump(data)
40
+ filemock = mock(:file)
41
+ filemock.should_receive(:write).with(marshaldata)
42
+ File.should_receive(:open!).with('.yardoc/objects/root.dat', 'wb').and_yield(filemock)
43
+ @serializer.serialize(data)
44
+ end
45
+ end
35
46
  end
@@ -12,7 +12,7 @@ describe "YARD::Server::RackMiddleware" do
12
12
  end
13
13
 
14
14
  it "should pass up to the next middleware on 404" do
15
- @superapp.should_receive(:call).and_return([200, {}, 'OK'])
16
- @app.call(Rack::MockRequest.env_for('/INVALID')).should == [200, {}, 'OK']
15
+ @superapp.should_receive(:call).and_return([200, {}, ['OK']])
16
+ @app.call(Rack::MockRequest.env_for('/INVALID')).should == [200, {}, ['OK']]
17
17
  end
18
18
  end
data/spec/spec_helper.rb CHANGED
@@ -7,6 +7,16 @@ end
7
7
 
8
8
  require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'yard'))
9
9
 
10
+ unless defined?(HAVE_RIPPER)
11
+ begin require 'ripper'; rescue LoadError; end
12
+ HAVE_RIPPER = defined?(::Ripper) && !ENV['LEGACY'] ? true : false
13
+ LEGACY_PARSER = !HAVE_RIPPER
14
+
15
+ class YARD::Parser::SourceParser
16
+ def self.parser_type; :ruby18 end
17
+ end if ENV['LEGACY']
18
+ end
19
+
10
20
  def parse_file(file, thisfile = __FILE__, log_level = log.level, ext = '.rb.txt')
11
21
  Registry.clear
12
22
  path = File.join(File.dirname(thisfile), 'examples', file.to_s + ext)
@@ -1,136 +1,138 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
2
 
3
- describe YARD::Tags::DefaultFactory, "extract_types_and_name_from_text" do
3
+ describe YARD::Tags::DefaultFactory do
4
4
  before { @f = YARD::Tags::DefaultFactory.new }
5
-
6
- def parse_types(types)
7
- @f.send(:extract_types_and_name_from_text, types)
8
- end
9
-
10
- it "should handle one type" do
11
- parse_types('[A]').should == [nil, ['A'], ""]
12
- end
13
5
 
14
- it "should handle a list of types" do
15
- parse_types('[A, B, C]').should == [nil, ['A', 'B', 'C'], ""]
16
- end
17
-
18
- it "should return the text before and after the type list" do
19
- parse_types(' b <String> description').should == ['b', ['String'], 'description']
20
- parse_types('b c <String> description (test)').should == [nil, nil, 'b c <String> description (test)']
6
+ describe '#parse_tag' do
7
+ it "should not have trailing whitespace on a regular freeform tag" do
8
+ @f.parse_tag('api', 'private ').text.should == "private"
9
+ end
21
10
  end
22
-
23
- it "should handle a complex list of types" do
24
- v = parse_types(' [Test, Array<String, Hash, C>, String]')
25
- v.should include(["Test", "Array<String, Hash, C>", "String"])
26
- end
27
-
28
- it "should handle any of the following start/end delimiting chars: (), <>, {}, []" do
29
- a = parse_types('[a,b,c]')
30
- b = parse_types('<a,b,c>')
31
- c = parse_types('(a,b,c)')
32
- d = parse_types('{a,b,c}')
33
- a.should == b
34
- b.should == c
35
- c.should == d
36
- a.should include(['a','b','c'])
37
- end
38
-
39
- it "should return the text before the type list as the last element" do
40
- parse_types('b[x, y, z]').should == ['b', ['x', 'y', 'z'], '']
41
- parse_types(' ! <x>').should == ["!", ['x'], '']
42
- end
43
-
44
- it "should return text unparsed if there is no type list" do
45
- parse_types('').should == [nil, nil, '']
46
- parse_types('[]').should == [nil, nil, '[]']
47
- end
48
-
49
- it "should allow A => B syntax" do
50
- v = parse_types(' [Test, Array<String, Hash{A => {B => C}}, C>, String]')
51
- v.should include(["Test", "Array<String, Hash{A => {B => C}}, C>", "String"])
52
- end
53
- end
54
11
 
55
- describe YARD::Tags::DefaultFactory, '#parse_tag_with_types' do
56
- before { @f = YARD::Tags::DefaultFactory.new }
57
-
58
- def parse_types(text)
59
- @f.send(:parse_tag_with_types, 'test', text)
60
- end
61
-
62
- it "should parse given types and description" do
63
- YARD::Tags::Tag.should_receive(:new).with("test", "description", ["x", "y", "z"])
64
- parse_types(' [x, y, z] description')
65
- end
66
-
67
- it "should parse given types only" do
68
- YARD::Tags::Tag.should_receive(:new).with("test", "", ["x", "y", "z"])
69
- parse_types(' [x, y, z] ')
70
- end
71
-
72
- it "should allow type list to be omitted" do
73
- YARD::Tags::Tag.should_receive(:new).with('test', 'description', nil)
74
- parse_types(' description ')
75
- end
76
-
77
- it "should raise an error if a name is specified before type list" do
78
- lambda { parse_types('b<String> desc') }.should raise_error(YARD::Tags::TagFormatError, 'cannot specify a name before type list for \'@test\'')
79
- end
80
- end
12
+ describe '#extract_types_and_name_from_text' do
13
+ def parse_types(types)
14
+ @f.send(:extract_types_and_name_from_text, types)
15
+ end
16
+
17
+ it "should handle one type" do
18
+ parse_types('[A]').should == [nil, ['A'], ""]
19
+ end
81
20
 
82
- describe YARD::Tags::DefaultFactory, '#parse_tag_with_types_name_and_default' do
83
- before { @f = YARD::Tags::DefaultFactory.new }
84
-
85
- def parse_types(text)
86
- @f.send(:parse_tag_with_types_name_and_default, 'test', text)
87
- end
88
-
89
- it "should parse a standard type list with name before types (no default)" do
90
- YARD::Tags::DefaultTag.should_receive(:new).with("test", "description", ["x", "y", "z"], 'NAME', nil)
91
- parse_types('NAME [x, y, z] description')
21
+ it "should handle a list of types" do
22
+ parse_types('[A, B, C]').should == [nil, ['A', 'B', 'C'], ""]
23
+ end
24
+
25
+ it "should return the text before and after the type list" do
26
+ parse_types(' b <String> description').should == ['b', ['String'], 'description']
27
+ parse_types('b c <String> description (test)').should == [nil, nil, 'b c <String> description (test)']
28
+ end
29
+
30
+ it "should handle a complex list of types" do
31
+ v = parse_types(' [Test, Array<String, Hash, C>, String]')
32
+ v.should include(["Test", "Array<String, Hash, C>", "String"])
33
+ end
34
+
35
+ it "should handle any of the following start/end delimiting chars: (), <>, {}, []" do
36
+ a = parse_types('[a,b,c]')
37
+ b = parse_types('<a,b,c>')
38
+ c = parse_types('(a,b,c)')
39
+ d = parse_types('{a,b,c}')
40
+ a.should == b
41
+ b.should == c
42
+ c.should == d
43
+ a.should include(['a','b','c'])
44
+ end
45
+
46
+ it "should return the text before the type list as the last element" do
47
+ parse_types('b[x, y, z]').should == ['b', ['x', 'y', 'z'], '']
48
+ parse_types(' ! <x>').should == ["!", ['x'], '']
49
+ end
50
+
51
+ it "should return text unparsed if there is no type list" do
52
+ parse_types('').should == [nil, nil, '']
53
+ parse_types('[]').should == [nil, nil, '[]']
54
+ end
55
+
56
+ it "should allow A => B syntax" do
57
+ v = parse_types(' [Test, Array<String, Hash{A => {B => C}}, C>, String]')
58
+ v.should include(["Test", "Array<String, Hash{A => {B => C}}, C>", "String"])
59
+ end
92
60
  end
93
61
 
94
- it "should parse a standard type list with name after types (no default)" do
95
- YARD::Tags::DefaultTag.should_receive(:new).with("test", "description", ["x", "y", "z"], 'NAME', nil)
96
- parse_types(' [x, y, z] NAME description')
97
- end
98
-
99
- it "should parse a tag definition with name, typelist and default" do
100
- YARD::Tags::DefaultTag.should_receive(:new).with("test", "description", ["x", "y", "z"], 'NAME', ['default', 'values'])
101
- parse_types(' [x, y, z] NAME (default, values) description')
62
+ describe '#parse_tag_with_types' do
63
+ def parse_types(text)
64
+ @f.send(:parse_tag_with_types, 'test', text)
65
+ end
66
+
67
+ it "should parse given types and description" do
68
+ YARD::Tags::Tag.should_receive(:new).with("test", "description", ["x", "y", "z"])
69
+ parse_types(' [x, y, z] description')
70
+ end
71
+
72
+ it "should parse given types only" do
73
+ YARD::Tags::Tag.should_receive(:new).with("test", "", ["x", "y", "z"])
74
+ parse_types(' [x, y, z] ')
75
+ end
76
+
77
+ it "should allow type list to be omitted" do
78
+ YARD::Tags::Tag.should_receive(:new).with('test', 'description', nil)
79
+ parse_types(' description ')
80
+ end
81
+
82
+ it "should raise an error if a name is specified before type list" do
83
+ lambda { parse_types('b<String> desc') }.should raise_error(YARD::Tags::TagFormatError, 'cannot specify a name before type list for \'@test\'')
84
+ end
102
85
  end
103
86
 
104
- it "should parse a tag definition with name, typelist and default when name is before type list" do
105
- YARD::Tags::DefaultTag.should_receive(:new).with("test", "description", ["x", "y", "z"], 'NAME', ['default', 'values'])
106
- parse_types(' NAME [x, y, z] (default, values) description')
107
- end
108
-
109
- it "should allow typelist to be omitted" do
110
- YARD::Tags::DefaultTag.should_receive(:new).with("test", "description", nil, 'NAME', ['default', 'values'])
111
- parse_types(' NAME (default, values) description')
112
- end
113
- end
87
+ describe '#parse_tag_with_types_name_and_default' do
88
+ def parse_types(text)
89
+ @f.send(:parse_tag_with_types_name_and_default, 'test', text)
90
+ end
91
+
92
+ it "should parse a standard type list with name before types (no default)" do
93
+ YARD::Tags::DefaultTag.should_receive(:new).with("test", "description", ["x", "y", "z"], 'NAME', nil)
94
+ parse_types('NAME [x, y, z] description')
95
+ end
114
96
 
115
- describe YARD::Tags::DefaultFactory, '#parse_tag_with_options' do
116
- before { @f = YARD::Tags::DefaultFactory.new }
117
-
118
- def parse_options(text)
119
- @f.parse_tag_with_options('option', text)
120
- end
97
+ it "should parse a standard type list with name after types (no default)" do
98
+ YARD::Tags::DefaultTag.should_receive(:new).with("test", "description", ["x", "y", "z"], 'NAME', nil)
99
+ parse_types(' [x, y, z] NAME description')
100
+ end
101
+
102
+ it "should parse a tag definition with name, typelist and default" do
103
+ YARD::Tags::DefaultTag.should_receive(:new).with("test", "description", ["x", "y", "z"], 'NAME', ['default', 'values'])
104
+ parse_types(' [x, y, z] NAME (default, values) description')
105
+ end
106
+
107
+ it "should parse a tag definition with name, typelist and default when name is before type list" do
108
+ YARD::Tags::DefaultTag.should_receive(:new).with("test", "description", ["x", "y", "z"], 'NAME', ['default', 'values'])
109
+ parse_types(' NAME [x, y, z] (default, values) description')
110
+ end
121
111
 
122
- it "should have a name before tag info" do
123
- t = parse_options("xyz key [Types] (default) description")
124
- t.tag_name.should == 'option'
125
- t.name.should == 'xyz'
112
+ it "should allow typelist to be omitted" do
113
+ YARD::Tags::DefaultTag.should_receive(:new).with("test", "description", nil, 'NAME', ['default', 'values'])
114
+ parse_types(' NAME (default, values) description')
115
+ end
126
116
  end
127
-
128
- it "should parse the rest of the tag like DefaultTag" do
129
- t = parse_options("xyz key [Types] (default) description")
130
- t.pair.should be_instance_of(Tags::DefaultTag)
131
- t.pair.types.should == ["Types"]
132
- t.pair.name.should == "key"
133
- t.pair.defaults.should == ["default"]
134
- t.pair.text.should == "description"
117
+
118
+ describe '#parse_tag_with_options' do
119
+ def parse_options(text)
120
+ @f.parse_tag_with_options('option', text)
121
+ end
122
+
123
+ it "should have a name before tag info" do
124
+ t = parse_options("xyz key [Types] (default) description")
125
+ t.tag_name.should == 'option'
126
+ t.name.should == 'xyz'
127
+ end
128
+
129
+ it "should parse the rest of the tag like DefaultTag" do
130
+ t = parse_options("xyz key [Types] (default) description")
131
+ t.pair.should be_instance_of(Tags::DefaultTag)
132
+ t.pair.types.should == ["Types"]
133
+ t.pair.name.should == "key"
134
+ t.pair.defaults.should == ["default"]
135
+ t.pair.text.should == "description"
136
+ end
135
137
  end
136
138
  end