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.

Files changed (121) hide show
  1. data/ChangeLog +585 -1
  2. data/README.md +10 -2
  3. data/benchmarks/yri_cache.rb +19 -0
  4. data/bin/yri +1 -26
  5. data/docs/WhatsNew.md +99 -0
  6. data/lib/rubygems_plugin.rb +2 -0
  7. data/lib/yard.rb +2 -2
  8. data/lib/yard/autoload.rb +9 -4
  9. data/lib/yard/cli/base.rb +26 -0
  10. data/lib/yard/cli/yard_graph.rb +2 -9
  11. data/lib/yard/cli/yardoc.rb +93 -33
  12. data/lib/yard/cli/yri.rb +128 -0
  13. data/lib/yard/code_objects/base.rb +16 -5
  14. data/lib/yard/code_objects/class_object.rb +11 -4
  15. data/lib/yard/code_objects/method_object.rb +11 -1
  16. data/lib/yard/code_objects/proxy.rb +5 -2
  17. data/lib/yard/code_objects/root_object.rb +1 -0
  18. data/lib/yard/core_ext/file.rb +1 -1
  19. data/lib/yard/core_ext/hash.rb +15 -0
  20. data/lib/yard/core_ext/module.rb +2 -2
  21. data/lib/yard/core_ext/string.rb +66 -0
  22. data/lib/yard/core_ext/symbol_hash.rb +1 -1
  23. data/lib/yard/docstring.rb +5 -5
  24. data/lib/yard/handlers/base.rb +10 -4
  25. data/lib/yard/handlers/processor.rb +3 -4
  26. data/lib/yard/handlers/ruby/attribute_handler.rb +3 -2
  27. data/lib/yard/handlers/ruby/legacy/attribute_handler.rb +2 -2
  28. data/lib/yard/handlers/ruby/legacy/method_handler.rb +7 -1
  29. data/lib/yard/handlers/ruby/method_handler.rb +7 -1
  30. data/lib/yard/logging.rb +11 -1
  31. data/lib/yard/parser/c_parser.rb +407 -0
  32. data/lib/yard/parser/ruby/ast_node.rb +2 -2
  33. data/lib/yard/parser/ruby/legacy/ruby_lex.rb +3 -4
  34. data/lib/yard/parser/source_parser.rb +18 -7
  35. data/lib/yard/rake/yardoc_task.rb +1 -1
  36. data/lib/yard/registry.rb +83 -29
  37. data/lib/yard/registry_store.rb +213 -0
  38. data/lib/yard/serializers/base.rb +1 -1
  39. data/lib/yard/serializers/yardoc_serializer.rb +113 -0
  40. data/lib/yard/tags/library.rb +4 -0
  41. data/lib/yard/tags/overload_tag.rb +16 -5
  42. data/lib/yard/tags/tag.rb +1 -2
  43. data/lib/yard/templates/engine.rb +3 -3
  44. data/lib/yard/templates/helpers/html_helper.rb +50 -16
  45. data/lib/yard/templates/helpers/html_syntax_highlight_helper.rb +1 -3
  46. data/lib/yard/templates/helpers/html_syntax_highlight_helper18.rb +1 -3
  47. data/lib/yard/templates/helpers/method_helper.rb +11 -4
  48. data/lib/yard/templates/helpers/text_helper.rb +24 -2
  49. data/lib/yard/verifier.rb +3 -3
  50. data/spec/cli/yardoc_spec.rb +33 -6
  51. data/spec/cli/yri_spec.rb +30 -0
  52. data/spec/code_objects/base_spec.rb +7 -0
  53. data/spec/code_objects/class_object_spec.rb +6 -1
  54. data/spec/code_objects/method_object_spec.rb +25 -0
  55. data/spec/core_ext/hash_spec.rb +10 -0
  56. data/spec/core_ext/module_spec.rb +1 -1
  57. data/spec/core_ext/string_spec.rb +50 -12
  58. data/spec/handlers/attribute_handler_spec.rb +4 -0
  59. data/spec/handlers/examples/method_handler_001.rb.txt +9 -0
  60. data/spec/handlers/method_handler_spec.rb +22 -4
  61. data/spec/parser/c_parser_spec.rb +22 -0
  62. data/spec/parser/examples/array.c.txt +3887 -0
  63. data/spec/parser/source_parser_spec.rb +29 -7
  64. data/spec/registry_spec.rb +93 -72
  65. data/spec/registry_store_spec.rb +184 -0
  66. data/spec/serializers/file_system_serializer_spec.rb +96 -75
  67. data/spec/spec_helper.rb +2 -2
  68. data/spec/tags/overload_tag_spec.rb +18 -0
  69. data/spec/templates/examples/class001.html +32 -30
  70. data/spec/templates/examples/method001.html +4 -1
  71. data/spec/templates/examples/method002.html +7 -2
  72. data/spec/templates/examples/method002.txt +1 -1
  73. data/spec/templates/examples/method003.html +30 -8
  74. data/spec/templates/examples/method003.txt +4 -4
  75. data/spec/templates/examples/method004.html +44 -0
  76. data/spec/templates/examples/method004.txt +10 -0
  77. data/spec/templates/examples/method005.html +99 -0
  78. data/spec/templates/examples/method005.txt +33 -0
  79. data/spec/templates/examples/module001.dot +1 -1
  80. data/spec/templates/examples/module001.html +391 -37
  81. data/spec/templates/examples/module001.txt +1 -1
  82. data/spec/templates/helpers/base_helper_spec.rb +2 -2
  83. data/spec/templates/helpers/html_helper_spec.rb +83 -0
  84. data/spec/templates/helpers/method_helper_spec.rb +47 -0
  85. data/spec/templates/helpers/shared_signature_examples.rb +102 -0
  86. data/spec/templates/helpers/text_helper_spec.rb +31 -0
  87. data/spec/templates/method_spec.rb +43 -18
  88. data/spec/templates/module_spec.rb +22 -1
  89. data/spec/templates/spec_helper.rb +10 -1
  90. data/spec/yard_spec.rb +4 -3
  91. data/templates/default/class/html/constructor_details.erb +1 -1
  92. data/templates/default/docstring/html/returns_void.erb +1 -0
  93. data/templates/default/docstring/setup.rb +9 -4
  94. data/templates/default/docstring/text/returns_void.erb +1 -0
  95. data/templates/default/fulldoc/html/css/style.css +4 -2
  96. data/templates/default/fulldoc/html/full_list.erb +2 -2
  97. data/templates/default/fulldoc/html/js/app.js +1 -1
  98. data/templates/default/fulldoc/html/setup.rb +14 -6
  99. data/templates/default/layout/dot/setup.rb +1 -1
  100. data/templates/default/layout/html/breadcrumb.erb +2 -2
  101. data/templates/default/layout/html/index.erb +2 -2
  102. data/templates/default/layout/html/setup.rb +5 -5
  103. data/templates/default/method/html/header.erb +6 -4
  104. data/templates/default/method_details/html/method_signature.erb +2 -1
  105. data/templates/default/method_details/html/source.erb +1 -1
  106. data/templates/default/method_details/setup.rb +2 -1
  107. data/templates/default/method_details/text/setup.rb +1 -1
  108. data/templates/default/module/html/attribute_details.erb +4 -4
  109. data/templates/default/module/html/attribute_summary.erb +3 -3
  110. data/templates/default/module/html/box_info.erb +2 -2
  111. data/templates/default/module/html/defines.erb +1 -1
  112. data/templates/default/module/html/inherited_constants.erb +1 -1
  113. data/templates/default/module/html/inherited_methods.erb +1 -1
  114. data/templates/default/module/html/item_summary.erb +13 -4
  115. data/templates/default/module/html/method_details_list.erb +5 -4
  116. data/templates/default/module/html/method_summary.erb +5 -4
  117. data/templates/default/module/html/methodmissing.erb +1 -1
  118. data/templates/default/module/setup.rb +14 -5
  119. data/templates/default/tags/html/overload.erb +3 -2
  120. data/templates/default/tags/setup.rb +4 -0
  121. metadata +23 -2
@@ -72,23 +72,49 @@ describe YARD::Parser::SourceParser do
72
72
  end
73
73
 
74
74
  it "should parse a set of file globs" do
75
- Dir.should_receive(:[]).with('lib/**/*.rb')
75
+ Dir.should_receive(:[]).with('lib/**/*.rb').and_return([])
76
76
  YARD.parse('lib/**/*.rb')
77
77
  end
78
78
 
79
79
  it "should parse a set of absolute paths" do
80
- Dir.should_not_receive(:[])
80
+ Dir.should_not_receive(:[]).and_return([])
81
+ File.should_receive(:file?).with('/path/to/file').and_return(true)
81
82
  IO.should_receive(:read).with('/path/to/file').and_return("")
82
83
  YARD.parse('/path/to/file')
83
84
  end
84
85
 
85
86
  it "should parse files with '*' in them as globs and others as absolute paths" do
86
87
  Dir.should_receive(:[]).with('*.rb').and_return(['a.rb', 'b.rb'])
88
+ File.should_receive(:file?).with('/path/to/file').and_return(true)
89
+ File.should_receive(:file?).with('a.rb').and_return(true)
90
+ File.should_receive(:file?).with('b.rb').and_return(true)
87
91
  IO.should_receive(:read).with('/path/to/file').and_return("")
88
92
  IO.should_receive(:read).with('a.rb').and_return("")
89
93
  IO.should_receive(:read).with('b.rb').and_return("")
90
94
  YARD.parse ['/path/to/file', '*.rb']
91
95
  end
96
+
97
+ it "should convert directories into globs" do
98
+ Dir.should_receive(:[]).with('foo/**/*.{rb,c}').and_return(['foo/a.rb', 'foo/bar/b.rb'])
99
+ File.should_receive(:directory?).with('foo').and_return(true)
100
+ File.should_receive(:file?).with('foo/a.rb').and_return(true)
101
+ File.should_receive(:file?).with('foo/bar/b.rb').and_return(true)
102
+ IO.should_receive(:read).with('foo/a.rb').and_return("")
103
+ IO.should_receive(:read).with('foo/bar/b.rb').and_return("")
104
+ YARD.parse ['foo']
105
+ end
106
+
107
+ it "should use Registry.checksums cache if file is cached" do
108
+ data = 'DATA'
109
+ hash = Registry.checksum_for(data)
110
+ cmock = mock(:cmock)
111
+ cmock.should_receive(:[]).with('foo/bar').and_return(hash)
112
+ log.should_receive(:info)
113
+ Registry.should_receive(:checksums).and_return(cmock)
114
+ File.should_receive(:file?).with('foo/bar').and_return(true)
115
+ IO.should_receive(:read).with('foo/bar').and_return(data)
116
+ YARD.parse('foo/bar')
117
+ end
92
118
  end
93
119
 
94
120
  describe '#parse_in_order' do
@@ -109,6 +135,7 @@ describe YARD::Parser::SourceParser do
109
135
 
110
136
  it "should attempt to order files by length (process toplevel files first)" do
111
137
  %w(a a/b a/b/c).each do |file|
138
+ File.should_receive(:file?).with(file).and_return(true)
112
139
  IO.should_receive(:read).with(file).ordered.and_return('')
113
140
  end
114
141
  YARD.parse %w(a/b/c a/b a)
@@ -116,11 +143,6 @@ describe YARD::Parser::SourceParser do
116
143
  end
117
144
 
118
145
  describe '#parse_statements' do
119
- it "should display a warning for C/C++ files" do
120
- log.should_receive(:warn).with(/no support/)
121
- YARD::Parser::SourceParser.parse_string("int main() { }", :c)
122
- end
123
-
124
146
  it "should display a warning for invalid parser type" do
125
147
  log.should_receive(:warn).with(/unrecognized file/)
126
148
  YARD::Parser::SourceParser.parse_string("int main() { }", :d)
@@ -4,94 +4,115 @@ include CodeObjects
4
4
  describe YARD::Registry do
5
5
  before { Registry.clear }
6
6
 
7
- it "should have an empty path for root" do
8
- Registry.root.path.should == ""
7
+ describe '#root' do
8
+ it "should have an empty path for root" do
9
+ Registry.root.path.should == ""
10
+ end
9
11
  end
10
12
 
11
- it "should #resolve any existing namespace" do
12
- o1 = ModuleObject.new(:root, :A)
13
- o2 = ModuleObject.new(o1, :B)
14
- o3 = ModuleObject.new(o2, :C)
15
- Registry.resolve(o1, "B::C").should == o3
16
- Registry.resolve(:root, "A::B::C")
17
- end
13
+ describe '#resolve' do
14
+ it "should resolve any existing namespace" do
15
+ o1 = ModuleObject.new(:root, :A)
16
+ o2 = ModuleObject.new(o1, :B)
17
+ o3 = ModuleObject.new(o2, :C)
18
+ Registry.resolve(o1, "B::C").should == o3
19
+ Registry.resolve(:root, "A::B::C")
20
+ end
18
21
 
19
- it "should resolve an object in the root namespace when prefixed with ::" do
20
- o1 = ModuleObject.new(:root, :A)
21
- o2 = ModuleObject.new(o1, :B)
22
- o3 = ModuleObject.new(o2, :C)
23
- Registry.resolve(o3, "::A").should == o1
22
+ it "should resolve an object in the root namespace when prefixed with ::" do
23
+ o1 = ModuleObject.new(:root, :A)
24
+ o2 = ModuleObject.new(o1, :B)
25
+ o3 = ModuleObject.new(o2, :C)
26
+ Registry.resolve(o3, "::A").should == o1
24
27
 
25
- Registry.resolve(o3, "::String", false, true).should == P(:String)
26
- end
28
+ Registry.resolve(o3, "::String", false, true).should == P(:String)
29
+ end
27
30
 
28
- it "should resolve instance methods with # prefix" do
29
- o1 = ModuleObject.new(:root, :A)
30
- o2 = ModuleObject.new(o1, :B)
31
- o3 = ModuleObject.new(o2, :C)
32
- o4 = MethodObject.new(o3, :methname)
33
- Registry.resolve(o1, "B::C#methname").should == o4
34
- Registry.resolve(o2, "C#methname").should == o4
35
- Registry.resolve(o3, "#methname").should == o4
36
- end
31
+ it "should resolve instance methods with # prefix" do
32
+ o1 = ModuleObject.new(:root, :A)
33
+ o2 = ModuleObject.new(o1, :B)
34
+ o3 = ModuleObject.new(o2, :C)
35
+ o4 = MethodObject.new(o3, :methname)
36
+ Registry.resolve(o1, "B::C#methname").should == o4
37
+ Registry.resolve(o2, "C#methname").should == o4
38
+ Registry.resolve(o3, "#methname").should == o4
39
+ end
37
40
 
38
- it "should resolve instance methods in the root without # prefix" do
39
- o = MethodObject.new(:root, :methname)
40
- Registry.resolve(:root, 'methname').should == o
41
- end
41
+ it "should resolve instance methods in the root without # prefix" do
42
+ o = MethodObject.new(:root, :methname)
43
+ Registry.resolve(:root, 'methname').should == o
44
+ end
42
45
 
43
- it "should resolve superclass methods when inheritance = true" do
44
- superyard = ClassObject.new(:root, :SuperYard)
45
- yard = ClassObject.new(:root, :YARD)
46
- yard.superclass = superyard
47
- imeth = MethodObject.new(superyard, :hello)
48
- cmeth = MethodObject.new(superyard, :class_hello, :class)
46
+ it "should resolve superclass methods when inheritance = true" do
47
+ superyard = ClassObject.new(:root, :SuperYard)
48
+ yard = ClassObject.new(:root, :YARD)
49
+ yard.superclass = superyard
50
+ imeth = MethodObject.new(superyard, :hello)
51
+ cmeth = MethodObject.new(superyard, :class_hello, :class)
49
52
 
50
- Registry.resolve(yard, "#hello", false).should be_nil
51
- Registry.resolve(yard, "#hello", true).should == imeth
52
- Registry.resolve(yard, "class_hello", false).should be_nil
53
- Registry.resolve(yard, "class_hello", true).should == cmeth
54
- end
53
+ Registry.resolve(yard, "#hello", false).should be_nil
54
+ Registry.resolve(yard, "#hello", true).should == imeth
55
+ Registry.resolve(yard, "class_hello", false).should be_nil
56
+ Registry.resolve(yard, "class_hello", true).should == cmeth
57
+ end
55
58
 
56
- it "should resolve mixin methods when inheritance = true" do
57
- yard = ClassObject.new(:root, :YARD)
58
- mixin = ModuleObject.new(:root, :Mixin)
59
- yard.mixins(:instance) << mixin
60
- imeth = MethodObject.new(mixin, :hello)
61
- cmeth = MethodObject.new(mixin, :class_hello, :class)
59
+ it "should resolve mixin methods when inheritance = true" do
60
+ yard = ClassObject.new(:root, :YARD)
61
+ mixin = ModuleObject.new(:root, :Mixin)
62
+ yard.mixins(:instance) << mixin
63
+ imeth = MethodObject.new(mixin, :hello)
64
+ cmeth = MethodObject.new(mixin, :class_hello, :class)
62
65
 
63
- Registry.resolve(yard, "#hello", false).should be_nil
64
- Registry.resolve(yard, "#hello", true).should == imeth
65
- Registry.resolve(yard, "class_hello", false).should be_nil
66
- Registry.resolve(yard, "class_hello", true).should == cmeth
66
+ Registry.resolve(yard, "#hello", false).should be_nil
67
+ Registry.resolve(yard, "#hello", true).should == imeth
68
+ Registry.resolve(yard, "class_hello", false).should be_nil
69
+ Registry.resolve(yard, "class_hello", true).should == cmeth
70
+ end
67
71
  end
68
72
 
69
- it "should allow symbols as object type in #all" do
70
- ModuleObject.new(:root, :A)
71
- o1 = ClassObject.new(:root, :B)
72
- o2 = MethodObject.new(:root, :testing)
73
- r = Registry.all(:method, :class)
74
- r.should include(o1, o2)
75
- end
73
+ describe '#all' do
74
+ it "should return objects of types specified by arguments" do
75
+ ModuleObject.new(:root, :A)
76
+ o1 = ClassObject.new(:root, :B)
77
+ o2 = MethodObject.new(:root, :testing)
78
+ r = Registry.all(:method, :class)
79
+ r.should include(o1, o2)
80
+ end
76
81
 
77
- it "should allow code object classes in #all" do
78
- o1 = ModuleObject.new(:root, :A)
79
- o2 = ClassObject.new(:root, :B)
80
- MethodObject.new(:root, :testing)
81
- r = Registry.all(CodeObjects::NamespaceObject)
82
- r.should include(o1, o2)
82
+ it "should return code objects" do
83
+ o1 = ModuleObject.new(:root, :A)
84
+ o2 = ClassObject.new(:root, :B)
85
+ MethodObject.new(:root, :testing)
86
+ r = Registry.all(CodeObjects::NamespaceObject)
87
+ r.should include(o1, o2)
88
+ end
89
+
90
+ it "should allow #all to omit list" do
91
+ o1 = ModuleObject.new(:root, :A)
92
+ o2 = ClassObject.new(:root, :B)
93
+ r = Registry.all
94
+ r.should include(o1, o2)
95
+ end
83
96
  end
84
97
 
85
- it "should allow #all to omit list" do
86
- o1 = ModuleObject.new(:root, :A)
87
- o2 = ClassObject.new(:root, :B)
88
- r = Registry.all
89
- r.should include(o1, o2)
98
+ describe '#paths' do
99
+ it "should return all object paths" do
100
+ o1 = ModuleObject.new(:root, :A)
101
+ o2 = ClassObject.new(:root, :B)
102
+ Registry.paths.should include('A', 'B')
103
+ end
90
104
  end
91
105
 
92
- it "should respond to #paths" do
93
- o1 = ModuleObject.new(:root, :A)
94
- o2 = ClassObject.new(:root, :B)
95
- Registry.paths.should include('A', 'B')
106
+ describe '#load_yardoc' do
107
+ before do
108
+ @store = RegistryStore.new
109
+ RegistryStore.should_receive(:new).and_return(@store)
110
+ end
111
+
112
+ it "should delegate load to RegistryStore" do
113
+ @store.should_receive(:load).with('foo')
114
+ Registry.yardoc_file = 'foo'
115
+ Registry.load_yardoc
116
+ end
96
117
  end
97
118
  end
@@ -0,0 +1,184 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe YARD::RegistryStore do
4
+ before { @store = RegistryStore.new }
5
+
6
+ describe '#load' do
7
+ it "should load old yardoc format if .yardoc is a file" do
8
+ File.should_receive(:directory?).with('foo').and_return(false)
9
+ File.should_receive(:file?).with('foo').and_return(true)
10
+ File.should_receive(:read).with('foo').and_return('FOO')
11
+ Marshal.should_receive(:load).with('FOO')
12
+
13
+ @store.load('foo')
14
+ end
15
+
16
+ it "should load new yardoc format if .yardoc is a directory" do
17
+ File.should_receive(:directory?).with('foo').and_return(true)
18
+ File.should_receive(:file?).with('foo/checksums').and_return(false)
19
+ File.should_receive(:file?).with('foo/proxy_types').and_return(false)
20
+ File.should_receive(:file?).with('foo/objects/root.dat').and_return(false)
21
+
22
+ @store.load('foo').should == true
23
+ end
24
+
25
+ it "should return true if .yardoc is loaded (file)" do
26
+ File.should_receive(:directory?).with('myyardoc').and_return(false)
27
+ File.should_receive(:file?).with('myyardoc').and_return(true)
28
+ File.should_receive(:read).with('myyardoc').and_return(Marshal.dump(''))
29
+ @store.load('myyardoc').should == true
30
+ end
31
+
32
+ it "should return true if .yardoc is loaded (directory)" do
33
+ File.should_receive(:directory?).with('foo').and_return(true)
34
+ File.should_receive(:file?).with('foo/checksums').and_return(false)
35
+ File.should_receive(:file?).with('foo/proxy_types').and_return(false)
36
+ File.should_receive(:file?).with('foo/objects/root.dat').and_return(false)
37
+ @store.load('foo').should == true
38
+ end
39
+
40
+ it "should return false if .yardoc does not exist" do
41
+ @store.load('NONEXIST').should == false
42
+ end
43
+
44
+ it "should return false if there is no file to load" do
45
+ @store.load(nil).should == false
46
+ end
47
+
48
+ it "should load checksums if they exist" do
49
+ File.should_receive(:directory?).with('foo').and_return(true)
50
+ File.should_receive(:file?).with('foo/checksums').and_return(true)
51
+ File.should_receive(:file?).with('foo/proxy_types').and_return(false)
52
+ File.should_receive(:file?).with('foo/objects/root.dat').and_return(false)
53
+ File.should_receive(:readlines).with('foo/checksums').and_return([
54
+ 'file1 CHECKSUM1', ' file2 CHECKSUM2 '
55
+ ])
56
+ @store.load('foo').should == true
57
+ @store.checksums.should == {'file1' => 'CHECKSUM1', 'file2' => 'CHECKSUM2'}
58
+ end
59
+
60
+ it "should load proxy_types if they exist" do
61
+ File.should_receive(:directory?).with('foo').and_return(true)
62
+ File.should_receive(:file?).with('foo/checksums').and_return(false)
63
+ File.should_receive(:file?).with('foo/proxy_types').and_return(true)
64
+ File.should_receive(:file?).with('foo/objects/root.dat').and_return(false)
65
+ File.should_receive(:read).with('foo/proxy_types').and_return(Marshal.dump({'a' => 'b'}))
66
+ @store.load('foo').should == true
67
+ @store.proxy_types.should == {'a' => 'b'}
68
+ end
69
+
70
+ it "should load root object if it exists" do
71
+ File.should_receive(:directory?).with('foo').and_return(true)
72
+ File.should_receive(:file?).with('foo/checksums').and_return(false)
73
+ File.should_receive(:file?).with('foo/proxy_types').and_return(false)
74
+ File.should_receive(:file?).with('foo/objects/root.dat').and_return(true)
75
+ File.should_receive(:read).with('foo/objects/root.dat').and_return(Marshal.dump('foo'))
76
+ @store.load('foo').should == true
77
+ @store.root.should == 'foo'
78
+ end
79
+ end
80
+
81
+ describe '#put' do
82
+ it "should assign values" do
83
+ @store.put(:YARD, true)
84
+ @store.get(:YARD).should == true
85
+ end
86
+
87
+ it "should treat '' as root" do
88
+ @store.put('', 'value')
89
+ @store.get(:root).should == 'value'
90
+ end
91
+ end
92
+
93
+ describe '#get' do
94
+ it "should hit cache if object exists" do
95
+ @store.put(:YARD, true)
96
+ @store.get(:YARD).should == true
97
+ end
98
+
99
+ it "should hit backstore on cache miss and cache is not fully loaded" do
100
+ serializer = mock(:serializer)
101
+ serializer.should_receive(:deserialize).once.with(:YARD).and_return('foo')
102
+ @store.load('foo')
103
+ @store.instance_variable_set("@loaded_objects", 0)
104
+ @store.instance_variable_set("@available_objects", 100)
105
+ @store.instance_variable_set("@serializer", serializer)
106
+ @store.get(:YARD).should == 'foo'
107
+ @store.get(:YARD).should == 'foo'
108
+ @store.instance_variable_get("@loaded_objects").should == 1
109
+ end
110
+ end
111
+
112
+ [:keys, :values].each do |item|
113
+ describe "##{item}" do
114
+ it "should load entire database if reload=true" do
115
+ File.should_receive(:directory?).with('foo').and_return(true)
116
+ @store.load('foo')
117
+ @store.should_receive(:load_all)
118
+ @store.send(item)
119
+ end
120
+
121
+ it "should not load entire database if reload=false" do
122
+ File.should_receive(:directory?).with('foo').and_return(true)
123
+ @store.load('foo')
124
+ @store.should_not_receive(:load_all)
125
+ @store.send(item, false)
126
+ end
127
+ end
128
+ end
129
+
130
+ describe '#load_all' do
131
+ it "should load the entire database" do
132
+ foomock = mock(:Foo)
133
+ barmock = mock(:Bar)
134
+ foomock.should_receive(:path).and_return('Foo')
135
+ barmock.should_receive(:path).and_return('Bar')
136
+ File.should_receive(:directory?).with('foo').and_return(true)
137
+ File.should_receive(:file?).with('foo/proxy_types').and_return(false)
138
+ File.should_receive(:file?).with('foo/checksums').and_return(false)
139
+ File.should_receive(:file?).with('foo/objects/root.dat').and_return(false)
140
+ @store.should_receive(:all_disk_objects).at_least(1).times.and_return(['foo/objects/foo', 'foo/objects/bar'])
141
+ @store.load('foo')
142
+ serializer = @store.instance_variable_get("@serializer")
143
+ serializer.should_receive(:deserialize).with('foo/objects/foo', true).and_return(foomock)
144
+ serializer.should_receive(:deserialize).with('foo/objects/bar', true).and_return(barmock)
145
+ @store.send(:load_all)
146
+ @store.instance_variable_get("@available_objects").should == 2
147
+ @store.instance_variable_get("@loaded_objects").should == 2
148
+ @store[:Foo].should == foomock
149
+ @store[:Bar].should == barmock
150
+ end
151
+ end
152
+
153
+ describe '#destroy' do
154
+ it "should destroy file ending in .yardoc when force=false" do
155
+ File.should_receive(:file?).with('foo.yardoc').and_return(true)
156
+ File.should_receive(:unlink).with('foo.yardoc')
157
+ @store.instance_variable_set("@file", 'foo.yardoc')
158
+ @store.destroy.should == true
159
+ end
160
+
161
+ it "should destroy dir ending in .yardoc when force=false" do
162
+ File.should_receive(:directory?).with('foo.yardoc').and_return(true)
163
+ FileUtils.should_receive(:rm_rf).with('foo.yardoc')
164
+ @store.instance_variable_set("@file", 'foo.yardoc')
165
+ @store.destroy.should == true
166
+ end
167
+
168
+ it "should not destroy file/dir not ending in .yardoc when force=false" do
169
+ File.should_not_receive(:file?).with('foo')
170
+ File.should_not_receive(:directory?).with('foo')
171
+ File.should_not_receive(:unlink).with('foo')
172
+ FileUtils.should_not_receive(:rm_rf).with('foo')
173
+ @store.instance_variable_set("@file", 'foo')
174
+ @store.destroy.should == false
175
+ end
176
+
177
+ it "should destroy any file/dir when force=true" do
178
+ File.should_receive(:file?).with('foo').and_return(true)
179
+ File.should_receive(:unlink).with('foo')
180
+ @store.instance_variable_set("@file", 'foo')
181
+ @store.destroy(true).should == true
182
+ end
183
+ end
184
+ end
@@ -8,90 +8,111 @@ describe YARD::Serializers::FileSystemSerializer do
8
8
  File.stub!(:open)
9
9
  end
10
10
 
11
- it "should default the base path to the 'doc/'" do
12
- obj = Serializers::FileSystemSerializer.new
13
- obj.basepath.should == 'doc'
14
- end
15
-
16
- it "should default the file extension to .html" do
17
- obj = Serializers::FileSystemSerializer.new
18
- obj.extension.should == "html"
19
- end
20
-
21
- it "should allow no extension to be used" do
22
- obj = Serializers::FileSystemSerializer.new :extension => nil
23
- yard = CodeObjects::ClassObject.new(nil, :FooBar)
24
- obj.serialized_path(yard).should == 'FooBar'
11
+ describe '#basepath' do
12
+ it "should default the base path to the 'doc/'" do
13
+ obj = Serializers::FileSystemSerializer.new
14
+ obj.basepath.should == 'doc'
15
+ end
25
16
  end
26
-
27
- it "should serialize to top-level-namespace for root" do
28
- obj = Serializers::FileSystemSerializer.new :extension => nil
29
- obj.serialized_path(Registry.root).should == "top-level-namespace"
17
+
18
+ describe '#extension' do
19
+ it "should default the file extension to .html" do
20
+ obj = Serializers::FileSystemSerializer.new
21
+ obj.extension.should == "html"
22
+ end
30
23
  end
31
24
 
32
- it "should serialize to the correct path" do
33
- yard = CodeObjects::ClassObject.new(nil, :FooBar)
34
- meth = CodeObjects::MethodObject.new(yard, :baz, :class)
35
- meth2 = CodeObjects::MethodObject.new(yard, :baz)
36
-
37
- { 'foo/FooBar/baz_c.txt' => meth,
38
- 'foo/FooBar/baz_i.txt' => meth2,
39
- 'foo/FooBar.txt' => yard }.each do |path, obj|
40
- io = StringIO.new
41
- File.should_receive(:open).with(path, 'wb').and_yield(io)
42
- io.should_receive(:write).with("data")
43
-
25
+ describe '#serialized_path' do
26
+ it "should allow no extension to be used" do
27
+ obj = Serializers::FileSystemSerializer.new :extension => nil
28
+ yard = CodeObjects::ClassObject.new(nil, :FooBar)
29
+ obj.serialized_path(yard).should == 'FooBar'
30
+ end
31
+
32
+ it "should serialize to top-level-namespace for root" do
33
+ obj = Serializers::FileSystemSerializer.new :extension => nil
34
+ obj.serialized_path(Registry.root).should == "top-level-namespace"
35
+ end
36
+
37
+ it "should return serialized_path for a String" do
44
38
  s = Serializers::FileSystemSerializer.new(:basepath => 'foo', :extension => 'txt')
45
- s.serialize(obj, "data")
39
+ s.serialized_path('test.txt').should == 'test.txt'
46
40
  end
47
- end
48
-
49
- it "should return serialized_path for a String" do
50
- s = Serializers::FileSystemSerializer.new(:basepath => 'foo', :extension => 'txt')
51
- s.serialized_path('test.txt').should == 'test.txt'
52
- end
53
-
54
- it "should remove special chars from path" do
55
- m = CodeObjects::MethodObject.new(nil, 'a')
56
- s = Serializers::FileSystemSerializer.new
57
41
 
58
- { :/ => '_2F_i.html',
59
- :gsub! => 'gsub_21_i.html',
60
- :ask? => 'ask_3F_i.html',
61
- :=== => '_3D_3D_3D_i.html',
62
- :+ => '_2B_i.html',
63
- :- => '-_i.html',
64
- :[]= => '_5B_5D_3D_i.html',
65
- :<< => '_3C_3C_i.html',
66
- :>= => '_3E_3D_i.html',
67
- :` => '_60_i.html',
68
- :& => '_26_i.html',
69
- :* => '_2A_i.html',
70
- :| => '_7C_i.html',
71
- :/ => '_2F_i.html',
72
- :=~ => '_3D_7E_i.html'
73
- }.each do |meth, value|
74
- m.stub!(:name).and_return(meth)
75
- s.serialized_path(m).should == value
42
+ it "should remove special chars from path" do
43
+ m = CodeObjects::MethodObject.new(nil, 'a')
44
+ s = Serializers::FileSystemSerializer.new
45
+
46
+ { :/ => '_2F_i.html',
47
+ :gsub! => 'gsub_21_i.html',
48
+ :ask? => 'ask_3F_i.html',
49
+ :=== => '_3D_3D_3D_i.html',
50
+ :+ => '_2B_i.html',
51
+ :- => '-_i.html',
52
+ :[]= => '_5B_5D_3D_i.html',
53
+ :<< => '_3C_3C_i.html',
54
+ :>= => '_3E_3D_i.html',
55
+ :` => '_60_i.html',
56
+ :& => '_26_i.html',
57
+ :* => '_2A_i.html',
58
+ :| => '_7C_i.html',
59
+ :/ => '_2F_i.html',
60
+ :=~ => '_3D_7E_i.html'
61
+ }.each do |meth, value|
62
+ m.stub!(:name).and_return(meth)
63
+ s.serialized_path(m).should == value
64
+ end
65
+ end
66
+
67
+ it "should differentiate instance and class methods from serialized path" do
68
+ s = Serializers::FileSystemSerializer.new
69
+ m1 = CodeObjects::MethodObject.new(nil, 'meth')
70
+ m2 = CodeObjects::MethodObject.new(nil, 'meth', :class)
71
+ s.serialized_path(m1).should_not == s.serialized_path(m2)
72
+ end
73
+
74
+ it "should serialize path from overload tag" do
75
+ YARD.parse_string <<-'eof'
76
+ class Foo
77
+ # @overload bar
78
+ def bar; end
79
+ end
80
+ eof
81
+
82
+ serializer = Serializers::FileSystemSerializer.new
83
+ object = Registry.at('Foo#bar').tag(:overload)
84
+ serializer.serialized_path(object).should == "Foo/bar_i.html"
76
85
  end
77
86
  end
78
87
 
79
- it "should differentiate instance and class methods from serialized path" do
80
- s = Serializers::FileSystemSerializer.new
81
- m1 = CodeObjects::MethodObject.new(nil, 'meth')
82
- m2 = CodeObjects::MethodObject.new(nil, 'meth', :class)
83
- s.serialized_path(m1).should_not == s.serialized_path(m2)
84
- end
85
-
86
- it "should guarantee the directory exists" do
87
- o1 = CodeObjects::ClassObject.new(nil, :Really)
88
- o2 = CodeObjects::ClassObject.new(o1, :Long)
89
- o3 = CodeObjects::ClassObject.new(o2, :PathName)
90
- obj = CodeObjects::MethodObject.new(o3, :foo)
88
+ describe '#serialize' do
89
+ it "should serialize to the correct path" do
90
+ yard = CodeObjects::ClassObject.new(nil, :FooBar)
91
+ meth = CodeObjects::MethodObject.new(yard, :baz, :class)
92
+ meth2 = CodeObjects::MethodObject.new(yard, :baz)
91
93
 
92
- FileUtils.should_receive(:mkdir_p).once.with('doc/Really/Long/PathName')
93
-
94
- s = Serializers::FileSystemSerializer.new
95
- s.serialize(obj, "data")
94
+ { 'foo/FooBar/baz_c.txt' => meth,
95
+ 'foo/FooBar/baz_i.txt' => meth2,
96
+ 'foo/FooBar.txt' => yard }.each do |path, obj|
97
+ io = StringIO.new
98
+ File.should_receive(:open).with(path, 'wb').and_yield(io)
99
+ io.should_receive(:write).with("data")
100
+
101
+ s = Serializers::FileSystemSerializer.new(:basepath => 'foo', :extension => 'txt')
102
+ s.serialize(obj, "data")
103
+ end
104
+ end
105
+
106
+ it "should guarantee the directory exists" do
107
+ o1 = CodeObjects::ClassObject.new(nil, :Really)
108
+ o2 = CodeObjects::ClassObject.new(o1, :Long)
109
+ o3 = CodeObjects::ClassObject.new(o2, :PathName)
110
+ obj = CodeObjects::MethodObject.new(o3, :foo)
111
+
112
+ FileUtils.should_receive(:mkdir_p).once.with('doc/Really/Long/PathName')
113
+
114
+ s = Serializers::FileSystemSerializer.new
115
+ s.serialize(obj, "data")
116
+ end
96
117
  end
97
118
  end