yard 0.6.8 → 0.7.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.
- data/.yardopts +1 -0
- data/ChangeLog +723 -0
- data/README.md +16 -6
- data/docs/CodeObjects.md +10 -16
- data/docs/GettingStarted.md +232 -32
- data/docs/Glossary.md +1 -2
- data/docs/Handlers.md +10 -16
- data/docs/Overview.md +14 -13
- data/docs/Parser.md +13 -22
- data/docs/Tags.md +209 -16
- data/docs/Templates.md +237 -26
- data/docs/WhatsNew.md +178 -2
- data/lib/yard.rb +13 -10
- data/lib/yard/autoload.rb +22 -18
- data/lib/yard/cli/command.rb +13 -12
- data/lib/yard/cli/command_parser.rb +20 -19
- data/lib/yard/cli/config.rb +19 -19
- data/lib/yard/cli/diff.rb +46 -21
- data/lib/yard/cli/gems.rb +11 -11
- data/lib/yard/cli/graph.rb +13 -13
- data/lib/yard/cli/help.rb +1 -1
- data/lib/yard/cli/list.rb +22 -0
- data/lib/yard/cli/server.rb +17 -17
- data/lib/yard/cli/stats.rb +32 -32
- data/lib/yard/cli/yardoc.rb +181 -135
- data/lib/yard/cli/yri.rb +29 -29
- data/lib/yard/code_objects/base.rb +101 -101
- data/lib/yard/code_objects/class_object.rb +20 -20
- data/lib/yard/code_objects/constant_object.rb +1 -1
- data/lib/yard/code_objects/extended_method_object.rb +5 -5
- data/lib/yard/code_objects/extra_file_object.rb +89 -0
- data/lib/yard/code_objects/macro_object.rb +215 -0
- data/lib/yard/code_objects/method_object.rb +30 -30
- data/lib/yard/code_objects/module_object.rb +1 -1
- data/lib/yard/code_objects/namespace_object.rb +39 -39
- data/lib/yard/code_objects/proxy.rb +38 -38
- data/lib/yard/code_objects/root_object.rb +1 -1
- data/lib/yard/config.rb +40 -40
- data/lib/yard/core_ext/array.rb +2 -2
- data/lib/yard/core_ext/file.rb +11 -11
- data/lib/yard/core_ext/insertion.rb +10 -10
- data/lib/yard/core_ext/module.rb +2 -2
- data/lib/yard/core_ext/string.rb +2 -2
- data/lib/yard/core_ext/symbol_hash.rb +14 -14
- data/lib/yard/docstring.rb +122 -54
- data/lib/yard/globals.rb +2 -2
- data/lib/yard/handlers/base.rb +216 -127
- data/lib/yard/handlers/processor.rb +65 -27
- data/lib/yard/handlers/ruby/alias_handler.rb +6 -3
- data/lib/yard/handlers/ruby/attribute_handler.rb +7 -6
- data/lib/yard/handlers/ruby/base.rb +50 -31
- data/lib/yard/handlers/ruby/class_condition_handler.rb +11 -11
- data/lib/yard/handlers/ruby/class_handler.rb +10 -10
- data/lib/yard/handlers/ruby/class_variable_handler.rb +3 -3
- data/lib/yard/handlers/ruby/constant_handler.rb +7 -7
- data/lib/yard/handlers/ruby/exception_handler.rb +2 -2
- data/lib/yard/handlers/ruby/extend_handler.rb +1 -1
- data/lib/yard/handlers/ruby/legacy/alias_handler.rb +8 -5
- data/lib/yard/handlers/ruby/legacy/attribute_handler.rb +6 -5
- data/lib/yard/handlers/ruby/legacy/base.rb +42 -27
- data/lib/yard/handlers/ruby/legacy/class_condition_handler.rb +9 -9
- data/lib/yard/handlers/ruby/legacy/class_handler.rb +13 -12
- data/lib/yard/handlers/ruby/legacy/class_variable_handler.rb +3 -6
- data/lib/yard/handlers/ruby/legacy/constant_handler.rb +5 -8
- data/lib/yard/handlers/ruby/legacy/exception_handler.rb +1 -1
- data/lib/yard/handlers/ruby/legacy/extend_handler.rb +1 -0
- data/lib/yard/handlers/ruby/legacy/macro_handler.rb +40 -0
- data/lib/yard/handlers/ruby/legacy/method_handler.rb +10 -10
- data/lib/yard/handlers/ruby/legacy/mixin_handler.rb +4 -3
- data/lib/yard/handlers/ruby/legacy/module_handler.rb +2 -1
- data/lib/yard/handlers/ruby/legacy/private_constant_handler.rb +4 -4
- data/lib/yard/handlers/ruby/legacy/visibility_handler.rb +2 -1
- data/lib/yard/handlers/ruby/legacy/yield_handler.rb +3 -3
- data/lib/yard/handlers/ruby/macro_handler.rb +41 -0
- data/lib/yard/handlers/ruby/macro_handler_methods.rb +130 -0
- data/lib/yard/handlers/ruby/method_condition_handler.rb +1 -1
- data/lib/yard/handlers/ruby/method_handler.rb +13 -13
- data/lib/yard/handlers/ruby/mixin_handler.rb +4 -4
- data/lib/yard/handlers/ruby/module_handler.rb +2 -1
- data/lib/yard/handlers/ruby/private_constant_handler.rb +4 -4
- data/lib/yard/handlers/ruby/struct_handler_methods.rb +11 -11
- data/lib/yard/handlers/ruby/visibility_handler.rb +1 -1
- data/lib/yard/handlers/ruby/yield_handler.rb +5 -5
- data/lib/yard/logging.rb +11 -11
- data/lib/yard/parser/base.rb +8 -8
- data/lib/yard/parser/c_parser.rb +42 -33
- data/lib/yard/parser/ruby/ast_node.rb +62 -61
- data/lib/yard/parser/ruby/legacy/ruby_lex.rb +66 -66
- data/lib/yard/parser/ruby/legacy/ruby_parser.rb +4 -4
- data/lib/yard/parser/ruby/legacy/statement.rb +11 -11
- data/lib/yard/parser/ruby/legacy/statement_list.rb +15 -15
- data/lib/yard/parser/ruby/legacy/token_list.rb +9 -9
- data/lib/yard/parser/ruby/ruby_parser.rb +51 -37
- data/lib/yard/parser/source_parser.rb +271 -46
- data/lib/yard/rake/yardoc_task.rb +18 -17
- data/lib/yard/registry.rb +64 -64
- data/lib/yard/registry_store.rb +34 -34
- data/lib/yard/rubygems/backports.rb +8 -0
- data/lib/yard/rubygems/backports/LICENSE.txt +57 -0
- data/lib/yard/rubygems/backports/MIT.txt +20 -0
- data/lib/yard/rubygems/backports/gem.rb +8 -0
- data/lib/yard/rubygems/backports/source_index.rb +353 -0
- data/lib/yard/rubygems/specification.rb +2 -2
- data/lib/yard/serializers/base.rb +20 -20
- data/lib/yard/serializers/file_system_serializer.rb +28 -24
- data/lib/yard/serializers/process_serializer.rb +3 -3
- data/lib/yard/serializers/stdout_serializer.rb +6 -6
- data/lib/yard/serializers/yardoc_serializer.rb +17 -17
- data/lib/yard/server/adapter.rb +12 -12
- data/lib/yard/server/commands/base.rb +26 -26
- data/lib/yard/server/commands/display_file_command.rb +3 -2
- data/lib/yard/server/commands/display_object_command.rb +5 -5
- data/lib/yard/server/commands/frames_command.rb +1 -1
- data/lib/yard/server/commands/library_command.rb +7 -7
- data/lib/yard/server/commands/library_index_command.rb +2 -2
- data/lib/yard/server/commands/list_command.rb +8 -8
- data/lib/yard/server/commands/search_command.rb +8 -8
- data/lib/yard/server/commands/static_file_command.rb +3 -3
- data/lib/yard/server/doc_server_helper.rb +6 -3
- data/lib/yard/server/doc_server_serializer.rb +1 -1
- data/lib/yard/server/library_version.rb +45 -45
- data/lib/yard/server/rack_adapter.rb +10 -10
- data/lib/yard/server/router.rb +28 -28
- data/lib/yard/server/static_caching.rb +5 -5
- data/lib/yard/server/templates/default/fulldoc/html/css/custom.css +3 -3
- data/lib/yard/server/templates/default/fulldoc/html/js/live.js +1 -1
- data/lib/yard/server/templates/default/layout/html/breadcrumb.erb +2 -2
- data/lib/yard/server/templates/default/layout/html/headers.erb +13 -8
- data/lib/yard/server/templates/default/layout/html/setup.rb +7 -0
- data/lib/yard/server/templates/doc_server/full_list/html/full_list.erb +2 -2
- data/lib/yard/server/templates/doc_server/full_list/html/setup.rb +14 -4
- data/lib/yard/server/templates/doc_server/library_list/html/contents.erb +2 -2
- data/lib/yard/server/templates/doc_server/library_list/html/headers.erb +2 -2
- data/lib/yard/server/templates/doc_server/processing/html/processing.erb +1 -1
- data/lib/yard/server/templates/doc_server/search/html/search.erb +1 -1
- data/lib/yard/server/webrick_adapter.rb +2 -2
- data/lib/yard/tags/default_factory.rb +19 -19
- data/lib/yard/tags/default_tag.rb +1 -1
- data/lib/yard/tags/library.rb +68 -63
- data/lib/yard/tags/option_tag.rb +1 -1
- data/lib/yard/tags/overload_tag.rb +9 -9
- data/lib/yard/tags/ref_tag_list.rb +2 -2
- data/lib/yard/tags/tag.rb +7 -7
- data/lib/yard/templates/engine.rb +31 -31
- data/lib/yard/templates/erb_cache.rb +1 -1
- data/lib/yard/templates/helpers/base_helper.rb +46 -32
- data/lib/yard/templates/helpers/filter_helper.rb +2 -2
- data/lib/yard/templates/helpers/html_helper.rb +120 -81
- data/lib/yard/templates/helpers/html_syntax_highlight_helper.rb +4 -4
- data/lib/yard/templates/helpers/markup/rdoc_markup.rb +9 -9
- data/lib/yard/templates/helpers/markup_helper.rb +37 -30
- data/lib/yard/templates/helpers/method_helper.rb +7 -7
- data/lib/yard/templates/helpers/text_helper.rb +7 -7
- data/lib/yard/templates/helpers/uml_helper.rb +3 -3
- data/lib/yard/templates/section.rb +14 -14
- data/lib/yard/templates/template.rb +54 -54
- data/lib/yard/verifier.rb +27 -27
- data/spec/cli/list_spec.rb +8 -0
- data/spec/cli/yardoc_spec.rb +58 -10
- data/spec/code_objects/extra_file_object_spec.rb +132 -0
- data/spec/code_objects/macro_object_spec.rb +154 -0
- data/spec/docstring_spec.rb +90 -0
- data/spec/handlers/base_spec.rb +22 -0
- data/spec/handlers/examples/macro_handler_001.rb.txt +73 -0
- data/spec/handlers/examples/method_handler_001.rb.txt +17 -0
- data/spec/handlers/macro_handler_spec.rb +140 -0
- data/spec/handlers/method_handler_spec.rb +28 -0
- data/spec/handlers/processor_spec.rb +4 -0
- data/spec/handlers/spec_helper.rb +1 -1
- data/spec/parser/c_parser_spec.rb +47 -16
- data/spec/parser/examples/extrafile.c.txt +8 -0
- data/spec/parser/examples/multifile.c.txt +6 -0
- data/spec/parser/ruby/ruby_parser_spec.rb +5 -0
- data/spec/parser/source_parser_spec.rb +235 -0
- data/spec/rake/yardoc_task_spec.rb +22 -17
- data/spec/serializers/file_system_serializer_spec.rb +6 -0
- data/spec/server/commands/library_command_spec.rb +39 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/templates/examples/method001.html +6 -6
- data/spec/templates/examples/method002.html +4 -4
- data/spec/templates/examples/method003.html +10 -10
- data/spec/templates/examples/method005.html +2 -2
- data/spec/templates/examples/module001.dot +2 -0
- data/spec/templates/examples/module001.html +76 -37
- data/spec/templates/examples/module001.txt +1 -1
- data/spec/templates/helpers/base_helper_spec.rb +7 -2
- data/spec/templates/helpers/html_helper_spec.rb +49 -5
- data/spec/templates/helpers/markup_helper_spec.rb +9 -8
- data/spec/templates/module_spec.rb +7 -0
- data/spec/templates/onefile_spec.rb +47 -0
- data/templates/default/fulldoc/html/css/style.css +7 -5
- data/templates/default/fulldoc/html/full_list.erb +13 -10
- data/templates/default/fulldoc/html/full_list_files.erb +1 -1
- data/templates/default/fulldoc/html/js/app.js +16 -14
- data/templates/default/fulldoc/html/js/full_list.js +7 -6
- data/templates/default/fulldoc/html/setup.rb +78 -17
- data/templates/default/layout/html/files.erb +1 -1
- data/templates/default/layout/html/headers.erb +11 -7
- data/templates/default/layout/html/search.erb +4 -4
- data/templates/default/layout/html/setup.rb +28 -8
- data/templates/default/module/html/inherited_attributes.erb +17 -0
- data/templates/default/module/setup.rb +1 -1
- data/templates/default/onefile/html/files.erb +2 -2
- data/templates/default/onefile/html/layout.erb +1 -1
- data/templates/default/onefile/html/setup.rb +7 -5
- data/templates/default/tags/html/option.erb +1 -1
- data/templates/default/tags/html/tag.erb +3 -3
- data/templates/guide/class/html/setup.rb +1 -0
- data/templates/guide/docstring/html/setup.rb +1 -0
- data/templates/guide/fulldoc/html/css/style.css +91 -0
- data/templates/guide/fulldoc/html/js/app.js +33 -0
- data/templates/guide/fulldoc/html/setup.rb +54 -0
- data/templates/guide/layout/html/layout.erb +81 -0
- data/templates/guide/layout/html/setup.rb +24 -0
- data/templates/guide/method/html/header.erb +18 -0
- data/templates/guide/method/html/setup.rb +21 -0
- data/templates/guide/module/html/header.erb +7 -0
- data/templates/guide/module/html/method_list.erb +5 -0
- data/templates/guide/module/html/setup.rb +26 -0
- data/templates/guide/tags/html/setup.rb +8 -0
- metadata +40 -7
- data/lib/yard/handlers/ruby/legacy/process_handler.rb +0 -13
- data/lib/yard/handlers/ruby/process_handler.rb +0 -18
- data/spec/handlers/process_handler_spec.rb +0 -17
data/lib/yard/docstring.rb
CHANGED
@@ -1,45 +1,45 @@
|
|
1
1
|
module YARD
|
2
|
-
# A documentation string, or "docstring" for short, encapsulates the
|
2
|
+
# A documentation string, or "docstring" for short, encapsulates the
|
3
3
|
# comments and metadata, or "tags", of an object. Meta-data is expressed
|
4
4
|
# in the form +@tag VALUE+, where VALUE can span over multiple lines as
|
5
5
|
# long as they are indented. The following +@example+ tag shows how tags
|
6
6
|
# can be indented:
|
7
|
-
#
|
7
|
+
#
|
8
8
|
# # @example My example
|
9
9
|
# # a = "hello world"
|
10
10
|
# # a.reverse
|
11
11
|
# # @version 1.0
|
12
|
-
#
|
13
|
-
# Tags can be nested in a documentation string, though the {Tags::Tag}
|
12
|
+
#
|
13
|
+
# Tags can be nested in a documentation string, though the {Tags::Tag}
|
14
14
|
# itself is responsible for parsing the inner tags.
|
15
15
|
class Docstring < String
|
16
16
|
# @return [Array<Tags::RefTag>] the list of reference tags
|
17
17
|
attr_reader :ref_tags
|
18
|
-
|
18
|
+
|
19
19
|
# @return [CodeObjects::Base] the object that owns the docstring.
|
20
20
|
attr_accessor :object
|
21
|
-
|
21
|
+
|
22
22
|
# @return [Range] line range in the {#object}'s file where the docstring was parsed from
|
23
23
|
attr_accessor :line_range
|
24
|
-
|
24
|
+
|
25
25
|
# @return [String] the raw documentation (including raw tag text)
|
26
26
|
attr_reader :all
|
27
|
-
|
27
|
+
|
28
28
|
# @return [Boolean] whether the docstring was started with "##"
|
29
29
|
attr_reader :hash_flag
|
30
30
|
def hash_flag=(v) @hash_flag = v == nil ? false : v end
|
31
31
|
|
32
32
|
# Matches a tag at the start of a comment line
|
33
33
|
META_MATCH = /^@([a-z_0-9]+)(?:\s+(.*))?$/i
|
34
|
-
|
34
|
+
|
35
35
|
# @group Creating a Docstring Object
|
36
36
|
|
37
37
|
# Creates a new docstring with the raw contents attached to an optional
|
38
38
|
# object.
|
39
|
-
#
|
39
|
+
#
|
40
40
|
# @example
|
41
41
|
# Docstring.new("hello world\n@return Object return", someobj)
|
42
|
-
#
|
42
|
+
#
|
43
43
|
# @param [String] content the raw comments to be parsed into a docstring
|
44
44
|
# and associated meta-data.
|
45
45
|
# @param [CodeObjects::Base] object an object to associate the docstring
|
@@ -48,12 +48,12 @@ module YARD
|
|
48
48
|
@object = object
|
49
49
|
@summary = nil
|
50
50
|
@hash_flag = false
|
51
|
-
|
51
|
+
|
52
52
|
self.all = content
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
# Adds another {Docstring}, copying over tags.
|
56
|
-
#
|
56
|
+
#
|
57
57
|
# @param [Docstring, String] other the other docstring (or string) to
|
58
58
|
# add.
|
59
59
|
# @return [Docstring] a new docstring with both docstrings combines
|
@@ -65,23 +65,41 @@ module YARD
|
|
65
65
|
super
|
66
66
|
end
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
# Replaces the docstring with new raw content. Called by {#all=}.
|
70
70
|
# @param [String] content the raw comments to be parsed
|
71
71
|
def replace(content)
|
72
|
+
content = content.join("\n") if content.is_a?(Array)
|
72
73
|
@tags, @ref_tags = [], []
|
73
74
|
@all = content
|
74
75
|
super parse_comments(content)
|
75
76
|
end
|
76
77
|
alias all= replace
|
78
|
+
|
79
|
+
# Deep-copies a docstring
|
80
|
+
#
|
81
|
+
# @note This method creates a new docstring with new tag lists, but does
|
82
|
+
# not create new individual tags. Modifying the tag objects will still
|
83
|
+
# affect the original tags.
|
84
|
+
# @return [Docstring] a new copied docstring
|
85
|
+
# @since 0.7.0
|
86
|
+
def dup
|
87
|
+
obj = super
|
88
|
+
%w(all summary tags ref_tags).each do |name|
|
89
|
+
val = instance_variable_get("@#{name}")
|
90
|
+
obj.instance_variable_set("@#{name}", val ? val.dup : nil)
|
91
|
+
end
|
92
|
+
obj
|
93
|
+
end
|
77
94
|
|
78
95
|
# @endgroup
|
79
|
-
|
80
|
-
# @return [Fixnum] the first line of the {#line_range}
|
96
|
+
|
97
|
+
# @return [Fixnum] the first line of the {#line_range}
|
98
|
+
# @return [nil] if there is no associated {#line_range}
|
81
99
|
def line
|
82
|
-
line_range.first
|
100
|
+
line_range ? line_range.first : nil
|
83
101
|
end
|
84
|
-
|
102
|
+
|
85
103
|
# Gets the first line of a docstring to the period or the first paragraph.
|
86
104
|
# @return [String] The first line or paragraph of the docstring; always ends with a period.
|
87
105
|
def summary
|
@@ -106,11 +124,64 @@ module YARD
|
|
106
124
|
@summary += '.' unless @summary.empty?
|
107
125
|
@summary
|
108
126
|
end
|
127
|
+
|
128
|
+
# Reformats and returns a raw representation of the tag data using the
|
129
|
+
# current tag and docstring data, not the original text.
|
130
|
+
#
|
131
|
+
# @return [String] the updated raw formatted docstring data
|
132
|
+
# @since 0.7.0
|
133
|
+
# @todo Add Tags::Tag#to_raw and refactor
|
134
|
+
def to_raw
|
135
|
+
tag_data = tags.sort_by {|t| t.tag_name }.map do |tag|
|
136
|
+
case tag
|
137
|
+
when Tags::OverloadTag
|
138
|
+
tag_text = "@#{tag.tag_name} #{tag.signature}\n"
|
139
|
+
unless tag.docstring.blank?
|
140
|
+
tag_text += "\n" + tag.docstring.all.gsub(/\r?\n/, "\n ")
|
141
|
+
end
|
142
|
+
else
|
143
|
+
tag_text = '@' + tag.tag_name
|
144
|
+
tag_text += ' [' + tag.types.join(', ') + ']' if tag.types
|
145
|
+
tag_text += ' ' + tag.name.to_s if tag.name
|
146
|
+
tag_text += "\n " if tag.name && tag.text
|
147
|
+
tag_text += ' ' + tag.text.strip.gsub(/\n/, "\n ") if tag.text
|
148
|
+
end
|
149
|
+
tag_text
|
150
|
+
end
|
151
|
+
[strip, tag_data.join("\n")].reject {|l| l.empty? }.compact.join("\n")
|
152
|
+
end
|
109
153
|
|
110
154
|
# @group Creating and Accessing Meta-data
|
111
|
-
|
112
|
-
#
|
155
|
+
|
156
|
+
# Creates a tag from the {Tags::DefaultFactory tag factory}.
|
157
|
+
#
|
158
|
+
# To add an already created tag object, use {#add_tag}
|
159
|
+
#
|
160
|
+
# @param [String] tag_name the tag name
|
161
|
+
# @param [String] tag_buf the text attached to the tag with newlines removed.
|
162
|
+
# @return [Tags::Tag, Tags::RefTag] a tag
|
163
|
+
def create_tag(tag_name, tag_buf)
|
164
|
+
if tag_buf =~ /\A\s*(?:(\S+)\s+)?\(\s*see\s+(\S+)\s*\)\s*\Z/
|
165
|
+
return create_ref_tag(tag_name, $1, $2)
|
166
|
+
end
|
167
|
+
|
168
|
+
tag_factory = Tags::Library.instance
|
169
|
+
tag_method = "#{tag_name}_tag"
|
170
|
+
if tag_name && tag_factory.respond_to?(tag_method)
|
171
|
+
add_tag(*[tag_factory.send(tag_method, tag_buf)].flatten)
|
172
|
+
else
|
173
|
+
log.warn "Unknown tag @#{tag_name}" + (object ? " in file `#{object.file}` near line #{object.line}" : "")
|
174
|
+
end
|
175
|
+
rescue Tags::TagFormatError
|
176
|
+
log.warn "Invalid tag format for @#{tag_name}" + (object ? " in file `#{object.file}` near line #{object.line}" : "")
|
177
|
+
end
|
178
|
+
|
179
|
+
# Adds a tag or reftag object to the tag list. If you want to parse
|
180
|
+
# tag data based on the {Tags::DefaultFactory} tag factory, use {#create_tag}
|
181
|
+
# instead.
|
182
|
+
#
|
113
183
|
# @param [Tags::Tag, Tags::RefTag] tags list of tag objects to add
|
184
|
+
# @return [void]
|
114
185
|
def add_tag(*tags)
|
115
186
|
tags.each_with_index do |tag, i|
|
116
187
|
case tag
|
@@ -124,7 +195,7 @@ module YARD
|
|
124
195
|
end
|
125
196
|
end
|
126
197
|
end
|
127
|
-
|
198
|
+
|
128
199
|
# Convenience method to return the first tag
|
129
200
|
# object in the list of tag objects of that name
|
130
201
|
#
|
@@ -155,6 +226,24 @@ module YARD
|
|
155
226
|
def has_tag?(name)
|
156
227
|
tags.any? {|tag| tag.tag_name.to_s == name.to_s }
|
157
228
|
end
|
229
|
+
|
230
|
+
# Delete all tags with +name+
|
231
|
+
# @param [String] name the tag name
|
232
|
+
# @return [void]
|
233
|
+
# @since 0.7.0
|
234
|
+
def delete_tags(name)
|
235
|
+
delete_tag_if {|tag| tag.tag_name.to_s == name.to_s }
|
236
|
+
end
|
237
|
+
|
238
|
+
# Deletes all tags where the block returns true
|
239
|
+
# @yieldparam [Tags::Tag] tag the tag that is being tested
|
240
|
+
# @yieldreturn [Boolean] true if the tag should be deleted
|
241
|
+
# @return [void]
|
242
|
+
# @since 0.7.0
|
243
|
+
def delete_tag_if(&block)
|
244
|
+
@tags.delete_if(&block)
|
245
|
+
@ref_tags.delete_if(&block)
|
246
|
+
end
|
158
247
|
|
159
248
|
# Returns true if the docstring has no content that is visible to a template.
|
160
249
|
#
|
@@ -168,51 +257,30 @@ module YARD
|
|
168
257
|
empty? && @tags.empty? && @ref_tags.empty?
|
169
258
|
end
|
170
259
|
end
|
171
|
-
|
260
|
+
|
172
261
|
# @endgroup
|
173
262
|
|
174
263
|
private
|
175
|
-
|
264
|
+
|
176
265
|
# Maps valid reference tags
|
177
|
-
#
|
266
|
+
#
|
178
267
|
# @return [Array<Tags::RefTag>] the list of valid reference tags
|
179
268
|
def convert_ref_tags
|
180
269
|
list = @ref_tags.reject {|t| CodeObjects::Proxy === t.owner }
|
181
270
|
list.map {|t| t.tags }.flatten
|
182
271
|
end
|
183
|
-
|
272
|
+
|
184
273
|
# Creates a {Tags::RefTag}
|
185
274
|
def create_ref_tag(tag_name, name, object_name)
|
186
275
|
@ref_tags << Tags::RefTagList.new(tag_name, P(object, object_name), name)
|
187
276
|
end
|
188
|
-
|
189
|
-
# Creates a tag from the {Tags::DefaultFactory tag factory}.
|
190
|
-
#
|
191
|
-
# @param [String] tag_name the tag name
|
192
|
-
# @param [String] tag_buf the text attached to the tag with newlines removed.
|
193
|
-
# @return [Tags::Tag, Tags::RefTag] a tag
|
194
|
-
def create_tag(tag_name, tag_buf)
|
195
|
-
if tag_buf =~ /\A\s*(?:(\S+)\s+)?\(\s*see\s+(\S+)\s*\)\s*\Z/
|
196
|
-
return create_ref_tag(tag_name, $1, $2)
|
197
|
-
end
|
198
|
-
|
199
|
-
tag_factory = Tags::Library.instance
|
200
|
-
tag_method = "#{tag_name}_tag"
|
201
|
-
if tag_name && tag_factory.respond_to?(tag_method)
|
202
|
-
add_tag(*[tag_factory.send(tag_method, tag_buf)].flatten)
|
203
|
-
else
|
204
|
-
log.warn "Unknown tag @#{tag_name}" + (object ? " in file `#{object.file}` near line #{object.line}" : "")
|
205
|
-
end
|
206
|
-
rescue Tags::TagFormatError
|
207
|
-
log.warn "Invalid tag format for @#{tag_name}" + (object ? " in file `#{object.file}` near line #{object.line}" : "")
|
208
|
-
end
|
209
277
|
|
210
278
|
# Parses out comments split by newlines into a new code object
|
211
279
|
#
|
212
|
-
# @param [String] comments
|
280
|
+
# @param [String] comments
|
213
281
|
# the newline delimited array of comments. If the comments
|
214
|
-
# are passed as a String, they will be split by newlines.
|
215
|
-
#
|
282
|
+
# are passed as a String, they will be split by newlines.
|
283
|
+
#
|
216
284
|
# @return [String] the non-metadata portion of the comments to
|
217
285
|
# be used as a docstring
|
218
286
|
def parse_comments(comments)
|
@@ -226,11 +294,11 @@ module YARD
|
|
226
294
|
tag_name, tag_klass, tag_buf = nil, nil, []
|
227
295
|
|
228
296
|
(comments+['']).each_with_index do |line, index|
|
229
|
-
indent = line[/^\s*/].length
|
297
|
+
indent = line[/^\s*/].length
|
230
298
|
empty = (line =~ /^\s*$/ ? true : false)
|
231
299
|
done = comments.size == index
|
232
300
|
|
233
|
-
if tag_name && (((indent < orig_indent && !empty) || done ||
|
301
|
+
if tag_name && (((indent < orig_indent && !empty) || done ||
|
234
302
|
(indent == 0 && !empty)) || (indent <= last_indent && line =~ META_MATCH))
|
235
303
|
create_tag(tag_name, tag_buf.join("\n"))
|
236
304
|
tag_name, tag_buf, = nil, []
|
@@ -244,12 +312,12 @@ module YARD
|
|
244
312
|
orig_indent = indent if orig_indent == 0
|
245
313
|
# Extra data added to the tag on the next line
|
246
314
|
last_empty = last_line =~ /^[ \t]*$/ ? true : false
|
247
|
-
|
315
|
+
|
248
316
|
tag_buf << '' if last_empty
|
249
317
|
tag_buf << line.gsub(/^[ \t]{#{orig_indent}}/, '')
|
250
318
|
elsif !tag_name
|
251
319
|
# Regular docstring text
|
252
|
-
docstring << line << "\n"
|
320
|
+
docstring << line << "\n"
|
253
321
|
end
|
254
322
|
|
255
323
|
last_indent = indent
|
data/lib/yard/globals.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# @group Global Convenience Methods
|
2
2
|
|
3
3
|
# Shortcut for creating a YARD::CodeObjects::Proxy via a path
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# @see YARD::CodeObjects::Proxy
|
6
6
|
# @see YARD::Registry.resolve
|
7
7
|
def P(namespace, name = nil)
|
@@ -10,7 +10,7 @@ def P(namespace, name = nil)
|
|
10
10
|
end
|
11
11
|
|
12
12
|
# The global {YARD::Logger} instance
|
13
|
-
#
|
13
|
+
#
|
14
14
|
# @return [YARD::Logger] the global {YARD::Logger} instance
|
15
15
|
# @see YARD::Logger
|
16
16
|
def log
|
data/lib/yard/handlers/base.rb
CHANGED
@@ -7,12 +7,12 @@ module YARD
|
|
7
7
|
# The object the error occurred on
|
8
8
|
# @return [CodeObjects::Base] a code object
|
9
9
|
attr_accessor :object
|
10
|
-
|
10
|
+
|
11
11
|
def initialize(object) @object = object end
|
12
12
|
end
|
13
|
-
|
14
|
-
# Handlers are pluggable semantic parsers for YARD's code generation
|
15
|
-
# phase. They allow developers to control what information gets
|
13
|
+
|
14
|
+
# Handlers are pluggable semantic parsers for YARD's code generation
|
15
|
+
# phase. They allow developers to control what information gets
|
16
16
|
# generated by YARD, giving them the ability to, for instance, document
|
17
17
|
# any Ruby DSLs that a customized framework may use. A good example
|
18
18
|
# of this would be the ability to document and generate meta data for
|
@@ -21,45 +21,45 @@ module YARD
|
|
21
21
|
# takes advantage of class level declarations could add these to the
|
22
22
|
# documentation in a very explicit format by treating them as first-
|
23
23
|
# class objects in any outputted documentation.
|
24
|
-
#
|
25
|
-
# == Overview of a Typical Handler Scenario
|
26
|
-
#
|
24
|
+
#
|
25
|
+
# == Overview of a Typical Handler Scenario
|
26
|
+
#
|
27
27
|
# Generally, a handler class will declare a set of statements which
|
28
28
|
# it will handle using the {handles} class declaration. It will then
|
29
29
|
# implement the {#process} method to do the work. The processing would
|
30
|
-
# usually involve the manipulation of the {#namespace}, {#owner}
|
31
|
-
# {CodeObjects::Base code objects} or the creation of new ones, in
|
32
|
-
# which case they should be registered by {#register}, a method that
|
30
|
+
# usually involve the manipulation of the {#namespace}, {#owner}
|
31
|
+
# {CodeObjects::Base code objects} or the creation of new ones, in
|
32
|
+
# which case they should be registered by {#register}, a method that
|
33
33
|
# sets some basic attributes for the new objects.
|
34
|
-
#
|
34
|
+
#
|
35
35
|
# Handlers are usually simple and take up to a page of code to process
|
36
36
|
# and register a new object or add new attributes to the current +namespace+.
|
37
|
-
#
|
38
|
-
# == Setting up a Handler for Use
|
39
|
-
#
|
37
|
+
#
|
38
|
+
# == Setting up a Handler for Use
|
39
|
+
#
|
40
40
|
# A Handler is automatically registered when it is subclassed from the
|
41
41
|
# base class. The only other thing that needs to be done is to specify
|
42
42
|
# which statement the handler will process. This is done with the +handles+
|
43
43
|
# declaration, taking either a {Parser::Ruby::Legacy::RubyToken}, {String} or `Regexp`.
|
44
44
|
# Here is a simple example which processes module statements.
|
45
|
-
#
|
45
|
+
#
|
46
46
|
# class MyModuleHandler < YARD::Handlers::Base
|
47
47
|
# handles TkMODULE
|
48
|
-
#
|
48
|
+
#
|
49
49
|
# def process
|
50
50
|
# # do something
|
51
51
|
# end
|
52
52
|
# end
|
53
|
-
#
|
54
|
-
# == Processing Handler Data
|
55
|
-
#
|
56
|
-
# The goal of a specific handler is really up to the developer, and as
|
53
|
+
#
|
54
|
+
# == Processing Handler Data
|
55
|
+
#
|
56
|
+
# The goal of a specific handler is really up to the developer, and as
|
57
57
|
# such there is no real guideline on how to process the data. However,
|
58
58
|
# it is important to know where the data is coming from to be able to use
|
59
59
|
# it.
|
60
|
-
#
|
61
|
-
# === +statement+ Attribute
|
62
|
-
#
|
60
|
+
#
|
61
|
+
# === +statement+ Attribute
|
62
|
+
#
|
63
63
|
# The +statement+ attribute pertains to the {Parser::Ruby::Legacy::Statement} object
|
64
64
|
# containing a set of tokens parsed in by the parser. This is the main set
|
65
65
|
# of data to be analyzed and processed. The comments attached to the statement
|
@@ -67,71 +67,71 @@ module YARD
|
|
67
67
|
# the data to be processed will live in the +tokens+ attribute. This list
|
68
68
|
# can be converted to a +String+ using +#to_s+ to parse the data with
|
69
69
|
# regular expressions (or other text processing mechanisms), if needed.
|
70
|
-
#
|
71
|
-
# === +namespace+ Attribute
|
72
|
-
#
|
73
|
-
# The +namespace+ attribute is a {CodeObjects::NamespaceObject namespace object}
|
70
|
+
#
|
71
|
+
# === +namespace+ Attribute
|
72
|
+
#
|
73
|
+
# The +namespace+ attribute is a {CodeObjects::NamespaceObject namespace object}
|
74
74
|
# which represents the current namespace that the parser is in. For instance:
|
75
|
-
#
|
75
|
+
#
|
76
76
|
# module SomeModule
|
77
77
|
# class MyClass
|
78
78
|
# def mymethod; end
|
79
79
|
# end
|
80
80
|
# end
|
81
|
-
#
|
81
|
+
#
|
82
82
|
# If a handler was to parse the 'class MyClass' statement, it would
|
83
83
|
# be necessary to know that it belonged inside the SomeModule module.
|
84
84
|
# This is the value that +namespace+ would return when processing such
|
85
85
|
# a statement. If the class was then entered and another handler was
|
86
86
|
# called on the method, the +namespace+ would be set to the 'MyClass'
|
87
87
|
# code object.
|
88
|
-
#
|
89
|
-
# === +owner+ Attribute
|
90
|
-
#
|
88
|
+
#
|
89
|
+
# === +owner+ Attribute
|
90
|
+
#
|
91
91
|
# The +owner+ attribute is similar to the +namespace+ attribute in that
|
92
92
|
# it also follows the scope of the code during parsing. However, a namespace
|
93
93
|
# object is loosely defined as a module or class and YARD has the ability
|
94
94
|
# to parse beyond module and class blocks (inside methods, for instance),
|
95
|
-
# so the +owner+ attribute would not be limited to modules and classes.
|
96
|
-
#
|
95
|
+
# so the +owner+ attribute would not be limited to modules and classes.
|
96
|
+
#
|
97
97
|
# To put this into context, the example from above will be used. If a method
|
98
98
|
# handler was added to the mix and decided to parse inside the method body,
|
99
99
|
# the +owner+ would be set to the method object but the namespace would remain
|
100
100
|
# set to the class. This would allow the developer to process any method
|
101
101
|
# definitions set inside a method (def x; def y; 2 end end) by adding them
|
102
102
|
# to the correct namespace (the class, not the method).
|
103
|
-
#
|
103
|
+
#
|
104
104
|
# In summary, the distinction between +namespace+ and +owner+ can be thought
|
105
105
|
# of as the difference between first-class Ruby objects (namespaces) and
|
106
106
|
# second-class Ruby objects (methods).
|
107
|
-
#
|
108
|
-
# === +visibility+ and +scope+ Attributes
|
109
|
-
#
|
107
|
+
#
|
108
|
+
# === +visibility+ and +scope+ Attributes
|
109
|
+
#
|
110
110
|
# Mainly needed for parsing methods, the +visibility+ and +scope+ attributes
|
111
111
|
# refer to the public/protected/private and class/instance values (respectively)
|
112
112
|
# of the current parsing position.
|
113
|
-
#
|
114
|
-
# == Parsing Blocks in Statements
|
115
|
-
#
|
113
|
+
#
|
114
|
+
# == Parsing Blocks in Statements
|
115
|
+
#
|
116
116
|
# In addition to parsing a statement and creating new objects, some
|
117
117
|
# handlers may wish to continue parsing the code inside the statement's
|
118
118
|
# block (if there is one). In this context, a block means the inside
|
119
119
|
# of any statement, be it class definition, module definition, if
|
120
|
-
# statement or classic 'Ruby block'.
|
121
|
-
#
|
122
|
-
# For example, a class statement would be "class MyClass" and the block
|
123
|
-
# would be a list of statements including the method definitions inside
|
124
|
-
# the class. For a class handler, the programmer would execute the
|
125
|
-
# {#parse_block} method to continue parsing code inside the block, with
|
126
|
-
# the +namespace+ now pointing to the class object the handler created.
|
127
|
-
#
|
128
|
-
# YARD has the ability to continue into any block: class, module, method,
|
129
|
-
# even if statements. For this reason, the block parsing method must be
|
120
|
+
# statement or classic 'Ruby block'.
|
121
|
+
#
|
122
|
+
# For example, a class statement would be "class MyClass" and the block
|
123
|
+
# would be a list of statements including the method definitions inside
|
124
|
+
# the class. For a class handler, the programmer would execute the
|
125
|
+
# {#parse_block} method to continue parsing code inside the block, with
|
126
|
+
# the +namespace+ now pointing to the class object the handler created.
|
127
|
+
#
|
128
|
+
# YARD has the ability to continue into any block: class, module, method,
|
129
|
+
# even if statements. For this reason, the block parsing method must be
|
130
130
|
# invoked explicitly out of efficiency sake.
|
131
|
-
#
|
131
|
+
#
|
132
132
|
# @abstract Subclass this class to provide a handler for YARD to use
|
133
133
|
# during the processing phase.
|
134
|
-
#
|
134
|
+
#
|
135
135
|
# @see CodeObjects::Base
|
136
136
|
# @see CodeObjects::NamespaceObject
|
137
137
|
# @see handles
|
@@ -139,20 +139,20 @@ module YARD
|
|
139
139
|
# @see #owner
|
140
140
|
# @see #register
|
141
141
|
# @see #parse_block
|
142
|
-
class Base
|
143
|
-
# For accessing convenience, eg. "MethodObject"
|
142
|
+
class Base
|
143
|
+
# For accessing convenience, eg. "MethodObject"
|
144
144
|
# instead of the full qualified namespace
|
145
145
|
include YARD::CodeObjects
|
146
|
-
|
146
|
+
|
147
147
|
include Parser
|
148
|
-
|
148
|
+
|
149
149
|
class << self
|
150
150
|
# Clear all registered subclasses. Testing purposes only
|
151
|
-
# @return [void]
|
151
|
+
# @return [void]
|
152
152
|
def clear_subclasses
|
153
153
|
@@subclasses = []
|
154
154
|
end
|
155
|
-
|
155
|
+
|
156
156
|
# Returns all registered handler subclasses.
|
157
157
|
# @return [Array<Base>] a list of handlers
|
158
158
|
def subclasses
|
@@ -165,70 +165,70 @@ module YARD
|
|
165
165
|
end
|
166
166
|
|
167
167
|
# Declares the statement type which will be processed
|
168
|
-
# by this handler.
|
169
|
-
#
|
168
|
+
# by this handler.
|
169
|
+
#
|
170
170
|
# A match need not be unique to a handler. Multiple
|
171
171
|
# handlers can process the same statement. However,
|
172
172
|
# in this case, care should be taken to make sure that
|
173
173
|
# {#parse_block} would only be executed by one of
|
174
174
|
# the handlers, otherwise the same code will be parsed
|
175
175
|
# multiple times and slow YARD down.
|
176
|
-
#
|
176
|
+
#
|
177
177
|
# @param [Parser::RubyToken, Symbol, String, Regexp] matches
|
178
178
|
# statements that match the declaration will be
|
179
|
-
# processed by this handler. A {String} match is
|
180
|
-
# equivalent to a +/\Astring/+ regular expression
|
181
|
-
# (match from the beginning of the line), and all
|
179
|
+
# processed by this handler. A {String} match is
|
180
|
+
# equivalent to a +/\Astring/+ regular expression
|
181
|
+
# (match from the beginning of the line), and all
|
182
182
|
# token matches match only the first token of the
|
183
183
|
# statement.
|
184
|
-
#
|
184
|
+
#
|
185
185
|
def handles(*matches)
|
186
186
|
(@handlers ||= []).push(*matches)
|
187
187
|
end
|
188
|
-
|
188
|
+
|
189
189
|
# This class is implemented by {Ruby::Base} and {Ruby::Legacy::Base}.
|
190
190
|
# To implement a base handler class for another language, implement
|
191
191
|
# this method to return true if the handler should process the given
|
192
192
|
# statement object. Use {handlers} to enumerate the matchers declared
|
193
193
|
# for the handler class.
|
194
|
-
#
|
194
|
+
#
|
195
195
|
# @param statement a statement object or node (depends on language type)
|
196
196
|
# @return [Boolean] whether or not this handler object should process
|
197
197
|
# the given statement
|
198
198
|
def handles?(statement)
|
199
199
|
raise NotImplementedError, "override #handles? in a subclass"
|
200
200
|
end
|
201
|
-
|
201
|
+
|
202
202
|
# @return [Array] a list of matchers for the handler object.
|
203
203
|
# @see handles?
|
204
204
|
def handlers
|
205
205
|
@handlers ||= []
|
206
206
|
end
|
207
|
-
|
207
|
+
|
208
208
|
# Declares that the handler should only be called when inside a
|
209
209
|
# {CodeObjects::NamespaceObject}, not a method body.
|
210
|
-
#
|
210
|
+
#
|
211
211
|
# @return [void]
|
212
212
|
def namespace_only
|
213
213
|
@namespace_only = true
|
214
214
|
end
|
215
|
-
|
215
|
+
|
216
216
|
# @return [Boolean] whether the handler should only be processed inside
|
217
217
|
# a namespace.
|
218
218
|
def namespace_only?
|
219
219
|
(@namespace_only ||= false) ? true : false
|
220
220
|
end
|
221
|
-
|
221
|
+
|
222
222
|
# Declares that a handler should only be called when inside a filename
|
223
223
|
# by its basename or a regex match for the full path.
|
224
|
-
#
|
224
|
+
#
|
225
225
|
# @param [String, Regexp] filename a matching filename or regex
|
226
226
|
# @return [void]
|
227
227
|
# @since 0.6.2
|
228
228
|
def in_file(filename)
|
229
229
|
(@in_files ||= []) << filename
|
230
230
|
end
|
231
|
-
|
231
|
+
|
232
232
|
# @return [Boolean] whether the filename matches the declared file
|
233
233
|
# match for a handler. If no file match is specified, returns true.
|
234
234
|
# @since 0.6.2
|
@@ -245,12 +245,16 @@ module YARD
|
|
245
245
|
end
|
246
246
|
end
|
247
247
|
end
|
248
|
-
|
248
|
+
|
249
249
|
# Generates a +process+ method, equivalent to +def process; ... end+.
|
250
250
|
# Blocks defined with this syntax will be wrapped inside an anonymous
|
251
251
|
# module so that the handler class can be extended with mixins that
|
252
252
|
# override the +process+ method without alias chaining.
|
253
|
-
#
|
253
|
+
#
|
254
|
+
# @macro yard.handlers.process
|
255
|
+
# @method process
|
256
|
+
# Main processing callback
|
257
|
+
# @return [void]
|
254
258
|
# @see #process
|
255
259
|
# @return [void]
|
256
260
|
# @since 0.5.4
|
@@ -268,57 +272,63 @@ module YARD
|
|
268
272
|
|
269
273
|
# The main handler method called by the parser on a statement
|
270
274
|
# that matches the {handles} declaration.
|
271
|
-
#
|
275
|
+
#
|
272
276
|
# Subclasses should override this method to provide the handling
|
273
|
-
# functionality for the class.
|
274
|
-
#
|
277
|
+
# functionality for the class.
|
278
|
+
#
|
275
279
|
# @return [Array<CodeObjects::Base>, CodeObjects::Base, Object]
|
276
280
|
# If this method returns a code object (or a list of them),
|
277
281
|
# they are passed to the +#register+ method which adds basic
|
278
282
|
# attributes. It is not necessary to return any objects and in
|
279
283
|
# some cases you may want to explicitly avoid the returning of
|
280
284
|
# any objects for post-processing by the register method.
|
281
|
-
#
|
285
|
+
#
|
282
286
|
# @see handles
|
283
287
|
# @see #register
|
284
|
-
#
|
288
|
+
#
|
285
289
|
def process
|
286
290
|
raise NotImplementedError, "#{self} did not implement a #process method for handling."
|
287
291
|
end
|
288
|
-
|
292
|
+
|
289
293
|
# Parses the semantic "block" contained in the statement node.
|
290
|
-
#
|
294
|
+
#
|
291
295
|
# @abstract Subclasses should call {Processor#process parser.process}
|
292
296
|
def parse_block(*args)
|
293
297
|
raise NotImplementedError, "#{self} did not implement a #parse_block method for handling"
|
294
298
|
end
|
295
|
-
|
299
|
+
|
296
300
|
protected
|
297
|
-
|
298
|
-
# @return [Processor] the processor object that manages all global state
|
301
|
+
|
302
|
+
# @return [Processor] the processor object that manages all global state
|
299
303
|
# during handling.
|
300
304
|
attr_reader :parser
|
301
|
-
|
305
|
+
|
302
306
|
# @return [Object] the statement object currently being processed. Usually
|
303
307
|
# refers to one semantic language statement, though the strict definition
|
304
308
|
# depends on the parser used.
|
305
309
|
attr_reader :statement
|
306
|
-
|
310
|
+
|
307
311
|
# (see Processor#owner)
|
308
312
|
attr_accessor :owner
|
309
|
-
|
313
|
+
|
310
314
|
# (see Processor#namespace)
|
311
315
|
attr_accessor :namespace
|
312
|
-
|
316
|
+
|
313
317
|
# (see Processor#visibility)
|
314
318
|
attr_accessor :visibility
|
315
|
-
|
319
|
+
|
316
320
|
# (see Processor#scope)
|
317
321
|
attr_accessor :scope
|
322
|
+
|
323
|
+
# (see Processor#globals)
|
324
|
+
attr_reader :globals
|
325
|
+
|
326
|
+
# (see Processor#extra_state)
|
327
|
+
attr_reader :extra_state
|
318
328
|
|
319
329
|
undef owner, owner=, namespace, namespace=
|
320
330
|
undef visibility, visibility=, scope, scope=
|
321
|
-
|
331
|
+
|
322
332
|
def owner; parser.owner end
|
323
333
|
def owner=(v) parser.owner=(v) end
|
324
334
|
def namespace; parser.namespace end
|
@@ -327,17 +337,19 @@ module YARD
|
|
327
337
|
def visibility=(v); parser.visibility=(v) end
|
328
338
|
def scope; parser.scope end
|
329
339
|
def scope=(v); parser.scope=(v) end
|
330
|
-
|
340
|
+
def globals; parser.globals end
|
341
|
+
def extra_state; parser.extra_state end
|
342
|
+
|
331
343
|
# Executes a given block with specific state values for {#owner},
|
332
344
|
# {#namespace} and {#scope}.
|
333
|
-
#
|
345
|
+
#
|
334
346
|
# @param [Proc] block the block to execute with specific state
|
335
|
-
# @option opts [CodeObjects::NamespaceObject] :namespace (value of #namespace)
|
347
|
+
# @option opts [CodeObjects::NamespaceObject] :namespace (value of #namespace)
|
336
348
|
# the namespace object that {#namespace} will be equal to for the
|
337
|
-
# duration of the block.
|
338
|
-
# @option opts [Symbol] :scope (:instance)
|
349
|
+
# duration of the block.
|
350
|
+
# @option opts [Symbol] :scope (:instance)
|
339
351
|
# the scope for the duration of the block.
|
340
|
-
# @option opts [CodeObjects::Base] :owner (value of #owner)
|
352
|
+
# @option opts [CodeObjects::Base] :owner (value of #owner)
|
341
353
|
# the owner object (method) for the duration of the block
|
342
354
|
# @yield a block to execute with the given state values.
|
343
355
|
def push_state(opts = {}, &block)
|
@@ -360,43 +372,52 @@ module YARD
|
|
360
372
|
self.scope = sc
|
361
373
|
self.owner = oo
|
362
374
|
end
|
363
|
-
|
364
|
-
# Do some post processing on a list of code objects.
|
365
|
-
# Adds basic attributes to the list of objects like
|
375
|
+
|
376
|
+
# Do some post processing on a list of code objects.
|
377
|
+
# Adds basic attributes to the list of objects like
|
366
378
|
# the filename, line number, {CodeObjects::Base#dynamic},
|
367
379
|
# source code and {CodeObjects::Base#docstring},
|
368
380
|
# but only if they don't exist.
|
369
|
-
#
|
381
|
+
#
|
370
382
|
# @param [Array<CodeObjects::Base>] objects
|
371
383
|
# the list of objects to post-process.
|
372
|
-
#
|
384
|
+
#
|
373
385
|
# @return [CodeObjects::Base, Array<CodeObjects::Base>]
|
374
386
|
# returns whatever is passed in, for chainability.
|
375
|
-
#
|
387
|
+
#
|
376
388
|
def register(*objects)
|
377
389
|
objects.flatten.each do |object|
|
378
390
|
next unless object.is_a?(CodeObjects::Base)
|
379
|
-
|
391
|
+
|
380
392
|
begin
|
381
393
|
ensure_loaded!(object.namespace)
|
382
394
|
object.namespace.children << object
|
383
395
|
rescue NamespaceMissingError
|
384
396
|
end
|
385
|
-
|
397
|
+
|
386
398
|
# Yield the object to the calling block because ruby will parse the syntax
|
387
|
-
#
|
399
|
+
#
|
388
400
|
# register obj = ClassObject.new {|o| ... }
|
389
|
-
#
|
401
|
+
#
|
390
402
|
# as the block for #register. We need to make sure this gets to the object.
|
391
|
-
yield(object) if block_given?
|
392
|
-
|
403
|
+
yield(object) if block_given?
|
404
|
+
|
393
405
|
object.add_file(parser.file, statement.line, statement.comments)
|
394
406
|
|
395
407
|
# Add docstring if there is one.
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
408
|
+
if statement.comments
|
409
|
+
object.docstring = Docstring.new(statement.comments, object)
|
410
|
+
end
|
411
|
+
|
412
|
+
# Expand/create any @macro tags
|
413
|
+
expand_macro(object, find_or_create_macro(object))
|
414
|
+
|
415
|
+
# Add hash_flag/line_range
|
416
|
+
if statement.comments
|
417
|
+
object.docstring.hash_flag = statement.comments_hash_flag
|
418
|
+
object.docstring.line_range = statement.comments_range
|
419
|
+
end
|
420
|
+
|
400
421
|
# Add group information
|
401
422
|
if statement.group
|
402
423
|
unless object.namespace.is_a?(Proxy)
|
@@ -404,7 +425,7 @@ module YARD
|
|
404
425
|
end
|
405
426
|
object.group = statement.group
|
406
427
|
end
|
407
|
-
|
428
|
+
|
408
429
|
# Add transitive tags
|
409
430
|
Tags::Library.transitive_tags.each do |tag|
|
410
431
|
next if object.namespace.is_a?(Proxy)
|
@@ -412,12 +433,12 @@ module YARD
|
|
412
433
|
next if object.has_tag?(tag)
|
413
434
|
object.docstring.add_tag(*object.namespace.tags(tag))
|
414
435
|
end
|
415
|
-
|
436
|
+
|
416
437
|
# Add source only to non-class non-module objects
|
417
438
|
unless object.is_a?(NamespaceObject)
|
418
439
|
object.source ||= statement
|
419
440
|
end
|
420
|
-
|
441
|
+
|
421
442
|
# Make it dynamic if its owner is not its namespace.
|
422
443
|
# This generally means it was defined in a method (or block of some sort)
|
423
444
|
object.dynamic = true if owner != namespace
|
@@ -428,17 +449,17 @@ module YARD
|
|
428
449
|
# Ensures that a specific +object+ has been parsed and loaded into the
|
429
450
|
# registry. This is necessary when adding data to a namespace, for instance,
|
430
451
|
# since the namespace may not have been processed yet (it can be located
|
431
|
-
# in a file that has not been handled).
|
432
|
-
#
|
433
|
-
# Calling this method defers the handler until all other files have been
|
452
|
+
# in a file that has not been handled).
|
453
|
+
#
|
454
|
+
# Calling this method defers the handler until all other files have been
|
434
455
|
# processed. If the object gets resolved, the rest of the handler continues,
|
435
456
|
# otherwise an exception is raised.
|
436
|
-
#
|
457
|
+
#
|
437
458
|
# @example Adding a mixin to the String class programmatically
|
438
459
|
# ensure_loaded! P('String')
|
439
460
|
# # "String" is now guaranteed to be loaded
|
440
461
|
# P('String').mixins << P('MyMixin')
|
441
|
-
#
|
462
|
+
#
|
442
463
|
# @param [Proxy, CodeObjects::Base] object the object to resolve.
|
443
464
|
# @param [Integer] max_retries the number of times to defer the handler
|
444
465
|
# before raising a +NamespaceMissingError+.
|
@@ -455,7 +476,7 @@ module YARD
|
|
455
476
|
nil
|
456
477
|
end
|
457
478
|
end
|
458
|
-
|
479
|
+
|
459
480
|
unless CONTINUATIONS_SUPPORTED
|
460
481
|
unless $NO_CONTINUATION_WARNING
|
461
482
|
$NO_CONTINUATION_WARNING = true
|
@@ -464,11 +485,11 @@ module YARD
|
|
464
485
|
end
|
465
486
|
raise NamespaceMissingError, object
|
466
487
|
end
|
467
|
-
|
488
|
+
|
468
489
|
retries = 0
|
469
490
|
context = callcc {|c| c }
|
470
|
-
retries += 1
|
471
|
-
|
491
|
+
retries += 1
|
492
|
+
|
472
493
|
if object.is_a?(Proxy)
|
473
494
|
if retries <= max_retries
|
474
495
|
log.debug "Missing object #{object} in file `#{parser.file}', moving it to the back of the line."
|
@@ -479,6 +500,74 @@ module YARD
|
|
479
500
|
end
|
480
501
|
object
|
481
502
|
end
|
503
|
+
|
504
|
+
# @group Macro Support
|
505
|
+
|
506
|
+
# @abstract Implement this method to return the parameters in a method call
|
507
|
+
# statement. It should return an empty list if the statement is not a
|
508
|
+
# method call.
|
509
|
+
# @return [Array<String>] a list of argument names
|
510
|
+
def call_params
|
511
|
+
raise NotImplementedError
|
512
|
+
end
|
513
|
+
|
514
|
+
# @abstract Implement this method to return the method being called in
|
515
|
+
# a method call. It should return nil if the statement is not a method
|
516
|
+
# call.
|
517
|
+
# @return [String] the method name being called
|
518
|
+
# @return [nil] if the statement is not a method call
|
519
|
+
def caller_method
|
520
|
+
raise NotImplementedError
|
521
|
+
end
|
522
|
+
|
523
|
+
# Attempts to find or create a macro if a +@macro+ tag is found in the
|
524
|
+
# docstring (or the object's docstring).
|
525
|
+
#
|
526
|
+
# @param [Docstring, CodeObjects::Base] object_or_docstring the docstring
|
527
|
+
# or it's object with which to check for a macro
|
528
|
+
# @return [CodeObjects::MacroObject] the newly created macro
|
529
|
+
# @return [nil] if the docstring does not create or reference a macro
|
530
|
+
def find_or_create_macro(object_or_docstring)
|
531
|
+
if object_or_docstring.is_a?(Docstring)
|
532
|
+
object, docstring = nil, object_or_docstring
|
533
|
+
else
|
534
|
+
object, docstring = object_or_docstring, object_or_docstring.docstring
|
535
|
+
end
|
536
|
+
return unless macro_tag = docstring.tag(:macro)
|
537
|
+
unless macro_tag.name
|
538
|
+
if object
|
539
|
+
log.warn "Invalid/missing macro name for #{object.path} (#{parser.file}:#{statement.line})"
|
540
|
+
return nil
|
541
|
+
else
|
542
|
+
raise UndocumentableError, 'method/attribute, missing macro name'
|
543
|
+
end
|
544
|
+
end
|
545
|
+
caller_obj = caller_method ? P(namespace, caller_method) : nil
|
546
|
+
if macro = MacroObject.find_or_create(docstring, caller_obj)
|
547
|
+
attached_method_name = caller_method
|
548
|
+
if object && object.is_a?(MethodObject) && object.scope == :class
|
549
|
+
macro.method_object = object
|
550
|
+
attached_method_name = object.name.to_s
|
551
|
+
end
|
552
|
+
if macro.attached?
|
553
|
+
globals.__attached_macros ||= {}
|
554
|
+
globals.__attached_macros[attached_method_name] ||= []
|
555
|
+
globals.__attached_macros[attached_method_name] |= [macro]
|
556
|
+
end
|
557
|
+
end
|
558
|
+
macro
|
559
|
+
end
|
560
|
+
|
561
|
+
# Sets the docstring on +object+ to the expanded macro.
|
562
|
+
# @param [CodeObjects::Base] object the object to expand the macro on
|
563
|
+
# @param [CodeObjects::MacroObject] macro the macro object to expand
|
564
|
+
# @return [void]
|
565
|
+
def expand_macro(object, macro)
|
566
|
+
return unless macro
|
567
|
+
all_params = ([caller_method] + call_params).compact
|
568
|
+
data = MacroObject.apply_macro(macro, object.docstring, all_params, statement.source)
|
569
|
+
object.docstring = Docstring.new(data, object)
|
570
|
+
end
|
482
571
|
end
|
483
572
|
end
|
484
573
|
end
|