yard 0.6.3 → 0.6.4

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 (46) hide show
  1. data/ChangeLog +119 -0
  2. data/README.md +16 -2
  3. data/Rakefile +29 -10
  4. data/docs/GettingStarted.md +186 -35
  5. data/lib/yard.rb +1 -1
  6. data/lib/yard/autoload.rb +10 -0
  7. data/lib/yard/cli/yri.rb +2 -2
  8. data/lib/yard/code_objects/base.rb +1 -1
  9. data/lib/yard/code_objects/method_object.rb +2 -1
  10. data/lib/yard/code_objects/root_object.rb +2 -2
  11. data/lib/yard/parser/ruby/ast_node.rb +0 -4
  12. data/lib/yard/parser/ruby/ruby_parser.rb +30 -1
  13. data/lib/yard/server/adapter.rb +50 -1
  14. data/lib/yard/server/commands/base.rb +117 -23
  15. data/lib/yard/server/commands/display_file_command.rb +3 -0
  16. data/lib/yard/server/commands/display_object_command.rb +1 -0
  17. data/lib/yard/server/commands/frames_command.rb +1 -0
  18. data/lib/yard/server/commands/library_command.rb +8 -1
  19. data/lib/yard/server/commands/list_command.rb +4 -0
  20. data/lib/yard/server/doc_server_helper.rb +15 -0
  21. data/lib/yard/server/doc_server_serializer.rb +2 -0
  22. data/lib/yard/server/library_version.rb +141 -0
  23. data/lib/yard/server/rack_adapter.rb +35 -2
  24. data/lib/yard/server/router.rb +71 -1
  25. data/lib/yard/server/static_caching.rb +29 -0
  26. data/lib/yard/server/webrick_adapter.rb +4 -0
  27. data/lib/yard/templates/engine.rb +1 -1
  28. data/lib/yard/templates/helpers/markup_helper.rb +22 -7
  29. data/spec/cli/diff_spec.rb +2 -2
  30. data/spec/cli/stats_spec.rb +1 -1
  31. data/spec/cli/yardoc_spec.rb +1 -1
  32. data/spec/cli/yri_spec.rb +21 -0
  33. data/spec/handlers/class_handler_spec.rb +1 -0
  34. data/spec/handlers/examples/class_handler_001.rb.txt +1 -0
  35. data/spec/parser/ruby/legacy/statement_list_spec.rb +6 -0
  36. data/spec/parser/ruby/ruby_parser_spec.rb +29 -0
  37. data/spec/server/rack_adapter_spec.rb +18 -0
  38. data/spec/spec_helper.rb +6 -2
  39. data/spec/templates/engine_spec.rb +4 -1
  40. data/spec/templates/helpers/html_helper_spec.rb +11 -0
  41. data/spec/templates/helpers/markup_helper_spec.rb +9 -5
  42. data/spec/templates/module_spec.rb +1 -1
  43. data/spec/templates/spec_helper.rb +3 -3
  44. data/templates/default/fulldoc/html/css/style.css +1 -1
  45. data/templates/default/fulldoc/html/js/app.js +3 -2
  46. metadata +7 -15
@@ -1,6 +1,35 @@
1
1
  module YARD
2
2
  module Server
3
+ # Implements static caching for requests.
4
+ #
5
+ # @see Router Router documentation for "Caching"
3
6
  module StaticCaching
7
+ # Called by a router to return the cached object. By default, this
8
+ # method performs disk-based caching. To perform other forms of caching,
9
+ # implement your own +#check_static_cache+ method and mix the module into
10
+ # the Router class.
11
+ #
12
+ # Note that caching does not occur here. This method simply checks for
13
+ # the existence of cached data. To actually cache a response, see
14
+ # {Commands::Base#cache}.
15
+ #
16
+ # @example Implementing In-Memory Cache Checking
17
+ # module MemoryCaching
18
+ # def check_static_cache
19
+ # # $memory_cache is filled by {Commands::Base#cache}
20
+ # cached_data = $memory_cache[request.path]
21
+ # if cached_data
22
+ # [200, {'Content-Type' => 'text/html'}, [cached_data]]
23
+ # else
24
+ # nil
25
+ # end
26
+ # end
27
+ # end
28
+ #
29
+ # class YARD::Server::Router; include MemoryCaching; end
30
+ # @return [Array(Number,Hash,Array)] the Rack-style response
31
+ # @return [nil] if no cache is available and routing should continue
32
+ # @see Commands::Base#cache
4
33
  def check_static_cache
5
34
  return nil unless adapter.document_root
6
35
  cache_path = File.join(adapter.document_root, request.path.sub(/\.html$/, '') + '.html')
@@ -2,7 +2,10 @@ require 'webrick'
2
2
 
3
3
  module YARD
4
4
  module Server
5
+ # The main adapter to initialize a WEBrick server.
5
6
  class WebrickAdapter < Adapter
7
+ # Initializes a WEBrick server. If {Adapter#server_options} contains a
8
+ # +:daemonize+ key set to true, the server will be daemonized.
6
9
  def start
7
10
  server_options[:ServerType] = WEBrick::Daemon if server_options[:daemonize]
8
11
  server = WEBrick::HTTPServer.new(server_options)
@@ -12,6 +15,7 @@ module YARD
12
15
  end
13
16
  end
14
17
 
18
+ # The main WEBrick servlet implementation, accepting only GET requests.
15
19
  class WebrickServlet < WEBrick::HTTPServlet::AbstractServlet
16
20
  attr_accessor :adapter
17
21
 
@@ -2,7 +2,7 @@ require 'ostruct'
2
2
 
3
3
  module YARD
4
4
  module Templates
5
- # This module manages all creation, handling and rendering of {Engine::Template}
5
+ # This module manages all creation, handling and rendering of {Template}
6
6
  # objects.
7
7
  #
8
8
  # * To create a template object at a path, use {template}.
@@ -4,6 +4,22 @@ module YARD
4
4
  module Templates::Helpers
5
5
  # Helper methods for loading and managing markup types.
6
6
  module MarkupHelper
7
+ class << self
8
+ # Clears the markup provider cache information. Mainly used for testing.
9
+ # @return [void]
10
+ def clear_markup_cache
11
+ self.markup_cache = {}
12
+ end
13
+
14
+ # @return [Hash{Symbol=>{(:provider,:class)=>Object}}] the cached markup providers
15
+ # @private
16
+ # @since 0.6.4
17
+ attr_accessor :markup_cache
18
+ end
19
+
20
+ MarkupHelper.clear_markup_cache
21
+
22
+ # The default list of markup providers for each markup type
7
23
  MARKUP_PROVIDERS = {
8
24
  :markdown => [
9
25
  {:lib => :bluecloth, :const => 'BlueCloth'},
@@ -61,9 +77,8 @@ module YARD
61
77
  #
62
78
  # @return [Boolean] whether the markup provider was successfully loaded.
63
79
  def load_markup_provider(type = options[:markup])
64
- return true if type == :rdoc || (@markup_cache && @markup_cache[type])
65
- @markup_cache ||= {}
66
- @markup_cache[type] ||= {}
80
+ return true if type == :rdoc || MarkupHelper.markup_cache[type]
81
+ MarkupHelper.markup_cache[type] ||= {}
67
82
 
68
83
  providers = MARKUP_PROVIDERS[type]
69
84
  return true if providers && providers.empty?
@@ -79,8 +94,8 @@ module YARD
79
94
  # Search for provider, return the library class name as const if found
80
95
  providers.each do |provider|
81
96
  begin require provider[:lib].to_s; rescue LoadError; next end
82
- @markup_cache[type][:provider] = provider[:lib] # Cache the provider
83
- @markup_cache[type][:class] = eval(provider[:const])
97
+ MarkupHelper.markup_cache[type][:provider] = provider[:lib] # Cache the provider
98
+ MarkupHelper.markup_cache[type][:class] = eval("::" + provider[:const])
84
99
  return true
85
100
  end
86
101
 
@@ -130,7 +145,7 @@ module YARD
130
145
  # @param [Symbol] the markup type (:rdoc, :markdown, etc.)
131
146
  # @return [Class] the markup class
132
147
  def markup_class(type = options[:markup])
133
- type == :rdoc ? SimpleMarkup : @markup_cache[type][:class]
148
+ type == :rdoc ? SimpleMarkup : MarkupHelper.markup_cache[type][:class]
134
149
  end
135
150
 
136
151
  # Gets the markup provider name for a markup type
@@ -139,7 +154,7 @@ module YARD
139
154
  # @param [Symbol] the markup type (:rdoc, :markdown, etc.)
140
155
  # @return [Symbol] the markup provider name (usually the gem name of the library)
141
156
  def markup_provider(type = options[:markup])
142
- type == :rdoc ? nil : @markup_cache[type][:provider]
157
+ type == :rdoc ? nil : MarkupHelper.markup_cache[type][:provider]
143
158
  end
144
159
  end
145
160
  end
@@ -31,8 +31,8 @@ describe YARD::CLI::Diff do
31
31
  @diff.should_receive(:load_gem_data).ordered.with('gem2').and_return(true)
32
32
  Registry.should_receive(:all).ordered.and_return(@objects1.map {|o| P(o) })
33
33
  Registry.should_receive(:all).ordered.and_return(@objects2.map {|o| P(o) })
34
- @diff.stub!(:print).with {|data| @data << data }
35
- @diff.stub!(:puts).with {|*args| @data << args.join("\n"); @data << "\n" }
34
+ @diff.stub!(:print) {|data| @data << data }
35
+ @diff.stub!(:puts) {|*args| @data << args.join("\n"); @data << "\n" }
36
36
  @diff.run(*(args + ['gem1', 'gem2']))
37
37
  end
38
38
 
@@ -28,7 +28,7 @@ describe YARD::CLI::Stats do
28
28
  @stats = CLI::Stats.new(false)
29
29
  @stats.stub!(:support_rdoc_document_file!).and_return([])
30
30
  @stats.stub!(:yardopts).and_return([])
31
- @stats.stub!(:puts).with {|*args| @output << args.join("\n") << "\n" }
31
+ @stats.stub!(:puts) {|*args| @output << args.join("\n") << "\n" }
32
32
  end
33
33
 
34
34
  it "should list undocumented objects with --list-undoc" do
@@ -446,7 +446,7 @@ describe YARD::CLI::Yardoc do
446
446
  visible_tags = []
447
447
  Tags::Library.stub!(:define_tag)
448
448
  Tags::Library.stub!(:visible_tags).and_return([:foo])
449
- Tags::Library.stub!(:visible_tags=).with {|value| visible_tags = value }
449
+ Tags::Library.stub!(:visible_tags=) {|value| visible_tags = value }
450
450
  @yardoc.parse_arguments('--tag', 'foo', '--tag', 'foo')
451
451
  visible_tags.should == [:foo]
452
452
  end
@@ -63,4 +63,25 @@ describe YARD::CLI::Yardoc do
63
63
  YARD::CLI::YRI::DEFAULT_SEARCH_PATHS.replace([])
64
64
  end
65
65
  end
66
+
67
+ describe '#run' do
68
+ it "should search for objects and print their documentation" do
69
+ obj = YARD::CodeObjects::ClassObject.new(:root, 'Foo')
70
+ @yri.should_receive(:print_object).with(obj)
71
+ @yri.run('Foo')
72
+ Registry.clear
73
+ end
74
+
75
+ it "should print usage if no object is provided" do
76
+ @yri.should_receive(:print_usage)
77
+ @yri.should_receive(:exit).with(1)
78
+ @yri.run('')
79
+ end
80
+
81
+ it "should print no documentation exists for object if object is not found" do
82
+ STDERR.should_receive(:puts).with("No documentation for `Foo'")
83
+ @yri.should_receive(:exit).with(1)
84
+ @yri.run('Foo')
85
+ end
86
+ end
66
87
  end
@@ -57,6 +57,7 @@ describe "YARD::Handlers::Ruby::#{RUBY18 ? "Legacy::" : ""}ClassHandler" do
57
57
 
58
58
  it "should handle a superclass of the same name in the form ::ClassName" do
59
59
  P('Q::Logger').superclass.should == P(:Logger)
60
+ P('Q::Foo').superclass.should_not == P('Q::Logger')
60
61
  end
61
62
 
62
63
  ["CallMethod('test')", "VSD^#}}", 'not.aclass', 'self'].each do |klass|
@@ -65,6 +65,7 @@ end
65
65
 
66
66
  module Q
67
67
  class Logger < ::Logger; end
68
+ class Foo < ::Logger; end
68
69
  end
69
70
 
70
71
  class << Symbol
@@ -281,4 +281,10 @@ eof
281
281
  s = stmt("alias do x if 2 ==\n 2")
282
282
  s.tokens.to_s.should == "alias do x if 2 ==\n 2"
283
283
  end
284
+
285
+ it "should convert heredoc to string" do
286
+ src = "<<-XML\n foo\n\nXML"
287
+ s = stmt(src)
288
+ s.source.should == '"foo\n\n"'
289
+ end
284
290
  end
@@ -10,6 +10,10 @@ if RUBY19
10
10
  YARD::Parser::Ruby::RubyParser.new(stmts, nil).parse.root
11
11
  end
12
12
 
13
+ def tokenize(stmt)
14
+ YARD::Parser::Ruby::RubyParser.new(stmt, nil).parse.tokens
15
+ end
16
+
13
17
  describe '#parse' do
14
18
  it "should get comment line numbers" do
15
19
  s = stmt <<-eof
@@ -166,6 +170,31 @@ if RUBY19
166
170
  it "should show proper source for assignment" do
167
171
  stmt("A=1").jump(:assign).source.should == "A=1"
168
172
  end
173
+
174
+ it "should show proper source for a top_const_ref" do
175
+ s = stmt("::\nFoo::Bar")
176
+ s.jump(:top_const_ref).source.should == "::\nFoo"
177
+ s.should be_ref
178
+ s.jump(:top_const_ref).should be_ref
179
+ s.source.should == "::\nFoo::Bar"
180
+ s.line_range.to_a.should == [1, 2]
181
+ end
182
+
183
+ it "should show proper source for heredoc" do
184
+ src = "def foo\n foo(<<-XML, 1, 2)\n bar\n\n XML\nend"
185
+ s = stmt(src)
186
+ t = tokenize(src)
187
+ s.source.should == src
188
+ t.map {|x| x[1] }.join.should == src
189
+ end
190
+
191
+ it "should show proper source for string" do
192
+ ["'", '"'].each do |q|
193
+ src = "#{q}hello\n\nworld#{q}"
194
+ s = stmt(src)
195
+ s.source.should == src
196
+ end
197
+ end
169
198
  end
170
199
  end
171
200
  end
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
3
+ describe "YARD::Server::RackMiddleware" do
4
+ before do
5
+ begin; require 'rack'; rescue LoadError; pending "rack required for these tests" end
6
+ @superapp = mock(:superapp)
7
+ @app = YARD::Server::RackMiddleware.new(@superapp, :libraries => {'foo' => [LibraryVersion.new('foo', nil)]})
8
+ end
9
+
10
+ it "should handle requests" do
11
+ @app.call(Rack::MockRequest.env_for('/'))[0].should == 200
12
+ end
13
+
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']
17
+ end
18
+ end
@@ -1,5 +1,9 @@
1
1
  require "rubygems"
2
- require "spec"
2
+ begin
3
+ require "rspec"
4
+ rescue LoadError
5
+ require "spec"
6
+ end
3
7
 
4
8
  require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'yard'))
5
9
 
@@ -74,4 +78,4 @@ def docspec(objname = self.class.description, klass = self.class.described_type)
74
78
  end
75
79
  end
76
80
 
77
- include YARD
81
+ include YARD
@@ -78,9 +78,12 @@ describe YARD::Templates::Engine do
78
78
  end
79
79
 
80
80
  before(:all) do
81
+ @object = CodeObjects::MethodObject.new(:root, :method)
82
+ end
83
+
84
+ before do
81
85
  @template = mock(:template)
82
86
  @template.stub!(:include)
83
- @object = CodeObjects::MethodObject.new(:root, :method)
84
87
  end
85
88
 
86
89
  it "should accept method call with no parameters" do
@@ -5,6 +5,8 @@ describe YARD::Templates::Helpers::HtmlHelper do
5
5
  include YARD::Templates::Helpers::BaseHelper
6
6
  include YARD::Templates::Helpers::HtmlHelper
7
7
  include YARD::Templates::Helpers::MethodHelper
8
+
9
+ def options; {} end
8
10
 
9
11
  describe '#h' do
10
12
  it "should use #h to escape HTML" do
@@ -357,6 +359,12 @@ describe YARD::Templates::Helpers::HtmlHelper do
357
359
  stub!(:object).and_return(Registry.root)
358
360
  end
359
361
 
362
+ def fix_rspec2_mock_teardown
363
+ return unless defined?(RSpec)
364
+ should_receive(:respond_to?).with(:teardown_mocks_for_rspec).and_return(false)
365
+ should_receive(:respond_to?).with(:verify_mocks_for_rspec).and_return(false)
366
+ end
367
+
360
368
  it "should return empty string on nil input" do
361
369
  html_syntax_highlight(nil).should == ''
362
370
  end
@@ -369,12 +377,14 @@ describe YARD::Templates::Helpers::HtmlHelper do
369
377
 
370
378
  it "should call #html_syntax_highlight_NAME if there's an object with a #source_type" do
371
379
  Registry.root.source_type = :NAME
380
+ fix_rspec2_mock_teardown
372
381
  should_receive(:respond_to?).with('html_syntax_highlight_NAME').and_return(true)
373
382
  should_receive(:html_syntax_highlight_NAME).and_return("foobar")
374
383
  html_syntax_highlight('def x; end').should == 'foobar'
375
384
  end
376
385
 
377
386
  it "should call html_syntax_highlight_NAME if source starts with !!!NAME" do
387
+ fix_rspec2_mock_teardown
378
388
  should_receive(:respond_to?).with('html_syntax_highlight_NAME').and_return(true)
379
389
  should_receive(:html_syntax_highlight_NAME).and_return("foobar")
380
390
  html_syntax_highlight(<<-eof
@@ -391,6 +401,7 @@ describe YARD::Templates::Helpers::HtmlHelper do
391
401
  end
392
402
 
393
403
  it "should not highlight if there is no highlight method specified by !!!NAME" do
404
+ fix_rspec2_mock_teardown
394
405
  should_receive(:respond_to?).with('html_syntax_highlight_NAME').and_return(false)
395
406
  should_not_receive(:html_syntax_highlight_NAME)
396
407
  html_syntax_highlight("!!!NAME\ndef x; end").should == "def x; end"
@@ -4,21 +4,25 @@ module YARD::Templates::Helpers::MarkupHelper
4
4
  public :load_markup_provider, :markup_class, :markup_provider
5
5
  end
6
6
 
7
- class MyMock
7
+ class GeneratorMock
8
8
  attr_accessor :options
9
9
  include YARD::Templates::Helpers::MarkupHelper
10
+ def initialize(options = {}) self.options = options end
10
11
  end
11
12
 
12
13
  describe YARD::Templates::Helpers::MarkupHelper do
14
+ before do
15
+ YARD::Templates::Helpers::MarkupHelper.clear_markup_cache
16
+ end
17
+
13
18
  describe '#load_markup_provider' do
14
19
  before do
15
20
  log.stub!(:error)
16
- @gen = mock('Generator')
17
- @gen.extend(YARD::Templates::Helpers::MarkupHelper)
21
+ @gen = GeneratorMock.new
18
22
  end
19
23
 
20
24
  it "should exit on an invalid markup type" do
21
- @gen.stub!(:options).and_return({:markup => :invalid})
25
+ @gen.options = {:markup => :invalid}
22
26
  @gen.load_markup_provider.should == false
23
27
  end
24
28
 
@@ -35,7 +39,7 @@ describe YARD::Templates::Helpers::MarkupHelper do
35
39
  end
36
40
 
37
41
  it "should search through available markup providers for the markup type if none is set" do
38
- module YARD::Templates::Helpers::MarkupHelper::BlueCloth; end
42
+ @gen.should_receive(:eval).with('::BlueCloth').and_return(mock(:bluecloth))
39
43
  @gen.should_receive(:require).with('bluecloth').and_return(true)
40
44
  @gen.should_not_receive(:require).with('maruku')
41
45
  @gen.stub!(:options).and_return({:markup => :markdown})
@@ -76,7 +76,7 @@ describe YARD::Templates::Engine.template(:default, :module) do
76
76
  end
77
77
 
78
78
  it "should render dot format correctly" do
79
- Registry.at('A').format(:format => :dot, :dependencies => true, :full => true).should == example(:module001, 'dot')
79
+ Registry.at('A').format(:format => :dot, :dependencies => true, :full => true).should == example_contents(:module001, 'dot')
80
80
  end
81
81
 
82
82
  it "should render groups correctly in html" do
@@ -11,7 +11,7 @@ end
11
11
 
12
12
  def text_equals(result, expected_example)
13
13
  return if only_copy?(result, expected_example, :text)
14
- text_equals_string(result, example(expected_example, :txt))
14
+ text_equals_string(result, example_contents(expected_example, :txt))
15
15
  end
16
16
 
17
17
  def text_equals_string(result, expected)
@@ -20,7 +20,7 @@ end
20
20
 
21
21
  def html_equals(result, expected_example)
22
22
  return if only_copy?(result, expected_example, :html)
23
- html_equals_string(result, example(expected_example))
23
+ html_equals_string(result, example_contents(expected_example))
24
24
  end
25
25
 
26
26
  def html_equals_string(result, expected)
@@ -31,7 +31,7 @@ def html_equals_string(result, expected)
31
31
  text_equals_string(result, expected)
32
32
  end
33
33
 
34
- def example(filename, ext = 'html')
34
+ def example_contents(filename, ext = 'html')
35
35
  File.read(File.join(File.dirname(__FILE__), 'examples', "#{filename}.#{ext}"))
36
36
  end
37
37
 
@@ -168,7 +168,7 @@ ul.summary li { margin-bottom: 5px; }
168
168
  -moz-border-radius: 3px; -webkit-border-radius: 3px;
169
169
  }
170
170
  .summary_signature:hover { background: #eeeeff; cursor: pointer; }
171
- ul.summary.compact li { display: inline; margin-right: 5px; line-height: 2.6em;}
171
+ ul.summary.compact li { display: inline-block; margin: 0px 5px 0px 0px; line-height: 2.6em;}
172
172
  ul.summary.compact .summary_signature { padding: 5px 7px; padding-right: 4px; }
173
173
  #content .summary_signature:hover a:link,
174
174
  #content .summary_signature:hover a:visited {
@@ -93,8 +93,9 @@ function keyboardShortcuts() {
93
93
  if (window.top.frames.main) return;
94
94
  $(document).keypress(function(evt) {
95
95
  if (evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) return;
96
- if (evt.originalTarget.nodeName == "INPUT" ||
97
- evt.originalTarget.nodeName == "TEXTAREA") return;
96
+ if (typeof evt.orignalTarget !== "undefined" &&
97
+ (evt.originalTarget.nodeName == "INPUT" ||
98
+ evt.originalTarget.nodeName == "TEXTAREA")) return;
98
99
  switch (evt.charCode) {
99
100
  case 67: case 99: $('#class_list_link').click(); break; // 'c'
100
101
  case 77: case 109: $('#method_list_link').click(); break; // 'm'