yard 0.5.2 → 0.5.3

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 (68) hide show
  1. data/README.md +14 -2
  2. data/Rakefile +5 -10
  3. data/benchmarks/parsing.rb +2 -2
  4. data/docs/WhatsNew.md +43 -5
  5. data/lib/rubygems_plugin.rb +49 -45
  6. data/lib/yard.rb +1 -1
  7. data/lib/yard/cli/base.rb +4 -0
  8. data/lib/yard/cli/yard_graph.rb +1 -0
  9. data/lib/yard/cli/yardoc.rb +24 -2
  10. data/lib/yard/cli/yri.rb +1 -0
  11. data/lib/yard/code_objects/base.rb +9 -0
  12. data/lib/yard/code_objects/class_object.rb +1 -1
  13. data/lib/yard/code_objects/method_object.rb +20 -4
  14. data/lib/yard/core_ext/file.rb +6 -0
  15. data/lib/yard/core_ext/hash.rb +1 -1
  16. data/lib/yard/core_ext/string.rb +3 -1
  17. data/lib/yard/handlers/ruby/attribute_handler.rb +22 -18
  18. data/lib/yard/handlers/ruby/legacy/attribute_handler.rb +21 -17
  19. data/lib/yard/handlers/ruby/legacy/method_handler.rb +8 -0
  20. data/lib/yard/handlers/ruby/method_handler.rb +8 -1
  21. data/lib/yard/logging.rb +1 -1
  22. data/lib/yard/parser/c_parser.rb +10 -17
  23. data/lib/yard/parser/ruby/legacy/statement_list.rb +7 -0
  24. data/lib/yard/parser/ruby/ruby_parser.rb +2 -1
  25. data/lib/yard/parser/source_parser.rb +20 -3
  26. data/lib/yard/templates/helpers/html_helper.rb +48 -22
  27. data/lib/yard/templates/template.rb +6 -1
  28. data/spec/cli/yardoc_spec.rb +22 -0
  29. data/spec/code_objects/base_spec.rb +34 -1
  30. data/spec/code_objects/method_object_spec.rb +35 -0
  31. data/spec/core_ext/hash_spec.rb +4 -0
  32. data/spec/core_ext/string_spec.rb +5 -1
  33. data/spec/handlers/attribute_handler_spec.rb +9 -1
  34. data/spec/handlers/examples/attribute_handler_001.rb.txt +8 -0
  35. data/spec/handlers/examples/method_handler_001.rb.txt +6 -0
  36. data/spec/handlers/method_handler_spec.rb +10 -0
  37. data/spec/parser/source_parser_spec.rb +29 -26
  38. data/spec/spec_helper.rb +1 -1
  39. data/spec/templates/engine_spec.rb +1 -0
  40. data/spec/templates/examples/class001.html +4 -0
  41. data/spec/templates/examples/class001.txt +5 -0
  42. data/spec/templates/examples/module001.dot +1 -1
  43. data/spec/templates/examples/module001.html +92 -12
  44. data/spec/templates/helpers/html_helper_spec.rb +25 -5
  45. data/spec/templates/module_spec.rb +3 -1
  46. data/spec/templates/template_spec.rb +11 -1
  47. data/templates/default/class/html/subclasses.erb +1 -1
  48. data/templates/default/class/setup.rb +10 -3
  49. data/templates/default/class/text/subclasses.erb +1 -1
  50. data/templates/default/fulldoc/html/css/full_list.css +38 -11
  51. data/templates/default/fulldoc/html/css/style.css +6 -1
  52. data/templates/default/fulldoc/html/frames.erb +13 -0
  53. data/templates/default/fulldoc/html/full_list.erb +20 -22
  54. data/templates/default/fulldoc/html/full_list_class.erb +2 -0
  55. data/templates/default/fulldoc/html/full_list_files.erb +5 -0
  56. data/templates/default/fulldoc/html/full_list_methods.erb +12 -0
  57. data/templates/default/fulldoc/html/js/app.js +10 -2
  58. data/templates/default/fulldoc/html/js/full_list.js +76 -9
  59. data/templates/default/fulldoc/html/setup.rb +37 -2
  60. data/templates/default/layout/html/breadcrumb.erb +3 -1
  61. data/templates/default/layout/html/layout.erb +4 -0
  62. data/templates/default/layout/html/search.erb +1 -1
  63. data/templates/default/layout/html/setup.rb +13 -2
  64. data/templates/default/module/dot/info.erb +1 -1
  65. data/templates/default/module/html/attribute_details.erb +1 -1
  66. data/templates/default/module/html/constant_summary.erb +1 -1
  67. data/templates/default/module/html/item_summary.erb +2 -2
  68. metadata +6 -2
@@ -49,4 +49,10 @@ class File
49
49
  FileUtils.mkdir_p(dir) unless directory?(dir)
50
50
  open(file, *args, &block)
51
51
  end
52
+
53
+ # Reads a file with binary encoding
54
+ # @return [String] the ascii-8bit encoded data
55
+ def self.read_binary(file)
56
+ File.open(file, 'rb') {|f| f.read }
57
+ end
52
58
  end
@@ -1,7 +1,7 @@
1
1
  class Hash
2
2
  class << self
3
3
  def create(*args)
4
- if args.is_a?(Array)
4
+ if args.first.is_a?(Array) && args.size == 1
5
5
  obj = new
6
6
  args.first.each {|k, v| obj[k] = v }
7
7
  obj
@@ -4,6 +4,7 @@ class String
4
4
  #
5
5
  # @example
6
6
  # "FooBar".underscore # => "foo_bar"
7
+ # "Foo::Bar".underscore # => "foo/bar"
7
8
  # @return [String] the underscored lower case string
8
9
  def underscore
9
10
  gsub(/([a-z])([A-Z])/, '\1_\2').downcase.gsub('::', '/')
@@ -13,9 +14,10 @@ class String
13
14
  #
14
15
  # @example
15
16
  # "foo_bar_baz".camelcase # => "FooBarBaz"
17
+ # "foo/bar".camelcase # => "Foo::Bar"
16
18
  # @return [String] the camel cased text
17
19
  def camelcase
18
- gsub(/([a-z])_([a-z])/i) { $1 + $2.upcase }.sub(/^(.)/) { $1.upcase }.gsub('/', '::')
20
+ gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(?:^|_)(.)/) { $1.upcase }
19
21
  end
20
22
 
21
23
  # Splits text into tokens the way a shell would, handling quoted
@@ -26,29 +26,33 @@ class YARD::Handlers::Ruby::AttributeHandler < YARD::Handlers::Ruby::Base
26
26
 
27
27
  # Add all attributes
28
28
  validated_attribute_names(params).each do |name|
29
- namespace.attributes[scope][name] = SymbolHash[:read => nil, :write => nil]
29
+ namespace.attributes[scope][name] ||= SymbolHash[:read => nil, :write => nil]
30
30
 
31
31
  # Show their methods as well
32
32
  {:read => name, :write => "#{name}="}.each do |type, meth|
33
- next unless (type == :read ? read : write)
34
-
35
- namespace.attributes[scope][name][type] = MethodObject.new(namespace, meth, scope) do |o|
36
- if type == :write
37
- src = "def #{meth}(value)"
38
- full_src = "#{src}\n @#{name} = value\nend"
39
- doc = "Sets the attribute #{name}\n@param value the value to set the attribute #{name} to."
40
- else
41
- src = "def #{meth}"
42
- full_src = "#{src}\n @#{name}\nend"
43
- doc = "Returns the value of attribute #{name}"
33
+ if (type == :read ? read : write)
34
+ namespace.attributes[scope][name][type] = MethodObject.new(namespace, meth, scope) do |o|
35
+ if type == :write
36
+ o.parameters = [['value', nil]]
37
+ src = "def #{meth}(value)"
38
+ full_src = "#{src}\n @#{name} = value\nend"
39
+ doc = "Sets the attribute #{name}\n@param value the value to set the attribute #{name} to."
40
+ else
41
+ src = "def #{meth}"
42
+ full_src = "#{src}\n @#{name}\nend"
43
+ doc = "Returns the value of attribute #{name}"
44
+ end
45
+ o.source ||= full_src
46
+ o.signature ||= src
47
+ o.docstring = statement.comments.to_s.empty? ? doc : statement.comments
44
48
  end
45
- o.source ||= full_src
46
- o.signature ||= src
47
- o.docstring = statement.comments.to_s.empty? ? doc : statement.comments
49
+
50
+ # Register the objects explicitly
51
+ register namespace.attributes[scope][name][type]
52
+ elsif obj = namespace.children.find {|o| o.name == meth.to_sym && o.scope == scope }
53
+ # register an existing method as attribute
54
+ namespace.attributes[scope][name][type] = obj
48
55
  end
49
-
50
- # Register the objects explicitly
51
- register namespace.attributes[scope][name][type]
52
56
  end
53
57
  end
54
58
  end
@@ -29,25 +29,29 @@ class YARD::Handlers::Ruby::Legacy::AttributeHandler < YARD::Handlers::Ruby::Leg
29
29
 
30
30
  # Show their methods as well
31
31
  {:read => name, :write => "#{name}="}.each do |type, meth|
32
- next unless (type == :read ? read : write)
33
-
34
- namespace.attributes[scope][name][type] = MethodObject.new(namespace, meth, scope) do |o|
35
- if type == :write
36
- src = "def #{meth}(value)"
37
- full_src = "#{src}\n @#{name} = value\nend"
38
- doc = "Sets the attribute #{name}\n@param value the value to set the attribute #{name} to."
39
- else
40
- src = "def #{meth}"
41
- full_src = "#{src}\n @#{name}\nend"
42
- doc = "Returns the value of attribute #{name}"
32
+ if (type == :read ? read : write)
33
+ namespace.attributes[scope][name][type] = MethodObject.new(namespace, meth, scope) do |o|
34
+ if type == :write
35
+ o.parameters = [['value', nil]]
36
+ src = "def #{meth}(value)"
37
+ full_src = "#{src}\n @#{name} = value\nend"
38
+ doc = "Sets the attribute #{name}\n@param value the value to set the attribute #{name} to."
39
+ else
40
+ src = "def #{meth}"
41
+ full_src = "#{src}\n @#{name}\nend"
42
+ doc = "Returns the value of attribute #{name}"
43
+ end
44
+ o.source ||= full_src
45
+ o.signature ||= src
46
+ o.docstring = statement.comments.to_s.empty? ? doc : statement.comments
43
47
  end
44
- o.source ||= full_src
45
- o.signature ||= src
46
- o.docstring = statement.comments.to_s.empty? ? doc : statement.comments
47
- end
48
48
 
49
- # Register the objects explicitly
50
- register namespace.attributes[scope][name][type]
49
+ # Register the objects explicitly
50
+ register namespace.attributes[scope][name][type]
51
+ elsif obj = namespace.children.find {|o| o.name == meth.to_sym && o.scope == scope }
52
+ # register an existing method as attribute
53
+ namespace.attributes[scope][name][type] = obj
54
+ end
51
55
  end
52
56
  end
53
57
  end
@@ -41,6 +41,14 @@ class YARD::Handlers::Ruby::Legacy::MethodHandler < YARD::Handlers::Ruby::Legacy
41
41
  obj.docstring.add_tag(YARD::Tags::Tag.new(:return, "", "Boolean"))
42
42
  end
43
43
  end
44
+
45
+ if info = obj.attr_info
46
+ if meth.to_s =~ /=$/ # writer
47
+ info[:write] = obj if info[:read]
48
+ else
49
+ info[:read] = obj if info[:write]
50
+ end
51
+ end
44
52
 
45
53
  parse_block(:owner => obj) # mainly for yield/exceptions
46
54
  end
@@ -22,7 +22,6 @@ class YARD::Handlers::Ruby::MethodHandler < YARD::Handlers::Ruby::Base
22
22
  o.signature = method_signature(meth)
23
23
  o.explicit = true
24
24
  o.parameters = args
25
-
26
25
  end
27
26
  if mscope == :instance && meth == "initialize"
28
27
  unless obj.has_tag?(:return)
@@ -40,6 +39,14 @@ class YARD::Handlers::Ruby::MethodHandler < YARD::Handlers::Ruby::Base
40
39
  end
41
40
  end
42
41
 
42
+ if info = obj.attr_info
43
+ if meth.to_s =~ /=$/ # writer
44
+ info[:write] = obj if info[:read]
45
+ else
46
+ info[:read] = obj if info[:write]
47
+ end
48
+ end
49
+
43
50
  parse_block(blk, :owner => obj) # mainly for yield/exceptions
44
51
  end
45
52
 
data/lib/yard/logging.rb CHANGED
@@ -15,7 +15,7 @@ module YARD
15
15
  # Creates a new logger
16
16
  def initialize(*args)
17
17
  super
18
- self.show_backtraces = false
18
+ self.show_backtraces = true
19
19
  self.level = WARN
20
20
  self.formatter = method(:format_log)
21
21
  end
@@ -18,7 +18,11 @@ module YARD
18
18
  parse_includes
19
19
  end
20
20
 
21
- protected
21
+ private
22
+
23
+ def remove_var_prefix(var)
24
+ var.gsub(/^rb_[mc]|^[a-z_]+/, '')
25
+ end
22
26
 
23
27
  def ensure_loaded!(object, max_retries = 1)
24
28
  return if object.is_a?(CodeObjects::RootObject)
@@ -45,7 +49,7 @@ module YARD
45
49
  end
46
50
 
47
51
  def handle_module(var_name, mod_name, in_module = nil)
48
- namespace = @namespaces[in_module] || (in_module ? P(in_module.gsub(/^rb_[mc]/, '')) : :root)
52
+ namespace = @namespaces[in_module] || (in_module ? P(remove_var_prefix(in_module)) : :root)
49
53
  ensure_loaded!(namespace)
50
54
  obj = CodeObjects::ModuleObject.new(namespace, mod_name)
51
55
  obj.add_file(@file)
@@ -55,10 +59,10 @@ module YARD
55
59
 
56
60
  def handle_class(var_name, class_name, parent, in_module = nil)
57
61
  parent = nil if parent == "0"
58
- namespace = @namespaces[in_module] || (in_module ? P(in_module.gsub(/^rb_[mc]/, '')) : :root)
62
+ namespace = @namespaces[in_module] || (in_module ? P(remove_var_prefix(in_module)) : :root)
59
63
  ensure_loaded!(namespace)
60
64
  obj = CodeObjects::ClassObject.new(namespace, class_name)
61
- obj.superclass = @namespaces[parent] || parent.gsub(/^rb_[mc]/, '') if parent
65
+ obj.superclass = @namespaces[parent] || remove_var_prefix(parent) if parent
62
66
  obj.add_file(@file)
63
67
  find_namespace_docstring(obj)
64
68
  @namespaces[var_name] = obj
@@ -71,7 +75,7 @@ module YARD
71
75
  else; scope = :instance
72
76
  end
73
77
 
74
- namespace = @namespaces[var_name] || P(var_name.gsub(/^rb_[mc]/, ''))
78
+ namespace = @namespaces[var_name] || P(remove_var_prefix(var_name))
75
79
  ensure_loaded!(namespace)
76
80
  obj = CodeObjects::MethodObject.new(namespace, name, scope)
77
81
  obj.add_file(@file)
@@ -112,17 +116,6 @@ module YARD
112
116
  comment = $1
113
117
  elsif @content =~ %r{Document-(?:class|module):\s#{object.path}\s*?(?:<\s+[:,\w]+)?\n((?>.*?\*/))}m
114
118
  comment = $1
115
- else
116
- if @content =~ /rb_define_(class|module)/m then
117
- comments = []
118
- @content.split(/(\/\*.*?\*\/)\s*?\n/m).each_with_index do |chunk, index|
119
- comments[index] = chunk
120
- if chunk =~ /rb_define_(class|module).*?"(#{object.name})"/m then
121
- comment = comments[index-1]
122
- break
123
- end
124
- end
125
- end
126
119
  end
127
120
  object.docstring = parse_comments(object, comment) if comment
128
121
  end
@@ -344,7 +337,7 @@ module YARD
344
337
  def parse_includes
345
338
  @content.scan(/rb_include_module\s*\(\s*(\w+?),\s*(\w+?)\s*\)/) do |klass, mod|
346
339
  if klass = @namespaces[klass]
347
- mod = @namespaces[mod] || P(mod.gsub(/^rb_[mc]/, ''))
340
+ mod = @namespaces[mod] || P(remove_var_prefix(mod))
348
341
  klass.mixins(:instance) << mod
349
342
  end
350
343
  end
@@ -48,6 +48,7 @@ module YARD
48
48
  @comments_line = nil
49
49
  @statement, @block, @comments = TokenList.new, nil, nil
50
50
  @last_tk, @last_ns_tk, @before_last_tk = nil, nil, nil
51
+ @first_line = nil
51
52
 
52
53
  while !@done && tk = @tokens.shift
53
54
  process_token(tk)
@@ -149,6 +150,10 @@ module YARD
149
150
  process_statement_end(tk)
150
151
  @state = :block
151
152
  end
153
+
154
+ if @first_line == tk.line_no && !@statement.empty? && TkCOMMENT === tk
155
+ process_initial_comment(tk)
156
+ end
152
157
  end
153
158
 
154
159
  ##
@@ -182,6 +187,7 @@ module YARD
182
187
 
183
188
  return unless tk.class == TkCOMMENT
184
189
  return if !@statement.empty? && @comments
190
+ return if @first_line && tk.line_no > @first_line
185
191
 
186
192
  @comments = nil if @comments_last_line && @comments_last_line < tk.line_no - 1
187
193
  @comments_line = tk.line_no unless @comments
@@ -316,6 +322,7 @@ module YARD
316
322
  #
317
323
  # @param [RubyToken::Token] tk the token to process
318
324
  def push_token(tk)
325
+ @first_line = tk.line_no if @statement.empty?
319
326
  @statement << tk unless @level == 0 && [TkCOMMENT].include?(tk.class)
320
327
  end
321
328
 
@@ -308,12 +308,13 @@ module YARD
308
308
  comment = comment.gsub(/^\#{1,2}\s{0,1}/, '').chomp
309
309
  append_comment = @comments[lineno - 1]
310
310
 
311
- if append_comment
311
+ if append_comment && @comments_last_column == column
312
312
  @comments.delete(lineno - 1)
313
313
  comment = append_comment + "\n" + comment
314
314
  end
315
315
 
316
316
  @comments[lineno] = comment
317
+ @comments_last_column = column
317
318
  end
318
319
 
319
320
  def on_parse_error(msg)
@@ -46,15 +46,22 @@ module YARD
46
46
  #
47
47
  # @param [String, Array<String>] paths a path, glob, or list of paths to
48
48
  # parse
49
+ # @param [Array<String, Regexp>] excluded a list of excluded path matchers
49
50
  # @param [Fixnum] level the logger level to use during parsing. See
50
51
  # {YARD::Logger}
51
52
  # @return the parser object that was used to parse the source.
52
- def parse(paths = ["lib/**/*.rb", "ext/**/*.c"], level = log.level)
53
+ def parse(paths = ["lib/**/*.rb", "ext/**/*.c"], excluded = [], level = log.level)
53
54
  log.debug("Parsing #{paths} with `#{parser_type}` parser")
55
+ excluded = excluded.map do |path|
56
+ case path
57
+ when Regexp; path
58
+ else Regexp.new(path.to_s, Regexp::IGNORECASE)
59
+ end
60
+ end
54
61
  files = [paths].flatten.
55
62
  map {|p| File.directory?(p) ? "#{p}/**/*.{rb,c}" : p }.
56
63
  map {|p| p.include?("*") ? Dir[p] : p }.flatten.
57
- reject {|p| !File.file?(p) }
64
+ reject {|p| !File.file?(p) || excluded.any? {|re| p =~ re } }
58
65
 
59
66
  log.enter_level(level) do
60
67
  parse_in_order(*files.uniq)
@@ -143,7 +150,7 @@ module YARD
143
150
  case content
144
151
  when String
145
152
  @file = content
146
- content = IO.read(content)
153
+ content = convert_encoding(File.read_binary(content))
147
154
  checksum = Registry.checksum_for(content)
148
155
  return if Registry.checksums[file] == checksum
149
156
 
@@ -183,6 +190,16 @@ module YARD
183
190
  end
184
191
 
185
192
  private
193
+
194
+ # Searches for encoding line and forces encoding
195
+ def convert_encoding(content)
196
+ return content if RUBY18
197
+ if content =~ /\A\s*#.*coding:\s*(\S+)\s*$/
198
+ content.force_encoding($1)
199
+ else
200
+ content
201
+ end
202
+ end
186
203
 
187
204
  # Runs a {Handlers::Processor} object to post process the parsed statements.
188
205
  # @return [void]
@@ -44,14 +44,14 @@ module YARD
44
44
  doc.hard_breaks = false if doc.respond_to?(:hard_breaks=)
45
45
  html = doc.to_html
46
46
  when :rdoc
47
- html = fix_typewriter(text)
48
47
 
49
48
  begin
50
49
  SimpleMarkupHtml.instance_variable_set("@from_path", url_for(object))
51
- html = MarkupHelper::SimpleMarkup.convert(html, SimpleMarkupHtml)
50
+ html = MarkupHelper::SimpleMarkup.convert(text, SimpleMarkupHtml)
52
51
  end
53
52
 
54
53
  html = fix_dash_dash(html)
54
+ html = fix_typewriter(html)
55
55
  end
56
56
 
57
57
  html = resolve_links(html)
@@ -73,7 +73,13 @@ module YARD
73
73
  # @todo Refactor into own SimpleMarkup subclass
74
74
  def fix_typewriter(text)
75
75
  text.gsub(/\+(?! )([^\n\+]{1,900})(?! )\+/) do
76
- '<tt>' + $1.gsub(/(.)/, "\\1\004") + '</tt>'
76
+ type_text, pre_text, no_match = $1, $`, $&
77
+ pre_match = pre_text.scan(%r(</?(?:pre|tt|code).*?>))
78
+ if pre_match.last.nil? || pre_match.last.include?('/')
79
+ '<tt>' + type_text + '</tt>'
80
+ else
81
+ no_match
82
+ end
77
83
  end
78
84
  end
79
85
 
@@ -96,7 +102,7 @@ module YARD
96
102
  # @return [String] HTML with linkified references
97
103
  def resolve_links(text)
98
104
  code_tags = 0
99
- text.gsub(/<(\/)?(pre|code|tt)|(\s|>|^)\{(\S+?)(?:\s(.*?\S))?\}(?=[\W<]|.+<\/|$)/) do |str|
105
+ text.gsub(/<(\/)?(pre|code|tt)|\{(\S+?)(?:\s(.*?\S))?\}(?=[\W<]|.+<\/|$)/) do |str|
100
106
  tag = $2
101
107
  closed = $1
102
108
  if tag
@@ -105,14 +111,14 @@ module YARD
105
111
  end
106
112
  next str unless code_tags == 0
107
113
 
108
- sp, name = $3, $4
109
- title = $5 || name
114
+ name = $3
115
+ title = $4 || name
110
116
 
111
117
  case name
112
118
  when %r{://}, /^mailto:/
113
- sp + link_url(name, title, :target => '_parent')
119
+ link_url(name, title, :target => '_parent')
114
120
  when /^file:(\S+?)(?:#(\S+))?$/
115
- sp + link_file($1, title == name ? $1 : title, $2)
121
+ link_file($1, title == name ? $1 : title, $2)
116
122
  else
117
123
  if object.is_a?(String)
118
124
  obj = name
@@ -123,7 +129,7 @@ module YARD
123
129
  log.warn "In file `#{object.file}':#{object.line}: Cannot resolve link to #{obj.path} from text" + (match ? ":" : ".")
124
130
  log.warn '...' + match.gsub(/\n/,"\n\t") + '...' if match
125
131
  end
126
- "#{sp}<tt>" + linkify(obj, title) + "</tt>"
132
+ "<tt>" + linkify(obj, title) + "</tt>"
127
133
  end
128
134
  end
129
135
  end
@@ -164,14 +170,21 @@ module YARD
164
170
  def link_object(obj, otitle = nil, anchor = nil, relative = true)
165
171
  return otitle if obj.nil?
166
172
  obj = Registry.resolve(object, obj, true, true) if obj.is_a?(String)
167
- title = otitle ? otitle.to_s : h(obj.path)
168
- title = "Top Level Namespace" if title == "" && obj.root?
173
+ if !otitle && obj.root?
174
+ title = "Top Level Namespace"
175
+ elsif otitle
176
+ title = otitle.to_s
177
+ elsif object.is_a?(CodeObjects::Base)
178
+ title = h(object.relative_path(obj))
179
+ else
180
+ title = h(obj.to_s)
181
+ end
169
182
  return title unless serializer
170
183
 
171
184
  return title if obj.is_a?(CodeObjects::Proxy)
172
185
 
173
186
  link = url_for(obj, anchor, relative)
174
- link ? link_url(link, title) : title
187
+ link ? link_url(link, title, :title => "#{obj.path} (#{obj.type})") : title
175
188
  end
176
189
 
177
190
  def link_url(url, title = nil, params = {})
@@ -244,12 +257,9 @@ module YARD
244
257
  link + '.html' + (anchor ? '#' + urlencode(anchor) : '')
245
258
  end
246
259
 
247
- def signature(meth, link = true, show_extras = true)
248
- # use first overload tag if it has a return type and method itself does not
249
- if !meth.tag(:return) && meth.tags(:overload).size == 1 && meth.tag(:overload).tag(:return)
250
- meth = meth.tag(:overload)
251
- end
252
-
260
+ def signature_types(meth, link = true)
261
+ meth = convert_method_to_overload(meth)
262
+
253
263
  type = options[:default_return] || ""
254
264
  if meth.tag(:return) && meth.tag(:return).types
255
265
  types = meth.tags(:return).map {|t| t.types ? t.types : [] }.flatten
@@ -268,16 +278,22 @@ module YARD
268
278
  elsif !type.empty?
269
279
  type = link ? h(type) : format_types([type], false)
270
280
  end
281
+ type = "(#{type}) " unless type.empty?
282
+ type
283
+ end
284
+
285
+ def signature(meth, link = true, show_extras = true, full_attr_name = true)
286
+ meth = convert_method_to_overload(meth)
271
287
 
288
+ type = signature_types(meth, link)
272
289
  scope = meth.scope == :class ? "+" : "-"
273
- type = "(#{type}) " unless type.empty?
274
- name = meth.name
290
+ name = full_attr_name ? meth.name : meth.name.to_s.gsub(/=$/, '')
275
291
  blk = format_block(meth)
276
- args = format_args(meth)
292
+ args = !full_attr_name && meth.writer? ? "" : format_args(meth)
277
293
  extras = []
278
294
  extras_text = ''
279
295
  if show_extras
280
- if meth.is_attribute? && rw = meth.namespace.attributes[meth.scope][meth.name]
296
+ if rw = meth.attr_info
281
297
  attname = [rw[:read] ? 'read' : nil, rw[:write] ? 'write' : nil].compact
282
298
  attname = attname.size == 1 ? attname.join('') + 'only' : nil
283
299
  extras << attname if attname
@@ -315,6 +331,16 @@ module YARD
315
331
  def html_syntax_highlight_plain(source)
316
332
  h(source)
317
333
  end
334
+
335
+ private
336
+
337
+ def convert_method_to_overload(meth)
338
+ # use first overload tag if it has a return type and method itself does not
339
+ if !meth.tag(:return) && meth.tags(:overload).size == 1 && meth.tag(:overload).tag(:return)
340
+ return meth.tag(:overload)
341
+ end
342
+ meth
343
+ end
318
344
  end
319
345
  end
320
346
  end