rdoc 8.0.0 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +1 -3
- data/RI.md +75 -75
- data/exe/rdoc +2 -2
- data/lib/rdoc/code_object/alias.rb +71 -69
- data/lib/rdoc/code_object/any_method.rb +305 -303
- data/lib/rdoc/code_object/attr.rb +150 -148
- data/lib/rdoc/code_object/class_module.rb +798 -792
- data/lib/rdoc/code_object/constant.rb +175 -173
- data/lib/rdoc/code_object/context/section.rb +142 -138
- data/lib/rdoc/code_object/context.rb +926 -958
- data/lib/rdoc/code_object/extend.rb +7 -5
- data/lib/rdoc/code_object/include.rb +7 -5
- data/lib/rdoc/code_object/method_attr.rb +326 -319
- data/lib/rdoc/code_object/mixin.rb +97 -95
- data/lib/rdoc/code_object/normal_class.rb +77 -78
- data/lib/rdoc/code_object/normal_module.rb +61 -59
- data/lib/rdoc/code_object/require.rb +23 -39
- data/lib/rdoc/code_object/single_class.rb +21 -19
- data/lib/rdoc/code_object/top_level.rb +212 -219
- data/lib/rdoc/code_object.rb +305 -303
- data/lib/rdoc/comment.rb +275 -273
- data/lib/rdoc/cross_reference.rb +192 -190
- data/lib/rdoc/encoding.rb +105 -103
- data/lib/rdoc/erb_partial.rb +13 -11
- data/lib/rdoc/erbio.rb +29 -27
- data/lib/rdoc/generator/aliki.rb +161 -153
- data/lib/rdoc/generator/darkfish.rb +645 -635
- data/lib/rdoc/generator/json_index.rb +233 -229
- data/lib/rdoc/generator/markup.rb +164 -146
- data/lib/rdoc/generator/pot/message_extractor.rb +57 -51
- data/lib/rdoc/generator/pot/po.rb +52 -51
- data/lib/rdoc/generator/pot/po_entry.rb +138 -132
- data/lib/rdoc/generator/pot.rb +85 -81
- data/lib/rdoc/generator/ri.rb +23 -19
- data/lib/rdoc/generator/template/aliki/DESIGN.md +6 -4
- data/lib/rdoc/generator/template/aliki/_footer.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/_head.rhtml +10 -10
- data/lib/rdoc/generator/template/aliki/_header.rhtml +29 -44
- data/lib/rdoc/generator/template/aliki/_sidebar_search.rhtml +4 -4
- data/lib/rdoc/generator/template/aliki/css/rdoc.css +207 -178
- data/lib/rdoc/generator/template/aliki/js/aliki.js +60 -84
- data/lib/rdoc/generator/template/darkfish/_footer.rhtml +1 -1
- data/lib/rdoc/generator.rb +48 -46
- data/lib/rdoc/i18n/locale.rb +99 -95
- data/lib/rdoc/i18n/text.rb +109 -105
- data/lib/rdoc/i18n.rb +7 -5
- data/lib/rdoc/markdown/byte_runtime.rb +80 -0
- data/lib/rdoc/markdown.kpeg +15 -11
- data/lib/rdoc/markdown.rb +40 -47
- data/lib/rdoc/markup/block_quote.rb +12 -8
- data/lib/rdoc/markup/document.rb +127 -123
- data/lib/rdoc/markup/formatter.rb +219 -215
- data/lib/rdoc/markup/include.rb +33 -29
- data/lib/rdoc/markup/indented_paragraph.rb +37 -33
- data/lib/rdoc/markup/inline_parser.rb +281 -277
- data/lib/rdoc/markup/list.rb +80 -88
- data/lib/rdoc/markup/list_item.rb +73 -85
- data/lib/rdoc/markup/paragraph.rb +23 -19
- data/lib/rdoc/markup/parser.rb +501 -497
- data/lib/rdoc/markup/pre_process.rb +283 -279
- data/lib/rdoc/markup/raw.rb +2 -2
- data/lib/rdoc/markup/rule.rb +16 -12
- data/lib/rdoc/markup/to_ansi.rb +143 -139
- data/lib/rdoc/markup/to_bs.rb +72 -68
- data/lib/rdoc/markup/to_html.rb +594 -565
- data/lib/rdoc/markup/to_html_crossref.rb +234 -230
- data/lib/rdoc/markup/to_html_snippet.rb +232 -227
- data/lib/rdoc/markup/to_joined_paragraph.rb +36 -32
- data/lib/rdoc/markup/to_label.rb +63 -59
- data/lib/rdoc/markup/to_markdown.rb +212 -208
- data/lib/rdoc/markup/to_rdoc.rb +336 -332
- data/lib/rdoc/markup/to_table_of_contents.rb +66 -62
- data/lib/rdoc/markup/to_test.rb +60 -56
- data/lib/rdoc/markup/to_tt_only.rb +84 -80
- data/lib/rdoc/markup/verbatim.rb +62 -58
- data/lib/rdoc/markup.rb +198 -196
- data/lib/rdoc/options.rb +1063 -1061
- data/lib/rdoc/parser/c.rb +1039 -1037
- data/lib/rdoc/parser/changelog.rb +319 -315
- data/lib/rdoc/parser/markdown.rb +17 -13
- data/lib/rdoc/parser/rbs.rb +239 -235
- data/lib/rdoc/parser/rd.rb +17 -13
- data/lib/rdoc/parser/ruby.rb +1245 -1124
- data/lib/rdoc/parser/ruby_colorizer.rb +263 -213
- data/lib/rdoc/parser/simple.rb +31 -27
- data/lib/rdoc/parser/text.rb +12 -8
- data/lib/rdoc/parser.rb +228 -220
- data/lib/rdoc/rbs_helper.rb +1 -1
- data/lib/rdoc/rd/inline.rb +57 -53
- data/lib/rdoc/rd.rb +90 -88
- data/lib/rdoc/rdoc.rb +500 -491
- data/lib/rdoc/ri/driver.rb +1140 -1135
- data/lib/rdoc/ri/formatter.rb +7 -3
- data/lib/rdoc/ri/paths.rb +140 -136
- data/lib/rdoc/ri/servlet.rb +354 -350
- data/lib/rdoc/ri/store.rb +4 -2
- data/lib/rdoc/ri/task.rb +55 -51
- data/lib/rdoc/ri.rb +14 -12
- data/lib/rdoc/rubygems_hook.rb +183 -181
- data/lib/rdoc/server.rb +349 -347
- data/lib/rdoc/stats/normal.rb +46 -42
- data/lib/rdoc/stats/quiet.rb +39 -35
- data/lib/rdoc/stats/verbose.rb +35 -31
- data/lib/rdoc/stats.rb +365 -363
- data/lib/rdoc/store.rb +888 -902
- data/lib/rdoc/task.rb +260 -256
- data/lib/rdoc/text.rb +135 -133
- data/lib/rdoc/token_stream.rb +101 -93
- data/lib/rdoc/tom_doc.rb +203 -201
- data/lib/rdoc/version.rb +1 -1
- metadata +4 -5
- data/lib/rdoc/markdown/literals.kpeg +0 -21
- data/lib/rdoc/markdown/literals.rb +0 -454
data/lib/rdoc/comment.rb
CHANGED
|
@@ -1,352 +1,354 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
2
|
+
module RDoc
|
|
3
|
+
##
|
|
4
|
+
# A comment holds the text comment for a RDoc::CodeObject and provides a
|
|
5
|
+
# unified way of cleaning it up and parsing it into an RDoc::Markup::Document.
|
|
6
|
+
#
|
|
7
|
+
# Each comment may have a different markup format set by #format=. By default
|
|
8
|
+
# 'rdoc' is used. The :markup: directive tells RDoc which format to use.
|
|
9
|
+
#
|
|
10
|
+
# See {RDoc Markup Reference}[rdoc-ref:doc/markup_reference/rdoc.rdoc@Directive+for+Specifying+RDoc+Source+Format].
|
|
10
11
|
|
|
11
12
|
|
|
12
|
-
class
|
|
13
|
+
class Comment
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
include Text
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
##
|
|
18
|
+
# The format of this comment. Defaults to RDoc::Markup
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
attr_reader :format
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
##
|
|
23
|
+
# The RDoc::TopLevel this comment was found in
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
attr_accessor :location
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
##
|
|
28
|
+
# Line where this Comment was written
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
attr_accessor :line
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
##
|
|
33
|
+
# For duck-typing when merging classes at load time
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
alias file location # :nodoc:
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
##
|
|
38
|
+
# The text for this comment
|
|
38
39
|
|
|
39
|
-
|
|
40
|
+
attr_reader :text
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
##
|
|
43
|
+
# Alias for text
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
alias to_s text
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
##
|
|
48
|
+
# Overrides the content returned by #parse. Use when there is no #text
|
|
49
|
+
# source for this comment
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
attr_writer :document
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def initialize(text = nil, location = nil, language = nil)
|
|
57
|
-
@location = location
|
|
58
|
-
@text = text.nil? ? nil : text.dup
|
|
59
|
-
@language = language
|
|
53
|
+
##
|
|
54
|
+
# Creates a new comment with +text+ that is found in the RDoc::TopLevel
|
|
55
|
+
# +location+.
|
|
60
56
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
def initialize(text = nil, location = nil, language = nil)
|
|
58
|
+
@location = location
|
|
59
|
+
@text = text.nil? ? nil : text.dup
|
|
60
|
+
@language = language
|
|
65
61
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
@document = nil
|
|
63
|
+
@format = 'rdoc'
|
|
64
|
+
@normalized = false
|
|
65
|
+
end
|
|
69
66
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
67
|
+
##
|
|
68
|
+
#--
|
|
69
|
+
# TODO deep copy @document
|
|
73
70
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
end
|
|
71
|
+
def initialize_copy(copy) # :nodoc:
|
|
72
|
+
@text = copy.text.dup
|
|
73
|
+
end
|
|
78
74
|
|
|
79
|
-
|
|
80
|
-
|
|
75
|
+
def ==(other) # :nodoc:
|
|
76
|
+
self.class === other and
|
|
77
|
+
other.text == @text and other.location == @location
|
|
78
|
+
end
|
|
81
79
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
end
|
|
80
|
+
##
|
|
81
|
+
# A comment is empty if its text String is empty.
|
|
85
82
|
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
def empty?
|
|
84
|
+
@text.empty? && (@document.nil? || @document.empty?)
|
|
85
|
+
end
|
|
88
86
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
self
|
|
92
|
-
end
|
|
87
|
+
##
|
|
88
|
+
# HACK dubious
|
|
93
89
|
|
|
94
|
-
|
|
95
|
-
|
|
90
|
+
def encode!(encoding)
|
|
91
|
+
@text = String.new @text, encoding: encoding
|
|
92
|
+
self
|
|
93
|
+
end
|
|
96
94
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
@document = nil
|
|
100
|
-
end
|
|
95
|
+
##
|
|
96
|
+
# Sets the format of this comment and resets any parsed document
|
|
101
97
|
|
|
102
|
-
|
|
103
|
-
|
|
98
|
+
def format=(format)
|
|
99
|
+
@format = format
|
|
100
|
+
@document = nil
|
|
101
|
+
end
|
|
104
102
|
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
def inspect # :nodoc:
|
|
104
|
+
location = @location ? @location.relative_name : '(unknown)'
|
|
107
105
|
|
|
108
|
-
|
|
109
|
-
|
|
106
|
+
"#<%s:%x %s %p>" % [self.class, object_id, location, @text]
|
|
107
|
+
end
|
|
110
108
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return self if @normalized # TODO eliminate duplicate normalization
|
|
109
|
+
##
|
|
110
|
+
# Normalizes the text. See RDoc::Text#normalize_comment for details
|
|
114
111
|
|
|
115
|
-
|
|
112
|
+
def normalize
|
|
113
|
+
return self unless @text
|
|
114
|
+
return self if @normalized # TODO eliminate duplicate normalization
|
|
116
115
|
|
|
117
|
-
|
|
116
|
+
@text = normalize_comment @text
|
|
118
117
|
|
|
119
|
-
|
|
120
|
-
end
|
|
118
|
+
@normalized = true
|
|
121
119
|
|
|
122
|
-
|
|
120
|
+
self
|
|
121
|
+
end
|
|
123
122
|
|
|
124
|
-
|
|
125
|
-
@normalized = value
|
|
126
|
-
end
|
|
123
|
+
# Change normalized, when creating already normalized comment.
|
|
127
124
|
|
|
128
|
-
|
|
129
|
-
|
|
125
|
+
def normalized=(value)
|
|
126
|
+
@normalized = value
|
|
127
|
+
end
|
|
130
128
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
end
|
|
129
|
+
##
|
|
130
|
+
# Was this text normalized?
|
|
134
131
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
132
|
+
def normalized? # :nodoc:
|
|
133
|
+
@normalized
|
|
134
|
+
end
|
|
138
135
|
|
|
139
|
-
|
|
140
|
-
|
|
136
|
+
##
|
|
137
|
+
# Parses the comment into an RDoc::Markup::Document. The parsed document is
|
|
138
|
+
# cached until the text is changed.
|
|
141
139
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
@document
|
|
145
|
-
end
|
|
140
|
+
def parse
|
|
141
|
+
return @document if @document
|
|
146
142
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
143
|
+
@document = super @text, @format
|
|
144
|
+
@document.file = @location
|
|
145
|
+
@document
|
|
146
|
+
end
|
|
151
147
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
148
|
+
##
|
|
149
|
+
# Replaces this comment's text with +text+ and resets the parsed document.
|
|
150
|
+
#
|
|
151
|
+
# An error is raised if the comment contains a document but no text.
|
|
155
152
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
153
|
+
def text=(text)
|
|
154
|
+
raise Error, 'replacing document-only comment is not allowed' if
|
|
155
|
+
@text.nil? and @document
|
|
159
156
|
|
|
160
|
-
|
|
161
|
-
|
|
157
|
+
@document = nil
|
|
158
|
+
@text = text.nil? ? nil : text.dup
|
|
159
|
+
end
|
|
162
160
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
end
|
|
161
|
+
##
|
|
162
|
+
# Returns true if this comment is in TomDoc format.
|
|
166
163
|
|
|
167
|
-
|
|
164
|
+
def tomdoc?
|
|
165
|
+
@format == 'tomdoc'
|
|
166
|
+
end
|
|
168
167
|
|
|
169
|
-
|
|
170
|
-
COLON_LESS_DIRECTIVES = %w[call-seq Document-method].freeze # :nodoc:
|
|
168
|
+
MULTILINE_DIRECTIVES = %w[call-seq].freeze # :nodoc:
|
|
171
169
|
|
|
172
|
-
|
|
170
|
+
# There are more, but already handled by RDoc::Parser::C
|
|
171
|
+
COLON_LESS_DIRECTIVES = %w[call-seq Document-method].freeze # :nodoc:
|
|
173
172
|
|
|
174
|
-
|
|
173
|
+
DIRECTIVE_OR_ESCAPED_DIRECTIV_REGEXP = /\A(?<colon>\\?:|:?)(?<directive>[\w-]+):(?<param>.*)/
|
|
175
174
|
|
|
176
|
-
|
|
175
|
+
private_constant :MULTILINE_DIRECTIVES, :COLON_LESS_DIRECTIVES, :DIRECTIVE_OR_ESCAPED_DIRECTIV_REGEXP
|
|
177
176
|
|
|
178
|
-
|
|
179
|
-
# Create a new parsed comment from a document
|
|
177
|
+
class << self
|
|
180
178
|
|
|
181
|
-
|
|
182
|
-
comment
|
|
183
|
-
comment.document = document
|
|
184
|
-
comment.location = RDoc::TopLevel.new(document.file) if document.file
|
|
185
|
-
comment
|
|
186
|
-
end
|
|
179
|
+
##
|
|
180
|
+
# Create a new parsed comment from a document
|
|
187
181
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
#
|
|
194
|
-
# Include
|
|
195
|
-
# # :include: filename
|
|
196
|
-
#
|
|
197
|
-
# Directive
|
|
198
|
-
# # :directive-without-value:
|
|
199
|
-
# # :directive-with-value: value
|
|
200
|
-
#
|
|
201
|
-
# Multiline directive (only :call-seq:)
|
|
202
|
-
# # :multiline-directive:
|
|
203
|
-
# # value1
|
|
204
|
-
# # value2
|
|
205
|
-
#
|
|
206
|
-
# Private section
|
|
207
|
-
# #--
|
|
208
|
-
# # private comment
|
|
209
|
-
# #++
|
|
210
|
-
|
|
211
|
-
def parse(text, filename, line_no, type, &include_callback)
|
|
212
|
-
case type
|
|
213
|
-
when :ruby
|
|
214
|
-
text = text.gsub(/^#+/, '') if text.start_with?('#')
|
|
215
|
-
private_start_regexp = /^-{2,}$/
|
|
216
|
-
private_end_regexp = /^\+{2}$/
|
|
217
|
-
indent_regexp = /^\s*/
|
|
218
|
-
when :c
|
|
219
|
-
private_start_regexp = /^(\s*\*)?-{2,}$/
|
|
220
|
-
private_end_regexp = /^(\s*\*)?\+{2}$/
|
|
221
|
-
indent_regexp = /^\s*(\/\*+|\*)?\s*/
|
|
222
|
-
text = text.gsub(/\s*\*+\/\s*\z/, '')
|
|
223
|
-
when :simple
|
|
224
|
-
# Unlike other types, this implementation only looks for two dashes at
|
|
225
|
-
# the beginning of the line. Three or more dashes are considered to be
|
|
226
|
-
# a rule and ignored.
|
|
227
|
-
private_start_regexp = /^-{2}$/
|
|
228
|
-
private_end_regexp = /^\+{2}$/
|
|
229
|
-
indent_regexp = /^\s*/
|
|
182
|
+
def from_document(document) # :nodoc:
|
|
183
|
+
comment = Comment.new('')
|
|
184
|
+
comment.document = document
|
|
185
|
+
comment.location = TopLevel.new(document.file) if document.file
|
|
186
|
+
comment
|
|
230
187
|
end
|
|
231
188
|
|
|
232
|
-
directives
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
189
|
+
# Parse comment, collect directives as an attribute and return [normalized_comment_text, directives_hash]
|
|
190
|
+
# This method expands include and removes everything not needed in the document text, such as
|
|
191
|
+
# private section, directive line, comment characters `# /* * */` and indent spaces.
|
|
192
|
+
#
|
|
193
|
+
# RDoc comment consists of include, directive, multiline directive, private section and comment text.
|
|
194
|
+
#
|
|
195
|
+
# Include
|
|
196
|
+
# # :include: filename
|
|
197
|
+
#
|
|
198
|
+
# Directive
|
|
199
|
+
# # :directive-without-value:
|
|
200
|
+
# # :directive-with-value: value
|
|
201
|
+
#
|
|
202
|
+
# Multiline directive (only :call-seq:)
|
|
203
|
+
# # :multiline-directive:
|
|
204
|
+
# # value1
|
|
205
|
+
# # value2
|
|
206
|
+
#
|
|
207
|
+
# Private section
|
|
208
|
+
# #--
|
|
209
|
+
# # private comment
|
|
210
|
+
# #++
|
|
211
|
+
|
|
212
|
+
def parse(text, filename, line_no, type, &include_callback)
|
|
213
|
+
case type
|
|
214
|
+
when :ruby
|
|
215
|
+
text = text.gsub(/^#+/, '') if text.start_with?('#')
|
|
216
|
+
private_start_regexp = /^-{2,}$/
|
|
217
|
+
private_end_regexp = /^\+{2}$/
|
|
218
|
+
indent_regexp = /^\s*/
|
|
219
|
+
when :c
|
|
220
|
+
private_start_regexp = /^(\s*\*)?-{2,}$/
|
|
221
|
+
private_end_regexp = /^(\s*\*)?\+{2}$/
|
|
222
|
+
indent_regexp = /^\s*(\/\*+|\*)?\s*/
|
|
223
|
+
text = text.gsub(/\s*\*+\/\s*\z/, '')
|
|
224
|
+
when :simple
|
|
225
|
+
# Unlike other types, this implementation only looks for two dashes at
|
|
226
|
+
# the beginning of the line. Three or more dashes are considered to be
|
|
227
|
+
# a rule and ignored.
|
|
228
|
+
private_start_regexp = /^-{2}$/
|
|
229
|
+
private_end_regexp = /^\+{2}$/
|
|
230
|
+
indent_regexp = /^\s*/
|
|
249
231
|
end
|
|
250
232
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
233
|
+
directives = {}
|
|
234
|
+
lines = text.split("\n")
|
|
235
|
+
in_private = false
|
|
236
|
+
comment_lines = []
|
|
237
|
+
until lines.empty?
|
|
238
|
+
line = lines.shift
|
|
239
|
+
read_lines = 1
|
|
240
|
+
if in_private
|
|
241
|
+
# If `++` appears in a private section that starts with `--`, private section ends.
|
|
242
|
+
in_private = false if line.match?(private_end_regexp)
|
|
243
|
+
line_no += read_lines
|
|
244
|
+
next
|
|
245
|
+
elsif line.match?(private_start_regexp)
|
|
246
|
+
# If `--` appears in a line, private section starts.
|
|
247
|
+
in_private = true
|
|
248
|
+
line_no += read_lines
|
|
249
|
+
next
|
|
250
|
+
end
|
|
254
251
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
252
|
+
prefix = line[indent_regexp]
|
|
253
|
+
prefix_indent = ' ' * prefix.size
|
|
254
|
+
line = line.byteslice(prefix.bytesize..)
|
|
255
|
+
|
|
256
|
+
if (directive_match = DIRECTIVE_OR_ESCAPED_DIRECTIV_REGEXP.match(line))
|
|
257
|
+
colon = directive_match[:colon]
|
|
258
|
+
directive = directive_match[:directive]
|
|
259
|
+
raw_param = directive_match[:param]
|
|
260
|
+
param = raw_param.strip
|
|
261
|
+
else
|
|
262
|
+
colon = directive = raw_param = param = nil
|
|
263
|
+
end
|
|
263
264
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
265
|
+
if !directive
|
|
266
|
+
comment_lines << prefix_indent + line
|
|
267
|
+
elsif colon == '\\:'
|
|
268
|
+
# If directive is escaped, unescape it
|
|
269
|
+
comment_lines << prefix_indent + line.sub('\\:', ':')
|
|
270
|
+
elsif raw_param.start_with?(':') || (colon.empty? && !COLON_LESS_DIRECTIVES.include?(directive))
|
|
271
|
+
# Something like `:toto::` is not a directive
|
|
272
|
+
# Only few directives allows to start without a colon
|
|
273
|
+
comment_lines << prefix_indent + line
|
|
274
|
+
elsif directive == 'include'
|
|
275
|
+
filename_to_include = param
|
|
276
|
+
include_callback.call(filename_to_include, prefix_indent).lines.each { |l| comment_lines << l.chomp }
|
|
277
|
+
elsif MULTILINE_DIRECTIVES.include?(directive)
|
|
278
|
+
value_lines = take_multiline_directive_value_lines(directive, filename, line_no, lines, prefix_indent.size, indent_regexp, !param.empty?)
|
|
279
|
+
read_lines += value_lines.size
|
|
280
|
+
lines.shift(value_lines.size)
|
|
281
|
+
unless param.empty?
|
|
282
|
+
# Accept `:call-seq: first-line\n second-line` for now
|
|
283
|
+
value_lines.unshift(param)
|
|
284
|
+
end
|
|
285
|
+
value = value_lines.join("\n")
|
|
286
|
+
directives[directive] = [value.empty? ? nil : value, line_no]
|
|
287
|
+
else
|
|
288
|
+
directives[directive] = [param.empty? ? nil : param, line_no]
|
|
283
289
|
end
|
|
284
|
-
|
|
285
|
-
directives[directive] = [value.empty? ? nil : value, line_no]
|
|
286
|
-
else
|
|
287
|
-
directives[directive] = [param.empty? ? nil : param, line_no]
|
|
290
|
+
line_no += read_lines
|
|
288
291
|
end
|
|
289
|
-
|
|
292
|
+
|
|
293
|
+
normalized_comment = String.new(encoding: text.encoding) << normalize_comment_lines(comment_lines).join("\n")
|
|
294
|
+
[normalized_comment, directives]
|
|
290
295
|
end
|
|
291
296
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
297
|
+
# Remove preceding indent spaces and blank lines from the comment lines
|
|
298
|
+
|
|
299
|
+
private def normalize_comment_lines(lines)
|
|
300
|
+
blank_line_regexp = /\A\s*\z/
|
|
301
|
+
lines = lines.dup
|
|
302
|
+
lines.shift while lines.first&.match?(blank_line_regexp)
|
|
303
|
+
lines.pop while lines.last&.match?(blank_line_regexp)
|
|
295
304
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
min_spaces = lines.map do |l|
|
|
305
|
-
l.match(/\A *(?=\S)/)&.end(0)
|
|
306
|
-
end.compact.min
|
|
307
|
-
if min_spaces && min_spaces > 0
|
|
308
|
-
lines.map { |l| l[min_spaces..] || '' }
|
|
309
|
-
else
|
|
310
|
-
lines
|
|
305
|
+
min_spaces = lines.map do |l|
|
|
306
|
+
l.match(/\A *(?=\S)/)&.end(0)
|
|
307
|
+
end.compact.min
|
|
308
|
+
if min_spaces && min_spaces > 0
|
|
309
|
+
lines.map { |l| l[min_spaces..] || '' }
|
|
310
|
+
else
|
|
311
|
+
lines
|
|
312
|
+
end
|
|
311
313
|
end
|
|
312
|
-
end
|
|
313
314
|
|
|
314
|
-
|
|
315
|
+
# Take value lines of multiline directive
|
|
315
316
|
|
|
316
|
-
|
|
317
|
-
|
|
317
|
+
private def take_multiline_directive_value_lines(directive, filename, line_no, lines, base_indent_size, indent_regexp, has_param)
|
|
318
|
+
return [] if lines.empty?
|
|
318
319
|
|
|
319
|
-
|
|
320
|
+
first_indent_size = lines.first.match(indent_regexp).end(0)
|
|
320
321
|
|
|
321
|
-
|
|
322
|
-
|
|
322
|
+
# Blank line or unindented line is not part of multiline-directive value
|
|
323
|
+
return [] if first_indent_size <= base_indent_size
|
|
323
324
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
end
|
|
332
|
-
min_indent = value_lines.map { |l| l.match(indent_regexp).end(0) }.min
|
|
333
|
-
value_lines.map { |l| l[min_indent..] }
|
|
334
|
-
else
|
|
335
|
-
# Take indented lines accepting blank lines between them
|
|
336
|
-
value_lines = lines.take_while do |l|
|
|
337
|
-
l = l.rstrip
|
|
338
|
-
indent = l[indent_regexp]
|
|
339
|
-
if indent == l || indent.size >= first_indent_size
|
|
340
|
-
true
|
|
325
|
+
if has_param
|
|
326
|
+
# :multiline-directive: line1
|
|
327
|
+
# line2
|
|
328
|
+
# line3
|
|
329
|
+
#
|
|
330
|
+
value_lines = lines.take_while do |l|
|
|
331
|
+
l.rstrip.match(indent_regexp).end(0) > base_indent_size
|
|
341
332
|
end
|
|
342
|
-
|
|
343
|
-
|
|
333
|
+
min_indent = value_lines.map { |l| l.match(indent_regexp).end(0) }.min
|
|
334
|
+
value_lines.map { |l| l[min_indent..] }
|
|
335
|
+
else
|
|
336
|
+
# Take indented lines accepting blank lines between them
|
|
337
|
+
value_lines = lines.take_while do |l|
|
|
338
|
+
l = l.rstrip
|
|
339
|
+
indent = l[indent_regexp]
|
|
340
|
+
if indent == l || indent.size >= first_indent_size
|
|
341
|
+
true
|
|
342
|
+
end
|
|
343
|
+
end
|
|
344
|
+
value_lines.map! { |l| (l[first_indent_size..] || '').chomp }
|
|
344
345
|
|
|
345
|
-
|
|
346
|
-
|
|
346
|
+
if value_lines.size != lines.size && !value_lines.last.empty?
|
|
347
|
+
warn "#{filename}:#{line_no} Multiline directive :#{directive}: should end with a blank line."
|
|
348
|
+
end
|
|
349
|
+
value_lines.pop while value_lines.last&.empty?
|
|
350
|
+
value_lines
|
|
347
351
|
end
|
|
348
|
-
value_lines.pop while value_lines.last&.empty?
|
|
349
|
-
value_lines
|
|
350
352
|
end
|
|
351
353
|
end
|
|
352
354
|
end
|