public
Description: PLEASE GO TO http://yard.soen.ca FOR IMPORTANT NEWS ABOUT YARD / THE AUTHOR!!!
Homepage: http://yard.soen.ca / IRC: #yard on irc.freenode.net
Clone URL: git://github.com/lsegal/yard.git
Click here to lend your support to: yard and make a donation at www.pledgie.com !
Move .docstring and .tags from CodeObject into new YARD::Docstring class
lsegal (author)
Mon Jun 30 11:50:07 -0700 2008
commit  713f607d521de0cdfed788c0d318a3bee8af3490
tree    e027bc9a43caca54c9567a76006da5a55719dc0b
parent  e75000c371855ba7476828792002d3fa4763930d
...
107
108
109
110
 
 
111
112
113
...
107
108
109
 
110
111
112
113
114
0
@@ -107,7 +107,8 @@ module YARD
0
     autoload :DefaultTag, 'yard/tags/default_tag'
0
   end
0
 
0
- autoload :Registry, 'yard/registry'
0
+ autoload :Docstring, 'yard/docstring'
0
+ autoload :Registry, 'yard/registry'
0
 end
0
 
0
 # Load handlers immediately
...
83
84
85
86
 
87
88
89
...
148
149
150
151
 
152
153
154
155
156
 
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
 
 
 
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
...
83
84
85
 
86
87
88
89
...
148
149
150
 
151
152
153
154
 
 
155
156
157
158
 
 
 
 
 
 
 
 
 
 
159
160
161
...
195
196
197
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
199
200
201
202
203
204
205
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
207
208
0
@@ -83,7 +83,7 @@ module YARD
0
 
0
         @name = name.to_sym
0
         @tags = []
0
- @docstring = ""
0
+ @docstring = Docstring.new
0
         self.namespace = namespace
0
         yield(self) if block_given?
0
       end
0
@@ -148,25 +148,14 @@ module YARD
0
       # Attaches a docstring to a code oject by parsing the comments attached to the statement
0
       # and filling the {#tags} and {#docstring} methods with the parsed information.
0
       #
0
- # @param [String, Array<String>] comments
0
+ # @param [String, Array<String>, Docstring] comments
0
       # the comments attached to the code object to be parsed
0
       # into a docstring and meta tags.
0
       def docstring=(comments)
0
- @short_docstring = nil
0
- parse_comments(comments) if comments
0
+ @docstring = Docstring === comments ? comments : Docstring.new(comments)
0
       end
0
       
0
       ##
0
- # Gets the first line of a docstring to the period or the first paragraph.
0
- #
0
- # @return [String] The first line or paragraph of the docstring; always ends with a period.
0
- def short_docstring
0
- @short_docstring ||= (docstring.split(/\.|\r?\n\r?\n/).first || '')
0
- @short_docstring += '.' unless @short_docstring.empty?
0
- @short_docstring
0
- end
0
-
0
- ##
0
       # Default type is the lowercase class name without the "Object" suffix
0
       #
0
       # Override this method to provide a custom object type
0
@@ -206,113 +195,14 @@ module YARD
0
       alias_method :parent, :namespace
0
       alias_method :parent=, :namespace=
0
 
0
- ##
0
- # Convenience method to return the first tag
0
- # object in the list of tag objects of that name
0
- #
0
- # Example:
0
- # doc = YARD::Documentation.new("@return zero when nil")
0
- # doc.tag("return").text # => "zero when nil"
0
- #
0
- # @param [#to_s] name the tag name to return data for
0
- # @return [Tags::Tag] the first tag in the list of {#tags}
0
- def tag(name)
0
- @tags.find {|tag| tag.tag_name.to_s == name.to_s }
0
- end
0
-
0
- ##
0
- # Returns a list of tags specified by +name+ or all tags if +name+ is not specified.
0
- #
0
- # @param name the tag name to return data for, or nil for all tags
0
- # @return [Array<Tags::Tag>] the list of tags by the specified tag name
0
- def tags(name = nil)
0
- return @tags if name.nil?
0
- @tags.select {|tag| tag.tag_name.to_s == name.to_s }
0
- end
0
-
0
- ##
0
- # Returns true if at least one tag by the name +name+ was declared
0
- #
0
- # @param [String] name the tag name to search for
0
- # @return [Boolean] whether or not the tag +name+ was declared
0
- def has_tag?(name)
0
- @tags.any? {|tag| tag.tag_name.to_s == name.to_s }
0
- end
0
+ def tag(name); @docstring.tag(name) end
0
+ def tags(name = nil); @docstring.tags(name) end
0
+ def has_tag?(name); @docstring.has_tag?(name) end
0
 
0
       protected
0
     
0
       def sep; NSEP end
0
 
0
- private
0
-
0
- ##
0
- # Parses out comments split by newlines into a new code object
0
- #
0
- # @param [Array<String>, String] comments
0
- # the newline delimited array of comments. If the comments
0
- # are passed as a String, they will be split by newlines.
0
- def parse_comments(comments)
0
- return if comments.empty?
0
- meta_match = /^@(\S+)\s*(.*)/
0
- comments = comments.split(/\r?\n/) if comments.is_a? String
0
- @tags, @docstring = [], ""
0
-
0
- indent, last_indent = comments.first[/^\s*/].length, 0
0
- orig_indent = 0
0
- last_line = ""
0
- tag_name, tag_klass, tag_buf, raw_buf = nil, nil, "", []
0
-
0
- (comments+['']).each_with_index do |line, index|
0
- indent = line[/^\s*/].length
0
- empty = (line =~ /^\s*$/ ? true : false)
0
- done = comments.size == index
0
-
0
- if tag_name && (((indent < orig_indent && !empty) || done) ||
0
- (indent <= last_indent && line =~ meta_match))
0
- tagfactory = Tags::Library.new
0
- tag_method = "#{tag_name}_tag"
0
- if tag_name && tagfactory.respond_to?(tag_method)
0
- if tagfactory.method(tag_method).arity == 2
0
- @tags << tagfactory.send(tag_method, tag_buf, raw_buf.join("\n"))
0
- else
0
- @tags << tagfactory.send(tag_method, tag_buf)
0
- end
0
- else
0
- log.warn "Unknown tag @#{tag_name} in documentation for `#{path}`"
0
- end
0
- tag_name, tag_buf, raw_buf = nil, '', []
0
- orig_indent = 0
0
- end
0
-
0
- # Found a meta tag
0
- if line =~ meta_match
0
- orig_indent = indent
0
- tag_name, tag_buf = $1, $2
0
- raw_buf = [tag_buf.dup]
0
- elsif tag_name && indent >= orig_indent && !empty
0
- # Extra data added to the tag on the next line
0
- last_empty = last_line =~ /^[ \t]*$/ ? true : false
0
-
0
- if last_empty
0
- tag_buf << "\n\n"
0
- raw_buf << ''
0
- end
0
-
0
- tag_buf << line.gsub(/^[ \t]{#{indent}}/, last_empty ? '' : ' ')
0
- raw_buf << line.gsub(/^[ \t]{#{orig_indent}}/, '')
0
- elsif !tag_name
0
- # Regular docstring text
0
- @docstring << line << "\n"
0
- end
0
-
0
- last_indent = indent
0
- last_line = line
0
- end
0
-
0
- # Remove trailing/leading whitespace / newlines
0
- @docstring.gsub!(/\A[\r\n\s]+|[\r\n\s]+\Z/, '')
0
- end
0
-
0
       # Formats source code by removing leading indentation
0
       def format_source(source)
0
         source.chomp!
...
30
31
32
33
34
35
36
37
38
39
40
41
 
 
 
 
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
...
97
98
99
100
101
102
103
...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
...
30
31
32
 
 
 
 
 
 
 
 
 
33
34
35
36
37
38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
40
41
...
59
60
61
 
62
63
64
...
98
99
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
102
103
0
@@ -30,50 +30,12 @@ describe YARD::CodeObjects::Base do
0
     o2.docstring.should == "NOT_DOCSTRING"
0
   end
0
   
0
- it "should handle empty docstrings with #short_docstring" do
0
- o1 = ClassObject.new(nil, :Me)
0
- o1.short_docstring.should == ""
0
- end
0
-
0
- it "should return the first sentence with #short_docstring" do
0
- o = ClassObject.new(nil, :Me)
0
- o.docstring = "DOCSTRING. Another sentence"
0
- o.short_docstring.should == "DOCSTRING."
0
+ it "should convert string into Docstring when #docstring= is set" do
0
+ o = ClassObject.new(:root, :Me)
0
+ o.docstring = "DOCSTRING"
0
+ o.docstring.should be_instance_of(Docstring)
0
   end
0
 
0
- it "should return the first paragraph with #short_docstring" do
0
- o = ClassObject.new(nil, :Me)
0
- o.docstring = "DOCSTRING, and other stuff\n\nAnother sentence."
0
- o.short_docstring.should == "DOCSTRING, and other stuff."
0
- end
0
-
0
- it "should return proper short_docstring when docstring is changed" do
0
- o = ClassObject.new(:root, :Me)
0
- o.docstring = "DOCSTRING, and other stuff\n\nAnother sentence."
0
- o.short_docstring.should == "DOCSTRING, and other stuff."
0
- o.docstring = "DOCSTRING."
0
- o.short_docstring.should == "DOCSTRING."
0
- end
0
-
0
- it "should not double the ending period in short_docstring" do
0
- o = ClassObject.new(nil, :Me)
0
- o.docstring = "Returns a list of tags specified by +name+ or all tags if +name+ is not specified.\n\nTest"
0
- o.short_docstring.should == "Returns a list of tags specified by +name+ or all tags if +name+ is not specified."
0
-
0
- Parser::SourceParser.parse_string <<-eof
0
- ##
0
- # Returns a list of tags specified by +name+ or all tags if +name+ is not specified.
0
- #
0
- # @param name the tag name to return data for, or nil for all tags
0
- # @return [Array<Tags::Tag>] the list of tags by the specified tag name
0
- def tags(name = nil)
0
- return @tags if name.nil?
0
- @tags.select {|tag| tag.tag_name.to_s == name.to_s }
0
- end
0
- eof
0
- P('#tags').short_docstring.should == "Returns a list of tags specified by +name+ or all tags if +name+ is not specified."
0
- end
0
-
0
   it "should allow complex name and convert that to namespace" do
0
     obj = CodeObjects::Base.new(nil, "A::B")
0
     obj.namespace.path.should == "A"
0
@@ -97,7 +59,6 @@ describe YARD::CodeObjects::Base do
0
     obj.namespace.should == Registry.root
0
   end
0
   
0
-
0
   it "should not allow any other types as namespace" do
0
     lambda { CodeObjects::Base.new("ROOT!", :Me) }.should raise_error(ArgumentError)
0
   end
0
@@ -137,30 +98,6 @@ describe YARD::CodeObjects::Base do
0
     obj.children.should include(obj2)
0
   end
0
   
0
- it "should parse comments into tags" do
0
- obj = CodeObjects::Base.new(nil, :Object)
0
- comments = <<-eof
0
- @param name Hello world
0
- how are you?
0
- @param name2
0
- this is a new line
0
- @param name3 and this
0
- is a new paragraph:
0
-
0
- right here.
0
- eof
0
- obj.send(:parse_comments, comments)
0
- obj.tags("param").each do |tag|
0
- if tag.name == "name"
0
- tag.text.should == "Hello world how are you?"
0
- elsif tag.name == "name2"
0
- tag.text.should == "this is a new line"
0
- elsif tag.name == "name3"
0
- tag.text.should == "and this is a new paragraph:\n\nright here."
0
- end
0
- end
0
- end
0
-
0
   it "should properly re-indent source starting from 0 indentation" do
0
     obj = CodeObjects::Base.new(nil, :test)
0
     obj.source = <<-eof
...
17
18
19
20
 
21
22
23
...
17
18
19
 
20
21
22
23
0
@@ -17,7 +17,7 @@
0
             <%= rw.values.compact.first.visibility %>
0
           </td>
0
           <td class="docstring">
0
- <%= htmlify rw.values.compact.first.short_docstring %>
0
+ <%= htmlify rw.values.compact.first.docstring.summary %>
0
             <% if rw[:read] && rw[:read].tag(:return) && rw[:read].tag(:return).types %>
0
               <p class='returns'>
0
                 Returns:
...
10
11
12
13
 
14
15
16
...
10
11
12
 
13
14
15
16
0
@@ -10,7 +10,7 @@
0
         <% end %>
0
       </th>
0
       <td class="docstring">
0
- <%= htmlify meth.short_docstring %>
0
+ <%= htmlify meth.docstring.summary %>
0
         <% if meth.tag(:return) && meth.tag(:return).types %>
0
           <p class='returns'>
0
             Returns:
...
11
12
13
14
 
15
16
 
17
18
19
...
11
12
13
 
14
15
 
16
17
18
19
0
@@ -11,9 +11,9 @@
0
           <span class='block'><%= format_block meth %></span>
0
         </tt>
0
         <span class="indent">
0
- <% if meth.short_docstring %>
0
+ <% unless meth.docstring.summary.empty? %>
0
             <br />
0
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<%= meth.short_docstring %>
0
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<%= meth.docstring.summary %>
0
           <% end %>
0
           <% if meth.has_tag?(:deprecated) %>
0
           <br /><strong>Deprecated.</strong> <em><%= meth.tag(:deprecated).text %></em>

Comments

    No one has commented yet.