decode 0.22.0 → 0.23.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
- checksums.yaml.gz.sig +0 -0
- data/bake/decode/index.rb +16 -9
- data/context/coverage.md +325 -0
- data/context/getting-started.md +242 -0
- data/context/ruby-documentation.md +363 -0
- data/lib/decode/comment/attribute.rb +9 -3
- data/lib/decode/comment/node.rb +4 -2
- data/lib/decode/comment/option.rb +1 -1
- data/lib/decode/comment/parameter.rb +12 -6
- data/lib/decode/comment/pragma.rb +12 -1
- data/lib/decode/comment/raises.rb +1 -1
- data/lib/decode/comment/returns.rb +3 -4
- data/lib/decode/comment/tag.rb +13 -3
- data/lib/decode/comment/tags.rb +17 -2
- data/lib/decode/comment/text.rb +4 -1
- data/lib/decode/comment/throws.rb +1 -1
- data/lib/decode/comment/yields.rb +7 -1
- data/lib/decode/definition.rb +54 -42
- data/lib/decode/documentation.rb +12 -14
- data/lib/decode/index.rb +29 -14
- data/lib/decode/language/generic.rb +30 -14
- data/lib/decode/language/reference.rb +13 -4
- data/lib/decode/language/ruby/alias.rb +41 -0
- data/lib/decode/language/ruby/attribute.rb +7 -6
- data/lib/decode/language/ruby/block.rb +4 -1
- data/lib/decode/language/ruby/call.rb +16 -6
- data/lib/decode/language/ruby/class.rb +19 -36
- data/lib/decode/language/ruby/code.rb +27 -15
- data/lib/decode/language/ruby/constant.rb +9 -8
- data/lib/decode/language/ruby/definition.rb +27 -19
- data/lib/decode/language/ruby/function.rb +2 -1
- data/lib/decode/language/ruby/generic.rb +17 -7
- data/lib/decode/language/ruby/method.rb +47 -12
- data/lib/decode/language/ruby/module.rb +4 -11
- data/lib/decode/language/ruby/parser.rb +358 -207
- data/lib/decode/language/ruby/reference.rb +26 -17
- data/lib/decode/language/ruby/segment.rb +11 -4
- data/lib/decode/language/ruby.rb +4 -2
- data/lib/decode/language.rb +2 -2
- data/lib/decode/languages.rb +25 -6
- data/lib/decode/location.rb +2 -0
- data/lib/decode/scope.rb +1 -1
- data/lib/decode/segment.rb +6 -5
- data/lib/decode/source.rb +12 -4
- data/lib/decode/syntax/link.rb +9 -1
- data/lib/decode/syntax/match.rb +12 -0
- data/lib/decode/syntax/rewriter.rb +10 -0
- data/lib/decode/trie.rb +27 -22
- data/lib/decode/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +9 -10
- metadata.gz.sig +0 -0
@@ -0,0 +1,363 @@
|
|
1
|
+
# Ruby Documentation
|
2
|
+
|
3
|
+
This guide covers documentation practices and pragmas supported by the Decode gem for documenting Ruby code. These pragmas provide structured documentation that can be parsed and used to generate API documentation and achieve complete documentation coverage.
|
4
|
+
|
5
|
+
## Documentation Guidelines
|
6
|
+
|
7
|
+
### Writing Style and Format
|
8
|
+
|
9
|
+
#### Definition Documentation
|
10
|
+
|
11
|
+
- **Full sentences**: All documentation for definitions (classes, modules, methods) should be written as complete sentences with proper grammar and punctuation.
|
12
|
+
- **Class documentation**: Documentation for classes should generally start with "Represents a ..." to clearly indicate what the class models or encapsulates.
|
13
|
+
- **Method documentation**: Should clearly describe what the method does, not how it does it.
|
14
|
+
- **Markdown format**: All documentation comments are written in Markdown format, allowing for rich formatting including lists, emphasis, code blocks, and links.
|
15
|
+
|
16
|
+
#### Inline Code Comments
|
17
|
+
|
18
|
+
- **Explanatory comments**: Comments within methods that explain specific lines or sections of code should end with a colon `:` to distinguish them from definition documentation.
|
19
|
+
- **Purpose**: These comments explain the reasoning behind specific implementation details.
|
20
|
+
|
21
|
+
#### Links and Code Formatting
|
22
|
+
|
23
|
+
- **Curly braces `{}`**: Use curly braces to create links to other methods, classes, or modules. The Decode gem uses `@index.lookup(text)` to resolve these references.
|
24
|
+
- **Absolute references**: `{Decode::Index#lookup}` - Links to a specific method in a specific class
|
25
|
+
- **Relative references**: `{lookup}` - Links to a method in the current scope or class
|
26
|
+
- **Class references**: `{User}` - Links to a class or module
|
27
|
+
- **Backticks**: Use backticks for code formatting of symbols, values, method names, and technical terms that should appear in monospace font.
|
28
|
+
- **Symbols**: `:admin`, `:user`, `:guest`
|
29
|
+
- **Values**: `true`, `false`, `nil`
|
30
|
+
- **Technical terms**: `attr_*`, `catch`/`throw`
|
31
|
+
- **Code expressions**: `**options`
|
32
|
+
|
33
|
+
#### Examples
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
# Represents a user account in the system.
|
37
|
+
class User
|
38
|
+
# @attribute [String] The user's email address.
|
39
|
+
attr_reader :email
|
40
|
+
|
41
|
+
# Initialize a new user account.
|
42
|
+
# @parameter email [String] The user's email address.
|
43
|
+
# @raises [ArgumentError] If email is invalid.
|
44
|
+
def initialize(email)
|
45
|
+
# Validate email format before assignment:
|
46
|
+
raise ArgumentError, "Invalid email format" unless email.match?(/\A[^@\s]+@[^@\s]+\z/)
|
47
|
+
|
48
|
+
# Store the normalized email:
|
49
|
+
@email = email.downcase.strip
|
50
|
+
end
|
51
|
+
|
52
|
+
# Authenticate the user with the provided password.
|
53
|
+
# @parameter password [String] The password to verify.
|
54
|
+
# @returns [Boolean] True if authentication succeeds.
|
55
|
+
def authenticate(password)
|
56
|
+
# Hash the password for comparison:
|
57
|
+
hashed = hash_password(password)
|
58
|
+
|
59
|
+
# Compare against stored hash:
|
60
|
+
hashed == @password_hash
|
61
|
+
end
|
62
|
+
|
63
|
+
# Deactivate the user account.
|
64
|
+
# This method sets the user's status to inactive. Use this instead of
|
65
|
+
# the deprecated {disable!} method. The account status can be checked
|
66
|
+
# using `active?` or by examining the `:active` attribute.
|
67
|
+
# @returns [Boolean] Returns `true` if deactivation was successful.
|
68
|
+
def deactivate!
|
69
|
+
@active = false
|
70
|
+
true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Represents a collection of users with search capabilities.
|
75
|
+
class UserCollection
|
76
|
+
# Find users matching the given criteria.
|
77
|
+
# @parameter criteria [Hash] Search parameters.
|
78
|
+
# @returns [Array(User)] Matching users.
|
79
|
+
def find(**criteria)
|
80
|
+
# Start with all users:
|
81
|
+
results = @users.dup
|
82
|
+
|
83
|
+
# Apply each filter criterion:
|
84
|
+
criteria.each do |key, value|
|
85
|
+
results = filter_by(results, key, value)
|
86
|
+
end
|
87
|
+
|
88
|
+
results
|
89
|
+
end
|
90
|
+
end
|
91
|
+
```
|
92
|
+
|
93
|
+
**Key formatting examples from above:**
|
94
|
+
- `{disable!}` - Creates a link to the `disable!` method (relative reference)
|
95
|
+
- `active?` - Formats the method name in monospace (backticks for code formatting)
|
96
|
+
- `:active` - Formats the symbol in monospace (backticks for code formatting)
|
97
|
+
- `true` - Formats the boolean value in monospace (backticks for code formatting)
|
98
|
+
|
99
|
+
### Best Practices
|
100
|
+
|
101
|
+
1. **Be Consistent**: Use the same format for similar types of documentation.
|
102
|
+
2. **Include Types**: Always specify types for parameters, returns, and attributes.
|
103
|
+
3. **Be Descriptive**: Provide clear, actionable descriptions.
|
104
|
+
4. **Document Exceptions**: Always document what exceptions might be raised.
|
105
|
+
5. **Use Examples**: Include usage examples when the behavior isn't obvious.
|
106
|
+
6. **Keep Updated**: Update documentation when you change the code.
|
107
|
+
7. **Use @namespace wisely**: Apply to organizational modules to achieve 100% coverage.
|
108
|
+
8. **Avoid redundancy**: For simple attributes and methods, attach descriptions directly to pragmas rather than repeating obvious information.
|
109
|
+
|
110
|
+
#### Simple Attributes and Methods
|
111
|
+
|
112
|
+
For extremely simple attributes and methods where the name clearly indicates the purpose, avoid redundant descriptions. Instead, attach the description directly to the `@attribute` pragma:
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
# Good - concise and clear:
|
116
|
+
# @attribute [String] The name of the parameter.
|
117
|
+
attr :name
|
118
|
+
|
119
|
+
# @attribute [String] The type of the parameter.
|
120
|
+
attr :type
|
121
|
+
|
122
|
+
# Avoid - redundant descriptions:
|
123
|
+
# The name of the parameter.
|
124
|
+
# @attribute [String] The parameter name.
|
125
|
+
attr :name
|
126
|
+
```
|
127
|
+
|
128
|
+
This approach keeps documentation concise while still providing essential type information.
|
129
|
+
|
130
|
+
## Type Signatures
|
131
|
+
|
132
|
+
Type signatures are used to specify the expected types of parameters, return values, and attributes in Ruby code. They help clarify the intended use of methods and improve code readability.
|
133
|
+
|
134
|
+
### Primitive Types
|
135
|
+
|
136
|
+
- `String`: Represents a sequence of characters.
|
137
|
+
- `Integer`: Represents whole numbers.
|
138
|
+
- `Float`: Represents decimal numbers.
|
139
|
+
- `Boolean`: Represents true or false values.
|
140
|
+
- `Symbol`: Represents a name or identifier.
|
141
|
+
|
142
|
+
### Composite Types
|
143
|
+
|
144
|
+
- `Array(Type)`: Represents an ordered collection of items.
|
145
|
+
- `Hash(KeyType, ValueType)`: Represents a collection of key-value pairs.
|
146
|
+
- `Interface(:method1, :method2)`: Represents a contract that a class must implement, specifying required methods.
|
147
|
+
- `Type | Nil`: Represents an optional type.
|
148
|
+
|
149
|
+
## Supported Pragmas
|
150
|
+
|
151
|
+
### Type and Return Value Documentation
|
152
|
+
|
153
|
+
#### `@attribute [Type] Description.`
|
154
|
+
|
155
|
+
Documents class attributes, instance variables, and `attr_*` declarations. Prefer to have one attribute per line for clarity.
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
# Represents a person with basic attributes.
|
159
|
+
class Person
|
160
|
+
# @attribute [String] The person's full name.
|
161
|
+
attr_reader :name
|
162
|
+
|
163
|
+
# @attribute [Integer] The person's age in years.
|
164
|
+
attr_accessor :age
|
165
|
+
|
166
|
+
# @attribute [Hash] Configuration settings.
|
167
|
+
attr_writer :config
|
168
|
+
end
|
169
|
+
```
|
170
|
+
|
171
|
+
#### `@parameter name [Type] Description.`
|
172
|
+
|
173
|
+
Documents method parameters with their types and descriptions.
|
174
|
+
|
175
|
+
```ruby
|
176
|
+
# @parameter x [Integer] The x coordinate.
|
177
|
+
# @parameter y [Integer] The y coordinate.
|
178
|
+
# @parameter options [Hash] Optional configuration.
|
179
|
+
def move(x, y, **options)
|
180
|
+
# ...
|
181
|
+
end
|
182
|
+
```
|
183
|
+
|
184
|
+
#### `@option :key [Type] Description.`
|
185
|
+
|
186
|
+
Documents hash options (keyword arguments).
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
# @parameter user [User] The user object.
|
190
|
+
# @option :cached [Boolean] Whether to cache the result.
|
191
|
+
# @option :timeout [Integer] Request timeout in seconds.
|
192
|
+
def fetch_user_data(user, **options)
|
193
|
+
# ...
|
194
|
+
end
|
195
|
+
```
|
196
|
+
|
197
|
+
#### `@returns [Type] Description.`
|
198
|
+
|
199
|
+
Documents return values.
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
# @returns [String] The formatted user name.
|
203
|
+
def full_name
|
204
|
+
"#{first_name} #{last_name}"
|
205
|
+
end
|
206
|
+
|
207
|
+
# @returns [Array(User)] All active users.
|
208
|
+
def active_users
|
209
|
+
users.select(&:active?)
|
210
|
+
end
|
211
|
+
```
|
212
|
+
|
213
|
+
#### `@raises [Exception] Description.`
|
214
|
+
|
215
|
+
Documents exceptions that may be raised.
|
216
|
+
|
217
|
+
```ruby
|
218
|
+
# @parameter age [Integer] The person's age.
|
219
|
+
# @raises [ArgumentError] If age is negative.
|
220
|
+
# @raises [TypeError] If age is not an integer.
|
221
|
+
def set_age(age)
|
222
|
+
raise ArgumentError, "Age cannot be negative" if age < 0
|
223
|
+
raise TypeError, "Age must be an integer" unless age.is_a?(Integer)
|
224
|
+
@age = age
|
225
|
+
end
|
226
|
+
```
|
227
|
+
|
228
|
+
#### `@throws [:symbol] Description.`
|
229
|
+
|
230
|
+
Documents symbols that may be thrown (used with `catch`/`throw`).
|
231
|
+
|
232
|
+
```ruby
|
233
|
+
# @throws [:skip] To skip processing this item.
|
234
|
+
# @throws [:retry] To retry the operation.
|
235
|
+
def process_item(item)
|
236
|
+
throw :skip if item.nil?
|
237
|
+
throw :retry if item.invalid?
|
238
|
+
# ...
|
239
|
+
end
|
240
|
+
```
|
241
|
+
|
242
|
+
### Block Documentation
|
243
|
+
|
244
|
+
#### `@yields {|param| ...} Description.`
|
245
|
+
|
246
|
+
Documents block parameters and behavior.
|
247
|
+
|
248
|
+
```ruby
|
249
|
+
# @yields {|item| ...} Each item in the collection.
|
250
|
+
# @parameter item [Object] The current item being processed.
|
251
|
+
def each_item(&block)
|
252
|
+
items.each(&block)
|
253
|
+
end
|
254
|
+
|
255
|
+
# @yields {|user, index| ...} User and their index.
|
256
|
+
# @parameter user [User] The current user.
|
257
|
+
# @parameter index [Integer] The user's position in the list.
|
258
|
+
def each_user_with_index(&block)
|
259
|
+
users.each_with_index(&block)
|
260
|
+
end
|
261
|
+
```
|
262
|
+
|
263
|
+
### Visibility and Access Control
|
264
|
+
|
265
|
+
#### `@public`
|
266
|
+
|
267
|
+
Explicitly marks a method as public (useful for documentation clarity).
|
268
|
+
|
269
|
+
```ruby
|
270
|
+
# @public
|
271
|
+
def public_method
|
272
|
+
# This method is part of the public API.
|
273
|
+
end
|
274
|
+
```
|
275
|
+
|
276
|
+
#### `@private`
|
277
|
+
|
278
|
+
Marks a method as private (for documentation purposes).
|
279
|
+
|
280
|
+
```ruby
|
281
|
+
# @private
|
282
|
+
def internal_helper
|
283
|
+
# This method is for internal use only.
|
284
|
+
end
|
285
|
+
```
|
286
|
+
|
287
|
+
### Behavioral Documentation
|
288
|
+
|
289
|
+
#### `@deprecated Description.`
|
290
|
+
|
291
|
+
Marks methods as deprecated with migration guidance.
|
292
|
+
|
293
|
+
```ruby
|
294
|
+
# @deprecated Use {new_method} instead.
|
295
|
+
def old_method
|
296
|
+
# Legacy implementation
|
297
|
+
end
|
298
|
+
```
|
299
|
+
|
300
|
+
#### `@asynchronous`
|
301
|
+
|
302
|
+
Indicates that a method may yield control.
|
303
|
+
|
304
|
+
```ruby
|
305
|
+
# @asynchronous
|
306
|
+
def fetch_data
|
307
|
+
# This method may yield control during execution.
|
308
|
+
end
|
309
|
+
```
|
310
|
+
|
311
|
+
### Namespace Documentation
|
312
|
+
|
313
|
+
#### `@namespace`
|
314
|
+
|
315
|
+
Marks a module as serving only as a namespace, achieving 100% documentation coverage without requiring detailed documentation of empty container modules.
|
316
|
+
|
317
|
+
```ruby
|
318
|
+
# @namespace
|
319
|
+
module MyGem
|
320
|
+
# This module serves only as a namespace for organizing classes.
|
321
|
+
|
322
|
+
class ActualImplementation
|
323
|
+
# This class contains the real functionality.
|
324
|
+
end
|
325
|
+
end
|
326
|
+
```
|
327
|
+
|
328
|
+
**Why use `@namespace`?**
|
329
|
+
- Achieves 100% documentation coverage without redundant documentation.
|
330
|
+
- Clearly indicates that a module is purely organizational.
|
331
|
+
- Avoids documenting modules that exist only to group related classes.
|
332
|
+
- Maintains clean, focused documentation on actual functionality.
|
333
|
+
|
334
|
+
**When to use `@namespace`:**
|
335
|
+
- Root gem modules that only contain other classes/modules.
|
336
|
+
- Organizational modules with no methods or meaningful state.
|
337
|
+
- Modules that exist purely for constant scoping.
|
338
|
+
- Any module where documentation would add no value.
|
339
|
+
|
340
|
+
**Note:** This pragma is treated as a form of documentation by the Decode gem, satisfying coverage requirements while keeping the codebase clean.
|
341
|
+
|
342
|
+
## Special Pragmas for Code Structure
|
343
|
+
|
344
|
+
### `@name custom_name`
|
345
|
+
|
346
|
+
Overrides the default name extraction for attributes or methods.
|
347
|
+
|
348
|
+
```ruby
|
349
|
+
# @name hostname
|
350
|
+
# @attribute [String] The server hostname.
|
351
|
+
attr_reader :server_name
|
352
|
+
```
|
353
|
+
|
354
|
+
### `@scope Module::Name`
|
355
|
+
|
356
|
+
Defines scope for definitions that should be associated with a specific module.
|
357
|
+
|
358
|
+
```ruby
|
359
|
+
# @scope Database
|
360
|
+
def connect
|
361
|
+
# This method belongs to the Database scope.
|
362
|
+
end
|
363
|
+
```
|
@@ -3,9 +3,10 @@
|
|
3
3
|
# Released under the MIT License.
|
4
4
|
# Copyright, 2020-2024, by Samuel Williams.
|
5
5
|
|
6
|
-
require_relative
|
6
|
+
require_relative "tag"
|
7
7
|
|
8
8
|
module Decode
|
9
|
+
# Represents comment parsing and processing functionality.
|
9
10
|
module Comment
|
10
11
|
# Describes an attribute type.
|
11
12
|
#
|
@@ -14,6 +15,9 @@ module Decode
|
|
14
15
|
class Attribute < Tag
|
15
16
|
PATTERN = /\A\[(?<type>.*?)\](\s+(?<details>.*?))?\Z/
|
16
17
|
|
18
|
+
# Build an attribute from a directive and match.
|
19
|
+
# @parameter directive [String] The original directive text.
|
20
|
+
# @parameter match [MatchData] The regex match data.
|
17
21
|
def self.build(directive, match)
|
18
22
|
node = self.new(directive, match[:type])
|
19
23
|
|
@@ -24,14 +28,16 @@ module Decode
|
|
24
28
|
return node
|
25
29
|
end
|
26
30
|
|
31
|
+
# Initialize a new attribute.
|
32
|
+
# @parameter directive [String] The original directive text.
|
33
|
+
# @parameter type [String] The type of the attribute.
|
27
34
|
def initialize(directive, type)
|
28
35
|
super(directive)
|
29
36
|
|
30
37
|
@type = type
|
31
38
|
end
|
32
39
|
|
33
|
-
# The type of the attribute.
|
34
|
-
# @attribute [String]
|
40
|
+
# @attribute [String] The type of the attribute.
|
35
41
|
attr :type
|
36
42
|
end
|
37
43
|
end
|
data/lib/decode/comment/node.rb
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
|
6
6
|
module Decode
|
7
7
|
module Comment
|
8
|
+
# Represents a node in a comment tree structure.
|
8
9
|
class Node
|
9
10
|
# Initialize the node.
|
10
11
|
# @parameter children [Array(Node) | Nil]
|
@@ -26,8 +27,7 @@ module Decode
|
|
26
27
|
@children << child
|
27
28
|
end
|
28
29
|
|
29
|
-
# Any children of this node.
|
30
|
-
# @attribute [Array(Node | Text) | Nil]
|
30
|
+
# @attribute [Array(Node | Text) | Nil] Any children of this node.
|
31
31
|
attr :children
|
32
32
|
|
33
33
|
# Enumerate all non-text children nodes.
|
@@ -39,6 +39,8 @@ module Decode
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
# Filter children nodes by class type.
|
43
|
+
# @parameter klass [Class] The class to filter by.
|
42
44
|
def filter(klass)
|
43
45
|
return to_enum(:filter, klass) unless block_given?
|
44
46
|
|
@@ -3,17 +3,21 @@
|
|
3
3
|
# Released under the MIT License.
|
4
4
|
# Copyright, 2020-2024, by Samuel Williams.
|
5
5
|
|
6
|
-
require_relative
|
6
|
+
require_relative "tag"
|
7
7
|
|
8
8
|
module Decode
|
9
9
|
module Comment
|
10
|
-
#
|
10
|
+
# Represents a named method parameter.
|
11
11
|
#
|
12
12
|
# - `@parameter age [Float] The users age.`
|
13
13
|
#
|
14
14
|
class Parameter < Tag
|
15
15
|
PATTERN = /\A(?<name>.*?)\s+\[(?<type>.*?)\](\s+(?<details>.*?))?\Z/
|
16
16
|
|
17
|
+
# Build a parameter from a directive and regex match.
|
18
|
+
# @parameter directive [String] The original directive text.
|
19
|
+
# @parameter match [MatchData] The regex match data containing name, type, and details.
|
20
|
+
# @returns [Parameter] A new parameter object.
|
17
21
|
def self.build(directive, match)
|
18
22
|
node = self.new(directive, match[:name], match[:type])
|
19
23
|
|
@@ -24,6 +28,10 @@ module Decode
|
|
24
28
|
return node
|
25
29
|
end
|
26
30
|
|
31
|
+
# Initialize a new parameter.
|
32
|
+
# @parameter directive [String] The original directive text.
|
33
|
+
# @parameter name [String] The name of the parameter.
|
34
|
+
# @parameter type [String] The type of the parameter.
|
27
35
|
def initialize(directive, name, type)
|
28
36
|
super(directive)
|
29
37
|
|
@@ -31,12 +39,10 @@ module Decode
|
|
31
39
|
@type = type
|
32
40
|
end
|
33
41
|
|
34
|
-
# The name of the parameter.
|
35
|
-
# @attribute [String]
|
42
|
+
# @attribute [String] The name of the parameter.
|
36
43
|
attr :name
|
37
44
|
|
38
|
-
# The type of the
|
39
|
-
# @attribute [String]
|
45
|
+
# @attribute [String] The type of the parameter.
|
40
46
|
attr :type
|
41
47
|
end
|
42
48
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
# Released under the MIT License.
|
4
4
|
# Copyright, 2020-2024, by Samuel Williams.
|
5
5
|
|
6
|
-
require_relative
|
6
|
+
require_relative "tag"
|
7
7
|
|
8
8
|
module Decode
|
9
9
|
module Comment
|
@@ -15,10 +15,19 @@ module Decode
|
|
15
15
|
# - `@asynchronous This method may yield.`
|
16
16
|
#
|
17
17
|
class Pragma < Tag
|
18
|
+
# Parse a pragma directive from text.
|
19
|
+
# @parameter directive [String] The directive name.
|
20
|
+
# @parameter text [String] The directive text.
|
21
|
+
# @parameter lines [Array(String)] The remaining lines.
|
22
|
+
# @parameter tags [Array(Tag)] The collection of tags.
|
23
|
+
# @parameter level [Integer] The indentation level.
|
18
24
|
def self.parse(directive, text, lines, tags, level = 0)
|
19
25
|
self.build(directive, text)
|
20
26
|
end
|
21
27
|
|
28
|
+
# Build a pragma from a directive and text.
|
29
|
+
# @parameter directive [String] The directive name.
|
30
|
+
# @parameter text [String] The directive text.
|
22
31
|
def self.build(directive, text)
|
23
32
|
node = self.new(directive)
|
24
33
|
|
@@ -29,6 +38,8 @@ module Decode
|
|
29
38
|
return node
|
30
39
|
end
|
31
40
|
|
41
|
+
# Initialize a new pragma.
|
42
|
+
# @parameter directive [String] The directive name.
|
32
43
|
def initialize(directive)
|
33
44
|
super(directive)
|
34
45
|
end
|
@@ -3,14 +3,13 @@
|
|
3
3
|
# Released under the MIT License.
|
4
4
|
# Copyright, 2020-2024, by Samuel Williams.
|
5
5
|
|
6
|
-
require_relative
|
6
|
+
require_relative "attribute"
|
7
7
|
|
8
8
|
module Decode
|
9
9
|
module Comment
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# - `@returns [Integer] The person's age.`
|
10
|
+
# Represents a return value.
|
13
11
|
#
|
12
|
+
# Example: `@returns [Integer] The person's age.`
|
14
13
|
class Returns < Attribute
|
15
14
|
end
|
16
15
|
end
|
data/lib/decode/comment/tag.rb
CHANGED
@@ -3,15 +3,24 @@
|
|
3
3
|
# Released under the MIT License.
|
4
4
|
# Copyright, 2020-2024, by Samuel Williams.
|
5
5
|
|
6
|
-
require_relative
|
6
|
+
require_relative "node"
|
7
7
|
|
8
8
|
module Decode
|
9
9
|
module Comment
|
10
|
+
# Represents a documentation tag parsed from a comment directive.
|
10
11
|
class Tag < Node
|
12
|
+
# Match text against the tag pattern.
|
13
|
+
# @parameter text [String] The text to match.
|
11
14
|
def self.match(text)
|
12
15
|
self::PATTERN.match(text)
|
13
16
|
end
|
14
17
|
|
18
|
+
# Parse a tag from a directive and text.
|
19
|
+
# @parameter directive [String] The directive name.
|
20
|
+
# @parameter text [String] The directive text.
|
21
|
+
# @parameter lines [Array(String)] The remaining lines.
|
22
|
+
# @parameter tags [Tags] The tags parser.
|
23
|
+
# @parameter level [Integer] The indentation level.
|
15
24
|
def self.parse(directive, text, lines, tags, level = 0)
|
16
25
|
if match = self.match(text)
|
17
26
|
node = self.build(directive, match)
|
@@ -27,12 +36,13 @@ module Decode
|
|
27
36
|
end
|
28
37
|
end
|
29
38
|
|
39
|
+
# Initialize a new tag.
|
40
|
+
# @parameter directive [String] The directive that generated the tag.
|
30
41
|
def initialize(directive)
|
31
42
|
@directive = directive
|
32
43
|
end
|
33
44
|
|
34
|
-
# The directive that generated the tag.
|
35
|
-
# @attribute [String]
|
45
|
+
# @attribute [String] The directive that generated the tag.
|
36
46
|
attr :directive
|
37
47
|
end
|
38
48
|
end
|
data/lib/decode/comment/tags.rb
CHANGED
@@ -3,11 +3,14 @@
|
|
3
3
|
# Released under the MIT License.
|
4
4
|
# Copyright, 2020-2024, by Samuel Williams.
|
5
5
|
|
6
|
-
require_relative
|
6
|
+
require_relative "text"
|
7
7
|
|
8
8
|
module Decode
|
9
9
|
module Comment
|
10
|
+
# Represents a collection of documentation tags and their parsing logic.
|
10
11
|
class Tags
|
12
|
+
# Build a tags parser with directive mappings.
|
13
|
+
# @parameter block [Proc] A block that yields the directives hash.
|
11
14
|
def self.build
|
12
15
|
directives = Hash.new
|
13
16
|
|
@@ -16,16 +19,25 @@ module Decode
|
|
16
19
|
return self.new(directives)
|
17
20
|
end
|
18
21
|
|
22
|
+
# Initialize a new tags parser.
|
23
|
+
# @parameter directives [Hash(String, Class)] The directive mappings.
|
19
24
|
def initialize(directives)
|
20
25
|
@directives = directives
|
21
26
|
end
|
22
27
|
|
28
|
+
# Check if a line has valid indentation for the given level.
|
29
|
+
# @parameter line [String] The line to check.
|
30
|
+
# @parameter level [Integer] The expected indentation level.
|
23
31
|
def valid_indentation?(line, level)
|
24
|
-
line.start_with?(
|
32
|
+
line.start_with?(" " * level) || line.start_with?("\t" * level)
|
25
33
|
end
|
26
34
|
|
27
35
|
PATTERN = /\A\s*@(?<directive>.*?)(\s+(?<remainder>.*?))?\Z/
|
28
36
|
|
37
|
+
# Parse documentation tags from lines.
|
38
|
+
# @parameter lines [Array(String)] The lines to parse.
|
39
|
+
# @parameter level [Integer] The indentation level.
|
40
|
+
# @parameter block [Proc] A block to yield parsed tags to.
|
29
41
|
def parse(lines, level = 0, &block)
|
30
42
|
while line = lines.first
|
31
43
|
# Is it at the right indentation level:
|
@@ -52,6 +64,9 @@ module Decode
|
|
52
64
|
end
|
53
65
|
end
|
54
66
|
|
67
|
+
# Ignore lines at the specified indentation level.
|
68
|
+
# @parameter lines [Array(String)] The lines to ignore.
|
69
|
+
# @parameter level [Integer] The indentation level.
|
55
70
|
def ignore(lines, level = 0)
|
56
71
|
if line = lines.first
|
57
72
|
# Is it at the right indentation level:
|
data/lib/decode/comment/text.rb
CHANGED
@@ -3,18 +3,21 @@
|
|
3
3
|
# Released under the MIT License.
|
4
4
|
# Copyright, 2020-2024, by Samuel Williams.
|
5
5
|
|
6
|
-
require_relative
|
6
|
+
require_relative "node"
|
7
7
|
|
8
8
|
module Decode
|
9
9
|
module Comment
|
10
10
|
# A structured comment.
|
11
11
|
class Text
|
12
|
+
# Initialize a new text node.
|
13
|
+
# @parameter line [String] The text content.
|
12
14
|
def initialize(line)
|
13
15
|
@line = line
|
14
16
|
end
|
15
17
|
|
16
18
|
attr :line
|
17
19
|
|
20
|
+
# Traverse the text node.
|
18
21
|
def traverse
|
19
22
|
end
|
20
23
|
end
|