decode 0.25.0 → 0.26.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 01244e4f44a9916295cace389ef8ad2116277a1e5831f500d1e13d953290386a
4
- data.tar.gz: e3a85a7b3c2c4d98aa8acc50026a2b515bc33db95fff2ec82c117cda0c1ded52
3
+ metadata.gz: 453b1f28ebb358dd7f37f17d12e6e48616895970d0a9a9225ddb8d3384f2fc90
4
+ data.tar.gz: 3720af135885d5d002f91a3bc758a3f04e58c1d7022fc4d90b008754568b66d2
5
5
  SHA512:
6
- metadata.gz: 974b45b31551d81b281fe5a483a93e0b3ed07a3b6508dbd30df014b45cc2b47a51a34ae6f20454bd973ec7fe5c23393a7176c20028e6dba9a1402fb987c79eb2
7
- data.tar.gz: 5028c457dc3c24d79996170725604fddffc127f96a96f8fdf5c3c4188162097538cb103be51808d125e3ed3edec786104874123197bd6e37bd8e463fcf7319b5
6
+ metadata.gz: cf74b8ffc88195be9440a81aeceb0da5b2b77ff9c2e45df2961f683b27ed15f1d5ccab54d161f05931d2c9c5fdd5641b50b6122757b91d55d3a5668c8dcbde1a
7
+ data.tar.gz: 417e14f2501bdb368a25f5872915d4d3de47cd57f39164977c4a42b372ab41f4a9d4d435644972297f076c84cc3d475f732a4d90677ba0bb7b01e897586ca9b1
checksums.yaml.gz.sig CHANGED
Binary file
@@ -0,0 +1,254 @@
1
+ # Documentation Coverage
2
+
3
+ This guide explains how to test and monitor documentation coverage in your Ruby projects using the Decode gem's built-in bake tasks.
4
+
5
+ ## Available Bake Tasks
6
+
7
+ The Decode gem provides several bake tasks for analyzing your codebase:
8
+
9
+ - `bake decode:index:coverage` - Check documentation coverage.
10
+ - `bake decode:index:symbols` - List all symbols in the codebase.
11
+ - `bake decode:index:documentation` - Extract all documentation.
12
+
13
+ ## Checking Documentation Coverage
14
+
15
+ ### Basic Coverage Check
16
+
17
+ ```bash
18
+ # Check coverage for the lib directory:
19
+ bake decode:index:coverage lib
20
+
21
+ # Check coverage for a specific directory:
22
+ bake decode:index:coverage app/models
23
+ ```
24
+
25
+ ### Example Output
26
+
27
+ When you run the coverage command, you'll see output like:
28
+
29
+ ```
30
+ Decode
31
+ Decode::VERSION
32
+ Decode::Languages.all
33
+ Decode::Languages#initialize
34
+ Decode::Languages#freeze
35
+ Decode::Languages#add
36
+ Decode::Languages#fetch
37
+ Decode::Languages#source_for
38
+ Decode::Languages::REFERENCE
39
+ Decode::Languages#reference_for
40
+ Decode::Source#initialize
41
+ ... snip ...
42
+ 135/215 definitions have documentation.
43
+ ```
44
+
45
+ Using this tool can show you areas that might require more attention.
46
+
47
+ ### Understanding Coverage Output
48
+
49
+ The coverage check:
50
+ - **Counts only public definitions** (public methods, classes, modules).
51
+ - **Reports the ratio** of documented vs total public definitions.
52
+ - **Lists missing documentation** by qualified name.
53
+ - **Fails with an error** if coverage is incomplete.
54
+
55
+ ### What Counts as "Documented"
56
+
57
+ A definition is considered documented if it has:
58
+ - Any comment preceding it.
59
+ - Documentation pragmas (like `@parameter`, `@returns`, `@example`).
60
+ - A `@namespace` pragma (for organizational modules).
61
+
62
+ ```ruby
63
+ # Represents a user in the system.
64
+ class MyClass
65
+ end
66
+
67
+ # @namespace
68
+ module OrganizationalModule
69
+ # Contains helper functionality.
70
+ end
71
+
72
+ # Process user data and return formatted results.
73
+ # @parameter name [String] The user's name.
74
+ # @returns [bool] Success status.
75
+ def process(name)
76
+ # Validation logic here:
77
+ return false if name.empty?
78
+
79
+ # Processing logic:
80
+ true
81
+ end
82
+
83
+ class UndocumentedClass
84
+ end
85
+ ```
86
+
87
+ ## Analyzing Symbols
88
+
89
+ ### List All Symbols
90
+
91
+ ```bash
92
+ # See the structure of your codebase
93
+ bake decode:index:symbols lib
94
+ ```
95
+
96
+ This shows the hierarchical structure of your code:
97
+
98
+ ```
99
+ [] -> []
100
+ ["MyGem"] -> [#<Decode::Language::Ruby::Module:...>]
101
+ MyGem
102
+ ["MyGem", "User"] -> [#<Decode::Language::Ruby::Class:...>]
103
+ MyGem::User
104
+ ["MyGem", "User", "initialize"] -> [#<Decode::Language::Ruby::Method:...>]
105
+ MyGem::User#initialize
106
+ ```
107
+
108
+ ### Extract Documentation
109
+
110
+ ```bash
111
+ # Extract all documentation from your codebase
112
+ bake decode:index:documentation lib
113
+ ```
114
+
115
+ This outputs formatted documentation for all documented definitions:
116
+
117
+ ~~~markdown
118
+ ## `MyGem::User#initialize`
119
+
120
+ Initialize a new user with the given email address.
121
+
122
+ ## `MyGem::User#authenticate`
123
+
124
+ Authenticate the user with a password.
125
+ Returns true if authentication is successful.
126
+ ~~~
127
+
128
+ ## Achieving 100% Coverage
129
+
130
+ ### Document all public APIs
131
+
132
+ ```ruby
133
+ # Represents a user management system.
134
+ class User
135
+ # @attribute [String] The user's email address.
136
+ attr_reader :email
137
+
138
+ # Initialize a new user.
139
+ # @parameter email [String] The user's email address.
140
+ def initialize(email)
141
+ # Store the email address:
142
+ @email = email
143
+ end
144
+ end
145
+ ```
146
+
147
+ ### Use @namespace for organizational modules
148
+
149
+ The best place to add these by default is `version.rb`.
150
+
151
+ ```ruby
152
+ # @namespace
153
+ module MyGem
154
+ VERSION = "0.1.0"
155
+ end
156
+ ```
157
+
158
+ ### Document edge cases
159
+
160
+ ```ruby
161
+ # @private
162
+ def internal_helper
163
+ # Add the fields:
164
+ return foo + bar
165
+ end
166
+ ```
167
+
168
+ ### Common Coverage Issues
169
+
170
+ #### Missing namespace documentation
171
+
172
+ ```ruby
173
+ # This module has no documentation and will show as missing coverage:
174
+ module MyGem
175
+ end
176
+
177
+ # Solution: Add @namespace pragma:
178
+ # @namespace
179
+ module MyGem
180
+ # Provides core functionality.
181
+ end
182
+ ```
183
+
184
+ #### Undocumented methods
185
+
186
+ Problem: Methods without any comments will show as missing coverage:
187
+ ```ruby
188
+ def process_data
189
+ # Implementation here
190
+ end
191
+ ```
192
+
193
+ Solution: Add description and pragmas:
194
+ ```ruby
195
+ # Process the input data and return results.
196
+ # @parameter data [Hash] Input data to process.
197
+ # @returns [Array] Processed results.
198
+ def process_data(data)
199
+ # Process the input:
200
+ results = data.map {|item| transform(item)}
201
+
202
+ # Return processed results:
203
+ results
204
+ end
205
+ ```
206
+
207
+ #### Missing attr documentation
208
+
209
+ Problem: Attributes without documentation will show as missing coverage:
210
+ ```ruby
211
+ attr_reader :name
212
+ ```
213
+
214
+ Solution: Document with @attribute pragma:
215
+ ```ruby
216
+ # @attribute [String] The user's full name.
217
+ attr_reader :name
218
+ ```
219
+
220
+ ## Integrating into CI/CD
221
+
222
+ ### GitHub Actions Example
223
+
224
+ ```yaml
225
+ name: Documentation Coverage
226
+
227
+ on: [push, pull_request]
228
+
229
+ jobs:
230
+ docs:
231
+ runs-on: ubuntu-latest
232
+ steps:
233
+ - uses: actions/checkout@v3
234
+ - uses: ruby/setup-ruby@v1
235
+ with:
236
+ bundler-cache: true
237
+ - name: Check documentation coverage
238
+ run: bake decode:index:coverage lib
239
+ ```
240
+
241
+ ### Rake Task Integration
242
+
243
+ Add to your `Rakefile`:
244
+
245
+ ```ruby
246
+ require "decode"
247
+
248
+ desc "Check documentation coverage"
249
+ task :doc_coverage do
250
+ system("bake decode:index:coverage lib") || exit(1)
251
+ end
252
+
253
+ task default: [:test, :doc_coverage]
254
+ ```
@@ -1,242 +1,54 @@
1
- # Getting Started with Decode
1
+ # Getting Started
2
2
 
3
- The Decode gem provides programmatic access to Ruby code structure and metadata. It can parse Ruby files and extract definitions, comments, and documentation pragmas, enabling code analysis, documentation generation, and other programmatic manipulations of Ruby codebases.
3
+ This guide explains how to use `decode` for source code analysis.
4
4
 
5
5
  ## Installation
6
6
 
7
- Add to your Gemfile:
7
+ Add the gem to your project:
8
8
 
9
- ```ruby
10
- gem 'decode'
11
- ```
9
+ ~~~ bash
10
+ $ bundle add decode
11
+ ~~~
12
12
 
13
- Or install directly:
13
+ ## Indexing
14
14
 
15
- ```bash
16
- bundle add decode
17
- ```
15
+ `decode` turns your source code into a kind of database with rich access to definitions, segments and associated comments. Use {ruby Decode::Index} to build an index of your project by loading in source files:
18
16
 
19
- ## Basic Usage
17
+ ~~~ ruby
18
+ require 'decode/index'
20
19
 
21
- ### Analyzing a Ruby File
22
-
23
- ```ruby
24
- require 'decode'
25
-
26
- # Create a source object:
27
- source = Decode::Source.new('lib/my_class.rb', Decode::Language::Ruby.new)
28
-
29
- # Extract definitions (classes, methods, etc.):
30
- definitions = source.definitions.to_a
31
-
32
- definitions.each do |definition|
33
- puts "#{definition.name}: #{definition.short_form}"
34
- end
35
- ```
20
+ index = Decode::Index.new
36
21
 
37
- ### Extracting Documentation
22
+ # Load all Ruby files into the index:
23
+ index.update(Dir['**/*.rb'])
24
+ ~~~
38
25
 
39
- ```ruby
40
- # Get segments (blocks of comments + code):
41
- segments = source.segments.to_a
26
+ Once you've done this, you can print out all the definitions from your project:
42
27
 
43
- segments.each do |segment|
44
- puts "Comments: #{segment.comments.join(' ')}"
45
- puts "Code: #{segment.code}"
28
+ ~~~ ruby
29
+ index.definitions.each do |name, symbol|
30
+ puts symbol.long_form
46
31
  end
47
- ```
48
-
49
- ### Checking Documentation Coverage
32
+ ~~~
50
33
 
51
- ```ruby
52
- # Check which definitions have documentation:
53
- definitions.each do |definition|
54
- status = definition.comments.any? ? 'documented' : 'missing docs'
55
- puts "#{definition.name}: #{status}"
56
- end
57
- ```
58
-
59
- ## Working with Documentation Pragmas
60
-
61
- The Decode gem understands structured documentation pragmas:
62
-
63
- ```ruby
64
- # This will be parsed and structured:
65
- source_code = <<~RUBY
66
- # Represents a user in the system.
67
- class User
68
- # @attribute [String] The user's email address.
69
- attr_reader :email
70
-
71
- # Initialize a new user.
72
- # @parameter email [String] The user's email address.
73
- # @parameter options [Hash] Additional options.
74
- # @option :active [bool] Whether the account is active.
75
- # @raises [ArgumentError] If email is invalid.
76
- def initialize(email, options = {})
77
- # Validate the email format:
78
- raise ArgumentError, "Invalid email" if email.empty?
79
-
80
- # Set instance variables:
81
- @email = email
82
- @active = options.fetch(:active, true)
83
- end
84
- end
85
- RUBY
86
-
87
- # Parse and analyze:
88
- result = Decode::Language::Ruby.new.parser.parse_source(source_code)
89
- definitions = Decode::Language::Ruby.new.parser.definitions_for(source_code).to_a
90
-
91
- definitions.each do |definition|
92
- puts "#{definition.name}: #{definition.comments.join(' ')}"
93
- end
94
- ```
95
-
96
- ## Common Use Cases
97
-
98
- ### 1. Code Analysis and Metrics
99
-
100
- ```ruby
101
- # Analyze a codebase and return metrics.
102
- # @parameter file_path [String] Path to the Ruby file to analyze.
103
- def analyze_codebase(file_path)
104
- source = Decode::Source.new(file_path, Decode::Language::Ruby.new)
105
- definitions = source.definitions.to_a
106
-
107
- # Count different definition types:
108
- classes = definitions.count { |d| d.is_a?(Decode::Language::Ruby::Class) }
109
- methods = definitions.count { |d| d.is_a?(Decode::Language::Ruby::Method) }
110
- modules = definitions.count { |d| d.is_a?(Decode::Language::Ruby::Module) }
111
-
112
- puts "Classes: #{classes}, Methods: #{methods}, Modules: #{modules}"
113
- end
114
- ```
115
-
116
- ### 2. Documentation Coverage Reports
117
-
118
- ```ruby
119
- # Calculate documentation coverage for a file.
120
- # @parameter file_path [String] Path to the Ruby file to analyze.
121
- def documentation_coverage(file_path)
122
- source = Decode::Source.new(file_path, Decode::Language::Ruby.new)
123
- definitions = source.definitions.to_a
124
-
125
- # Calculate coverage statistics:
126
- total = definitions.count
127
- documented = definitions.count { |d| d.comments.any? }
128
-
129
- puts "Coverage: #{documented}/#{total} (#{(documented.to_f / total * 100).round(1)}%)"
130
- end
131
- ```
132
-
133
- ### 3. Extracting API Information
134
-
135
- ```ruby
136
- # Extract API information from a Ruby file.
137
- # @parameter file_path [String] Path to the Ruby file to analyze.
138
- def extract_api_info(file_path)
139
- source = Decode::Source.new(file_path, Decode::Language::Ruby.new)
140
- definitions = source.definitions.to_a
141
-
142
- # Get public methods only:
143
- public_methods = definitions.select do |definition|
144
- definition.is_a?(Decode::Language::Ruby::Method) &&
145
- definition.visibility == :public
146
- end
147
-
148
- public_methods.each do |method|
149
- puts "#{method.long_form}"
150
- puts " Comments: #{method.comments.join(' ')}" if method.comments.any?
151
- end
152
- end
153
- ```
154
-
155
- ### 4. Code Structure Analysis
156
-
157
- ```ruby
158
- # Analyze the structure of Ruby files in a directory.
159
- # @parameter directory [String] Path to the directory to analyze.
160
- def analyze_structure(directory)
161
- Dir.glob("#{directory}/**/*.rb").each do |file|
162
- source = Decode::Source.new(file, Decode::Language::Ruby.new)
163
- definitions = source.definitions.to_a
164
-
165
- # Find nested classes and modules:
166
- nested = definitions.select { |d| d.parent }
167
-
168
- if nested.any?
169
- puts "#{file}:"
170
- nested.each do |definition|
171
- puts " #{definition.qualified_name}"
172
- end
173
- end
174
- end
175
- end
176
- ```
177
-
178
- ### 5. Finding Undocumented Code
179
-
180
- ```ruby
181
- # Find undocumented code in a directory.
182
- # @parameter directory [String] Path to the directory to analyze.
183
- def find_undocumented(directory)
184
- Dir.glob("#{directory}/**/*.rb").each do |file|
185
- source = Decode::Source.new(file, Decode::Language::Ruby.new)
186
- definitions = source.definitions.to_a
187
-
188
- # Filter for undocumented public definitions:
189
- undocumented = definitions.select { |d| d.comments.empty? && d.visibility == :public }
190
-
191
- if undocumented.any?
192
- puts "#{file}:"
193
- undocumented.each do |definition|
194
- puts " - #{definition.short_form}"
195
- end
196
- end
197
- end
198
- end
199
- ```
200
-
201
- ## Advanced Features
202
-
203
- ### Using the Index
204
-
205
- ```ruby
206
- # Create an index for multiple files:
207
- index = Decode::Index.new
208
- index.update(Dir.glob("lib/**/*.rb"))
209
-
210
- # Search through the index:
211
- index.trie.traverse do |path, node, descend|
212
- if node.values
213
- node.values.each do |definition|
214
- puts "#{path.join('::')} - #{definition.short_form}"
215
- end
216
- end
217
- descend.call
218
- end
219
- ```
34
+ ## References
220
35
 
221
- ### Custom Language Support
36
+ References are strings which can be resolved into definitions. The index allows you to efficiently resolve references.
222
37
 
223
- ```ruby
224
- # The decode gem is extensible:
225
- language = Decode::Language::Generic.new("custom")
226
- # You can implement your own parser for other languages:
227
- ```
38
+ ~~~ ruby
39
+ # Lookup a specific symbol:
40
+ reference = index.languages.parse_reference("ruby Decode::Index#lookup")
41
+ definition = index.lookup(reference).first
42
+ puts definition.long_form
43
+ ~~~
228
44
 
229
- ## Tips for Effective Usage
45
+ ## Documentation
230
46
 
231
- 1. **Use structured pragmas** - They help tools understand your code better.
232
- 2. **Leverage programmatic access** - Build tools that analyze and manipulate code.
233
- 3. **Use @namespace** - For organizational modules to achieve complete coverage.
234
- 4. **Analyze code patterns** - Use decode to understand codebase structure.
235
- 5. **Build automation** - Use decode in CI/CD pipelines for code quality checks.
47
+ The {ruby Decode::Documentation} provides rich access to the comments that preceed a definition. This includes metadata including `@parameter`, `@returns` and other tags.
236
48
 
237
- ## Next Steps
49
+ ~~~ ruby
50
+ lines = definition.documentation.text
51
+ puts lines
52
+ ~~~
238
53
 
239
- - See [Ruby Documentation](ruby-documentation.md) for complete pragma reference.
240
- - Check out [Documentation Coverage](coverage.md) for coverage monitoring.
241
- - Use decode to build code analysis tools for your projects.
242
- - Integrate decode into your development workflow and CI/CD pipelines.
54
+ See {ruby Decode::Comment::Node#traverse} for more details about how to consume this data.
@@ -0,0 +1,22 @@
1
+ # Automatically generated context index for Utopia::Project guides.
2
+ # Do not edit then files in this directory directly, instead edit the guides and then run `bake utopia:project:agent:context:update`.
3
+ ---
4
+ description: Code analysis for documentation generation.
5
+ metadata:
6
+ documentation_uri: https://socketry.github.io/decode/
7
+ funding_uri: https://github.com/sponsors/socketry/
8
+ source_code_uri: https://github.com/socketry/decode.git
9
+ files:
10
+ - path: getting-started.md
11
+ title: Getting Started
12
+ description: This guide explains how to use `decode` for source code analysis.
13
+ - path: documentation-coverage.md
14
+ title: Documentation Coverage
15
+ description: This guide explains how to test and monitor documentation coverage
16
+ in your Ruby projects using the Decode gem's built-in bake tasks.
17
+ - path: ruby-documentation.md
18
+ title: Ruby Documentation
19
+ description: This guide covers documentation practices and pragmas supported by
20
+ the Decode gem for documenting Ruby code. These pragmas provide structured documentation
21
+ that can be parsed and used to generate API documentation and achieve complete
22
+ documentation coverage.
@@ -8,27 +8,27 @@ This guide covers documentation practices and pragmas supported by the Decode ge
8
8
 
9
9
  #### Definition Documentation
10
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.
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
15
 
16
16
  #### Inline Code Comments
17
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.
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
20
 
21
21
  #### Links and Code Formatting
22
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`
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
32
 
33
33
  #### Examples
34
34
 
@@ -98,14 +98,14 @@ end
98
98
 
99
99
  ### Best Practices
100
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.
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
109
 
110
110
  #### Simple Attributes and Methods
111
111
 
@@ -247,14 +247,14 @@ Documents block parameters and behavior.
247
247
 
248
248
  ```ruby
249
249
  # @yields {|item| ...} Each item in the collection.
250
- # @parameter item [Object] The current item being processed.
250
+ # @parameter item [Object] The current item being processed.
251
251
  def each_item(&block)
252
252
  items.each(&block)
253
253
  end
254
254
 
255
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.
256
+ # @parameter user [User] The current user.
257
+ # @parameter index [Integer] The user's position in the list.
258
258
  def each_user_with_index(&block)
259
259
  users.each_with_index(&block)
260
260
  end
@@ -308,6 +308,39 @@ def fetch_data
308
308
  end
309
309
  ```
310
310
 
311
+ ### Example Code
312
+
313
+ #### `@example Title?`
314
+
315
+ Includes an example usage snippet for a method or definition. The `@example` directive can have an optional title on the same line, followed by one or more indented lines of code:
316
+
317
+ ```ruby
318
+ # @example Create a new thing
319
+ # thing = Thing.new
320
+ # thing.process
321
+ def process
322
+ # ...
323
+ end
324
+ ```
325
+
326
+ Behaviour:
327
+
328
+ - The optional title is captured verbatim (e.g., `"Create a new thing"`).
329
+ - Indented lines following the directive are captured as the example code.
330
+ - When parsed, examples are available as `Decode::Comment::Example` nodes with:
331
+ - `title` – `String?`, the optional example title.
332
+ - `text` – `Array(String)?`, the raw code lines (including leading indentation).
333
+ - `code` – `String?`, the code as a single string with leading indentation removed (convenience).
334
+
335
+ Multiple `@example` pragmas can be used on the same definition to show different scenarios.
336
+
337
+ ```ruby
338
+ definition.documentation.filter(Decode::Comment::Example) do |example|
339
+ puts "Title: #{example.title.inspect}"
340
+ puts example.code # => joined string with indentation removed
341
+ end
342
+ ```
343
+
311
344
  ### Namespace Documentation
312
345
 
313
346
  #### `@namespace`
@@ -44,4 +44,4 @@ module Decode
44
44
  attr :type
45
45
  end
46
46
  end
47
- end
47
+ end