yard 0.5.4 → 0.5.5
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of yard might be problematic. Click here for more details.
- data/.yardopts +1 -0
- data/ChangeLog +181 -0
- data/LEGAL +74 -0
- data/LICENSE +1 -1
- data/README.md +15 -8
- data/lib/yard.rb +3 -3
- data/lib/yard/cli/yard_graph.rb +10 -10
- data/lib/yard/cli/yardoc.rb +29 -9
- data/lib/yard/code_objects/base.rb +1 -1
- data/lib/yard/code_objects/class_object.rb +1 -1
- data/lib/yard/code_objects/module_object.rb +1 -1
- data/lib/yard/code_objects/proxy.rb +1 -1
- data/lib/yard/docstring.rb +2 -2
- data/lib/yard/handlers/ruby/constant_handler.rb +2 -2
- data/lib/yard/handlers/ruby/legacy/class_condition_handler.rb +64 -1
- data/lib/yard/handlers/ruby/legacy/constant_handler.rb +2 -2
- data/lib/yard/handlers/ruby/legacy/method_handler.rb +11 -0
- data/lib/yard/handlers/ruby/method_handler.rb +11 -0
- data/lib/yard/parser/ruby/legacy/statement_list.rb +3 -3
- data/lib/yard/parser/source_parser.rb +2 -2
- data/lib/yard/tags/default_factory.rb +9 -6
- data/lib/yard/templates/helpers/base_helper.rb +14 -4
- data/lib/yard/templates/helpers/html_helper.rb +16 -22
- data/lib/yard/templates/helpers/method_helper.rb +1 -1
- data/lib/yard/templates/helpers/module_helper.rb +1 -2
- data/spec/cli/yardoc_spec.rb +1 -1
- data/spec/code_objects/class_object_spec.rb +1 -0
- data/spec/code_objects/module_object_spec.rb +1 -0
- data/spec/docstring_spec.rb +14 -0
- data/spec/handlers/class_condition_handler_spec.rb +8 -10
- data/spec/handlers/examples/method_handler_001.rb.txt +4 -0
- data/spec/handlers/method_handler_spec.rb +7 -0
- data/spec/parser/ruby/legacy/statement_list_spec.rb +14 -0
- data/spec/parser/source_parser_spec.rb +7 -0
- data/spec/tags/default_factory_spec.rb +1 -0
- data/spec/templates/examples/class001.html +5 -5
- data/spec/templates/examples/method001.html +1 -1
- data/spec/templates/examples/module001.html +4 -4
- data/spec/templates/helpers/base_helper_spec.rb +18 -1
- data/spec/templates/helpers/html_helper_spec.rb +2 -1
- data/spec/templates/module_spec.rb +5 -2
- data/templates/default/docstring/html/abstract.erb +2 -2
- data/templates/default/docstring/html/deprecated.erb +1 -1
- data/templates/default/docstring/html/note.erb +2 -2
- data/templates/default/docstring/html/private.erb +4 -0
- data/templates/default/docstring/html/todo.erb +2 -2
- data/templates/default/docstring/setup.rb +6 -1
- data/templates/default/docstring/text/private.erb +2 -0
- data/templates/default/fulldoc/html/css/style.css +7 -3
- data/templates/default/fulldoc/html/js/app.js +27 -0
- data/templates/default/fulldoc/html/setup.rb +1 -1
- data/templates/default/module/html/attribute_summary.erb +1 -1
- data/templates/default/module/html/box_info.erb +1 -1
- data/templates/default/module/html/header.erb +2 -1
- data/templates/default/module/html/item_summary.erb +1 -0
- data/templates/default/module/html/method_summary.erb +4 -1
- data/templates/default/module/text/extends.erb +2 -2
- data/templates/default/tags/html/see.erb +1 -1
- metadata +5 -2
data/lib/yard/docstring.rb
CHANGED
@@ -149,8 +149,8 @@ module YARD
|
|
149
149
|
end
|
150
150
|
|
151
151
|
# Creates a {Tags::RefTag}
|
152
|
-
def create_ref_tag(tag_name, name,
|
153
|
-
@ref_tags << Tags::RefTagList.new(tag_name, object, name)
|
152
|
+
def create_ref_tag(tag_name, name, object_name)
|
153
|
+
@ref_tags << Tags::RefTagList.new(tag_name, P(object, object_name), name)
|
154
154
|
end
|
155
155
|
|
156
156
|
# Creates a tag from the {Tags::DefaultFactory tag factory}.
|
@@ -39,8 +39,8 @@ class YARD::Handlers::Ruby::ConstantHandler < YARD::Handlers::Ruby::Base
|
|
39
39
|
name = node.jump(:ident).source
|
40
40
|
klass.attributes[scope][name] = SymbolHash[:read => nil, :write => nil]
|
41
41
|
{read: name, write: "#{name}="}.each do |type, meth|
|
42
|
-
klass.attributes[scope][name][type] = MethodObject.new(klass, meth, scope)
|
42
|
+
klass.attributes[scope][name][type] = register MethodObject.new(klass, meth, scope)
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
46
|
-
end
|
46
|
+
end
|
@@ -1,8 +1,71 @@
|
|
1
1
|
class YARD::Handlers::Ruby::Legacy::ClassConditionHandler < YARD::Handlers::Ruby::Legacy::Base
|
2
2
|
namespace_only
|
3
|
-
handles TkIF, TkELSIF,
|
3
|
+
handles TkIF, TkELSIF, TkUNLESS
|
4
4
|
|
5
5
|
process do
|
6
|
+
condition = parse_condition
|
7
|
+
if condition == nil
|
8
|
+
# Parse both blocks if we're unsure of the condition
|
9
|
+
parse_then_block
|
10
|
+
parse_else_block
|
11
|
+
elsif condition
|
12
|
+
parse_then_block
|
13
|
+
else
|
14
|
+
parse_else_block
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
# Parses the condition part of the if/unless statement
|
21
|
+
#
|
22
|
+
# @return [true, false, nil] true if the condition can be definitely
|
23
|
+
# parsed to true, false if not, and nil if the condition cannot be
|
24
|
+
# parsed with certainty (it's dynamic)
|
25
|
+
def parse_condition
|
26
|
+
condition = nil
|
27
|
+
|
28
|
+
# Right now we can handle very simple unary conditions like:
|
29
|
+
# if true
|
30
|
+
# if false
|
31
|
+
# if 0
|
32
|
+
# if 100 (not 0)
|
33
|
+
# if defined? SOME_CONSTANT
|
34
|
+
#
|
35
|
+
# The last case will do a lookup in the registry and then one
|
36
|
+
# in the Ruby world (using eval).
|
37
|
+
case statement.tokens[1..-1].to_s.strip
|
38
|
+
when /^(\d+)$/
|
39
|
+
condition = $1 != "0"
|
40
|
+
when /^defined\?\s*\(?(.+?)\)?$/
|
41
|
+
# defined? keyword used, let's see if we can look up the name
|
42
|
+
# in the registry, then we'll try using Ruby's powers. eval() is not
|
43
|
+
# *too* dangerous here since code is not actually executed.
|
44
|
+
name = $1
|
45
|
+
obj = YARD::Registry.resolve(namespace, name, true)
|
46
|
+
condition = true if obj || Object.instance_eval("defined? #{name}")
|
47
|
+
when "true"
|
48
|
+
condition = true
|
49
|
+
when "false"
|
50
|
+
condition = false
|
51
|
+
end
|
52
|
+
|
53
|
+
if TkUNLESS === statement.tokens.first
|
54
|
+
condition = !condition if condition != nil
|
55
|
+
end
|
56
|
+
condition
|
57
|
+
end
|
58
|
+
|
59
|
+
def parse_then_block
|
6
60
|
parse_block
|
7
61
|
end
|
62
|
+
|
63
|
+
def parse_else_block
|
64
|
+
stmtlist = YARD::Parser::Ruby::Legacy::StatementList
|
65
|
+
stmtlist.new(statement.block).each do |stmt|
|
66
|
+
if TkELSE === stmt.tokens.first
|
67
|
+
parser.process(stmtlist.new(stmt.block))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
8
71
|
end
|
@@ -25,8 +25,8 @@ class YARD::Handlers::Ruby::Legacy::ConstantHandler < YARD::Handlers::Ruby::Lega
|
|
25
25
|
tokval_list(YARD::Parser::Ruby::Legacy::TokenList.new(parameters), TkSYMBOL).each do |name|
|
26
26
|
klass.attributes[scope][name] = SymbolHash[:read => nil, :write => nil]
|
27
27
|
{:read => name, :write => "#{name}="}.each do |type, meth|
|
28
|
-
klass.attributes[scope][name][type] = MethodObject.new(klass, meth, scope)
|
28
|
+
klass.attributes[scope][name][type] = register MethodObject.new(klass, meth, scope)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
32
|
-
end
|
32
|
+
end
|
@@ -42,6 +42,17 @@ class YARD::Handlers::Ruby::Legacy::MethodHandler < YARD::Handlers::Ruby::Legacy
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
if obj.has_tag?(:option)
|
46
|
+
# create the options parameter if its missing
|
47
|
+
obj.tags(:option).each do |option|
|
48
|
+
expected_param = option.name
|
49
|
+
unless obj.tags(:param).find {|x| x.name == expected_param }
|
50
|
+
new_tag = YARD::Tags::Tag.new(:param, "a customizable set of options", "Hash", expected_param)
|
51
|
+
obj.docstring.add_tag(new_tag)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
45
56
|
if info = obj.attr_info
|
46
57
|
if meth.to_s =~ /=$/ # writer
|
47
58
|
info[:write] = obj if info[:read]
|
@@ -39,6 +39,17 @@ class YARD::Handlers::Ruby::MethodHandler < YARD::Handlers::Ruby::Base
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
if obj.has_tag?(:option)
|
43
|
+
# create the options parameter if its missing
|
44
|
+
obj.tags(:option).each do |option|
|
45
|
+
expected_param = option.name
|
46
|
+
unless obj.tags(:param).find {|x| x.name == expected_param }
|
47
|
+
new_tag = YARD::Tags::Tag.new(:param, "a customizable set of options", "Hash", expected_param)
|
48
|
+
obj.docstring.add_tag(new_tag)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
42
53
|
if info = obj.attr_info
|
43
54
|
if meth.to_s =~ /=$/ # writer
|
44
55
|
info[:write] = obj if info[:read]
|
@@ -6,7 +6,7 @@ module YARD
|
|
6
6
|
# The following list of tokens will require a block to be opened
|
7
7
|
# if used at the beginning of a statement.
|
8
8
|
OPEN_BLOCK_TOKENS = [TkCLASS, TkDEF, TkMODULE, TkUNTIL,
|
9
|
-
TkIF, TkUNLESS, TkWHILE, TkFOR, TkCASE]
|
9
|
+
TkIF, TkELSIF, TkUNLESS, TkWHILE, TkFOR, TkCASE]
|
10
10
|
|
11
11
|
##
|
12
12
|
# Creates a new statement list
|
@@ -215,7 +215,7 @@ module YARD
|
|
215
215
|
#
|
216
216
|
# @param [RubyToken::Token] tk the token to process
|
217
217
|
def process_simple_block_opener(tk)
|
218
|
-
return unless [TkLBRACE, TkDO, TkBEGIN].include?(tk.class) &&
|
218
|
+
return unless [TkLBRACE, TkDO, TkBEGIN, TkELSE].include?(tk.class) &&
|
219
219
|
# Make sure hashes are parsed as hashes, not as blocks
|
220
220
|
(@last_ns_tk.nil? || @last_ns_tk.lex_state != EXPR_BEG)
|
221
221
|
|
@@ -314,7 +314,7 @@ module YARD
|
|
314
314
|
if [TkLPAREN, TkLBRACK, TkLBRACE, TkDO, TkBEGIN].include?(tk.class)
|
315
315
|
@level += 1
|
316
316
|
elsif OPEN_BLOCK_TOKENS.include?(tk.class)
|
317
|
-
@level += 1 unless @last_ns_tk.class == TkALIAS
|
317
|
+
@level += 1 unless @last_ns_tk.class == TkALIAS || tk.class == TkELSIF
|
318
318
|
elsif [TkRPAREN, TkRBRACK, TkRBRACE, TkEND].include?(tk.class) && @level > 0
|
319
319
|
@level -= 1
|
320
320
|
end
|
@@ -149,8 +149,8 @@ module YARD
|
|
149
149
|
def parse(content = __FILE__)
|
150
150
|
case content
|
151
151
|
when String
|
152
|
-
@file = content
|
153
|
-
content = convert_encoding(File.read_binary(
|
152
|
+
@file = File.cleanpath(content)
|
153
|
+
content = convert_encoding(File.read_binary(file))
|
154
154
|
checksum = Registry.checksum_for(content)
|
155
155
|
return if Registry.checksums[file] == checksum
|
156
156
|
|
@@ -110,20 +110,20 @@ module YARD
|
|
110
110
|
[title, desc]
|
111
111
|
end
|
112
112
|
|
113
|
-
# Parses a [], <>, {} or () block at the beginning of a line of text
|
114
|
-
# comma delimited values.
|
113
|
+
# Parses a [], <>, {} or () block at the beginning of a line of text
|
114
|
+
# into a list of comma delimited values.
|
115
115
|
#
|
116
116
|
# @example
|
117
117
|
# obj.parse_types('[String, Array<Hash, String>, nil]') # => [nil, ['String', 'Array<Hash, String>', 'nil'], ""]
|
118
118
|
# obj.parse_types('b<String> A string') # => ['b', ['String'], 'A string']
|
119
119
|
#
|
120
|
-
# @return [String, Array<String
|
121
|
-
#
|
122
|
-
#
|
120
|
+
# @return [Array(String, Array<String>, String)] the text before the type
|
121
|
+
# list (or nil), followed by the type list parsed into an array of
|
122
|
+
# strings, followed by the text following the type list.
|
123
123
|
def extract_types_and_name_from_text(text, opening_types = TYPELIST_OPENING_CHARS, closing_types = TYPELIST_CLOSING_CHARS)
|
124
124
|
s, e = 0, 0
|
125
125
|
before = ''
|
126
|
-
list, level = [''], 0
|
126
|
+
list, level, seen_space = [''], 0, false
|
127
127
|
text.split(//).each_with_index do |c, i|
|
128
128
|
if opening_types.include?(c)
|
129
129
|
list.last << c if level > 0
|
@@ -136,7 +136,10 @@ module YARD
|
|
136
136
|
elsif c == ',' && level == 1
|
137
137
|
list.push ''
|
138
138
|
elsif c =~ /\S/ && level == 0
|
139
|
+
break e = i if seen_space && list == ['']
|
139
140
|
before << c
|
141
|
+
elsif c =~ /\s/ && level == 0 && !before.empty?
|
142
|
+
seen_space = true
|
140
143
|
elsif level >= 1
|
141
144
|
list.last << c
|
142
145
|
end
|
@@ -14,9 +14,15 @@ module YARD::Templates::Helpers
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def linkify(*args)
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
if args.first.is_a?(String)
|
18
|
+
case args.first
|
19
|
+
when %r{://}, /^mailto:/
|
20
|
+
link_url(args[0], args[1], {:target => '_parent'}.merge(args[2]||{}))
|
21
|
+
when /^file:(\S+?)(?:#(\S+))?$/
|
22
|
+
link_file($1, args[1] ? args[1] : $1, $2)
|
23
|
+
else
|
24
|
+
link_object(*args)
|
25
|
+
end
|
20
26
|
else
|
21
27
|
link_object(*args)
|
22
28
|
end
|
@@ -35,10 +41,14 @@ module YARD::Templates::Helpers
|
|
35
41
|
end
|
36
42
|
end
|
37
43
|
|
38
|
-
def link_url(url)
|
44
|
+
def link_url(url, title = nil, params = nil)
|
39
45
|
url
|
40
46
|
end
|
41
47
|
|
48
|
+
def link_file(filename, title = nil, anchor = nil)
|
49
|
+
filename
|
50
|
+
end
|
51
|
+
|
42
52
|
def format_types(list, brackets = true)
|
43
53
|
list.nil? || list.empty? ? "" : (brackets ? "(#{list.join(", ")})" : list.join(", "))
|
44
54
|
end
|
@@ -122,33 +122,27 @@ module YARD
|
|
122
122
|
def resolve_links(text)
|
123
123
|
code_tags = 0
|
124
124
|
text.gsub(/<(\/)?(pre|code|tt)|\{(\S+?)(?:\s(.*?\S))?\}(?=[\W<]|.+<\/|$)/) do |str|
|
125
|
-
tag = $2
|
126
|
-
closed = $1
|
125
|
+
closed, tag, name, title = $1, $2, $3, $4
|
127
126
|
if tag
|
128
127
|
code_tags += (closed ? -1 : 1)
|
129
128
|
next str
|
130
129
|
end
|
131
130
|
next str unless code_tags == 0
|
132
131
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
case name
|
137
|
-
when %r{://}, /^mailto:/
|
138
|
-
link_url(name, title, :target => '_parent')
|
139
|
-
when /^file:(\S+?)(?:#(\S+))?$/
|
140
|
-
link_file($1, title == name ? $1 : title, $2)
|
132
|
+
if object.is_a?(String)
|
133
|
+
object
|
141
134
|
else
|
142
|
-
|
143
|
-
|
135
|
+
link = linkify(name, title)
|
136
|
+
if link == name || link == title
|
137
|
+
match = text[/(.{0,20}\{.*?#{Regexp.quote name}.*?\}.{0,20})/, 1]
|
138
|
+
log.warn "In file `#{object.file}':#{object.line}: Cannot resolve link to #{name} from text" + (match ? ":" : ".")
|
139
|
+
log.warn '...' + match.gsub(/\n/,"\n\t") + '...' if match
|
140
|
+
end
|
141
|
+
|
142
|
+
if name =~ %r{://} || name =~ /^(mailto|file):/
|
143
|
+
link
|
144
144
|
else
|
145
|
-
|
146
|
-
if obj.is_a?(CodeObjects::Proxy)
|
147
|
-
match = text[/(.{0,20}\{.*?#{Regexp.quote name}.*?\}.{0,20})/, 1]
|
148
|
-
log.warn "In file `#{object.file}':#{object.line}: Cannot resolve link to #{obj.path} from text" + (match ? ":" : ".")
|
149
|
-
log.warn '...' + match.gsub(/\n/,"\n\t") + '...' if match
|
150
|
-
end
|
151
|
-
"<tt>" + linkify(obj, title) + "</tt>"
|
145
|
+
"<tt>" + link + "</tt>"
|
152
146
|
end
|
153
147
|
end
|
154
148
|
end
|
@@ -199,17 +193,17 @@ module YARD
|
|
199
193
|
title = h(obj.to_s)
|
200
194
|
end
|
201
195
|
return title unless serializer
|
202
|
-
|
203
196
|
return title if obj.is_a?(CodeObjects::Proxy)
|
204
|
-
|
197
|
+
|
205
198
|
link = url_for(obj, anchor, relative)
|
206
199
|
link ? link_url(link, title, :title => "#{obj.path} (#{obj.type})") : title
|
207
200
|
end
|
208
201
|
|
209
202
|
def link_url(url, title = nil, params = {})
|
203
|
+
title ||= url
|
210
204
|
params = SymbolHash.new(false).update(
|
211
205
|
:href => url,
|
212
|
-
:title => h(title
|
206
|
+
:title => h(title)
|
213
207
|
).update(params)
|
214
208
|
"<a #{tag_attrs(params)}>#{title}</a>"
|
215
209
|
end
|
@@ -4,7 +4,6 @@ module YARD
|
|
4
4
|
module ModuleHelper
|
5
5
|
def prune_method_listing(list, hide_attributes = true)
|
6
6
|
list = run_verifier(list)
|
7
|
-
list = list.reject {|o| !options[:visibilities].include? o.visibility } if options[:visibilities]
|
8
7
|
list = list.reject {|o| o.is_alias? unless CodeObjects::Proxy === o.namespace }
|
9
8
|
list = list.reject {|o| o.is_attribute? unless CodeObjects::Proxy === o.namespace } if hide_attributes
|
10
9
|
list
|
@@ -12,4 +11,4 @@ module YARD
|
|
12
11
|
end
|
13
12
|
end
|
14
13
|
end
|
15
|
-
end
|
14
|
+
end
|
data/spec/cli/yardoc_spec.rb
CHANGED
@@ -41,7 +41,7 @@ describe YARD::CLI::Yardoc do
|
|
41
41
|
|
42
42
|
it "should use String#shell_split to split .yardopts tokens" do
|
43
43
|
optsdata = "foo bar"
|
44
|
-
optsdata.should_receive(:shell_split)
|
44
|
+
optsdata.should_receive(:shell_split).and_return([optsdata])
|
45
45
|
IO.should_receive(:read).with("test").and_return(optsdata)
|
46
46
|
@yardoc.stub!(:support_rdoc_document_file!).and_return([])
|
47
47
|
@yardoc.options_file = "test"
|
@@ -6,6 +6,7 @@ describe YARD::CodeObjects::ClassObject do
|
|
6
6
|
Registry.clear
|
7
7
|
@mixin = ModuleObject.new(:root, :SomeMixin)
|
8
8
|
@mixin2 = ModuleObject.new(:root, :SomeMixin2)
|
9
|
+
@mixin2.instance_mixins << @mixin
|
9
10
|
@mixin3 = ModuleObject.new(:root, :SomeMixin3)
|
10
11
|
@mixin4 = ModuleObject.new(:root, :SomeMixin4)
|
11
12
|
@mixin2.instance_mixins << @mixin3
|
data/spec/docstring_spec.rb
CHANGED
@@ -117,6 +117,20 @@ describe YARD::Docstring do
|
|
117
117
|
tags = doc.tags('param')
|
118
118
|
tags.size.should == 0
|
119
119
|
end
|
120
|
+
|
121
|
+
it "resolves references to methods in the same class with #methname" do
|
122
|
+
klass = CodeObjects::ClassObject.new(:root, "Foo")
|
123
|
+
o = CodeObjects::MethodObject.new(klass, "bar")
|
124
|
+
ref = CodeObjects::MethodObject.new(klass, "baz")
|
125
|
+
o.docstring.add_tag Tags::Tag.new('param', 'testing', nil, 'arg1')
|
126
|
+
ref.docstring = "@param (see #bar)"
|
127
|
+
|
128
|
+
tags = ref.docstring.tags("param")
|
129
|
+
tags.size.should == 1
|
130
|
+
tags.first.text.should == "testing"
|
131
|
+
tags.first.should be_kind_of(Tags::RefTag)
|
132
|
+
tags.first.owner.should == o
|
133
|
+
end
|
120
134
|
end
|
121
135
|
|
122
136
|
describe '#empty?/#blank?' do
|
@@ -32,17 +32,15 @@ describe "YARD::Handlers::Ruby::#{RUBY18 ? "Legacy::" : ""}ClassConditionHandler
|
|
32
32
|
verify_method :j, :k
|
33
33
|
end
|
34
34
|
|
35
|
-
if
|
36
|
-
|
37
|
-
|
38
|
-
end
|
35
|
+
it "should parse all if/elsif blocks for complex conditions" do
|
36
|
+
verify_method :a, :b, :c, :d
|
37
|
+
end
|
39
38
|
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
it "should only parse else block if condition is literal value `false`" do
|
40
|
+
verify_method :q
|
41
|
+
end
|
43
42
|
|
44
|
-
|
45
|
-
|
46
|
-
end
|
43
|
+
it "should only parse else block if condition is literal integer == 0" do
|
44
|
+
verify_method :n
|
47
45
|
end
|
48
46
|
end
|