decode 0.25.0 → 0.27.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.
@@ -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,32 +8,38 @@ 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: Should directly describe what the class *is* or *does*.
13
+ - For data/model classes, "A user account in the system." works well.
14
+ - For functional classes (servers, clients, connections), lead with what the class does: "An HTTP client that manages persistent connections...".
15
+ - Method documentation: Should clearly describe what the method does, not how it does it.
16
+ - Markdown format: All documentation comments are written in Markdown format, allowing for rich formatting including lists, emphasis, code blocks, and links.
15
17
 
16
18
  #### Inline Code Comments
17
19
 
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
+ - Explanatory comments: Comments within methods that explain specific lines or sections of code should end with a colon `:` to distinguish them from definition documentation.
21
+ - Purpose: These comments explain the reasoning behind specific implementation details.
20
22
 
21
23
  #### Links and Code Formatting
22
24
 
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`
25
+ - 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.
26
+ - Absolute references: `{Decode::Index#lookup}` - Links to a specific method in a specific class
27
+ - Relative references: `{lookup}` - Links to a method in the current scope or class
28
+ - Class references: `{User}` - Links to a class or module
29
+ - Backticks: Use backticks for code formatting of symbols, values, method names, and technical terms that should appear in monospace font.
30
+ - Symbols: `:admin`, `:user`, `:guest`
31
+ - Values: `true`, `false`, `nil`
32
+ - Technical terms: `attr_*`, `catch`/`throw`
33
+ - Code expressions: `**options`
32
34
 
33
35
  #### Examples
34
36
 
37
+ ##### Data/Model Classes
38
+
39
+ For classes that model domain concepts, describe what the class is:
40
+
35
41
  ```ruby
36
- # Represents a user account in the system.
42
+ # A user account in the system.
37
43
  class User
38
44
  # @attribute [String] The user's email address.
39
45
  attr_reader :email
@@ -70,26 +76,35 @@ class User
70
76
  true
71
77
  end
72
78
  end
79
+ ```
73
80
 
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
81
+ ##### Functional/Service Classes
82
+
83
+ For classes that *do* something (clients, servers, processors), lead with what the class does:
84
+
85
+ ```ruby
86
+ # An HTTP client that manages persistent connections to a remote server, with automatic retries for idempotent requests.
87
+ class Client
88
+ # Send a request to the remote server.
89
+ # @parameter request [Protocol::HTTP::Request] The request to send.
90
+ # @returns [Protocol::HTTP::Response] The response from the server.
91
+ def call(request)
92
+ # ...
93
+ end
94
+
95
+ # Close the client and release all connections.
96
+ def close
97
+ # ...
89
98
  end
90
99
  end
100
+
101
+ # Raised when a connection to the remote server cannot be established.
102
+ class ConnectionError < StandardError
103
+ end
91
104
  ```
92
105
 
106
+ Note the difference: `User` is described as a thing ("A user account..."), while `Client` is described by what it does ("An HTTP client that manages..."), and `ConnectionError` is described by when it occurs ("Raised when...").
107
+
93
108
  **Key formatting examples from above:**
94
109
  - `{disable!}` - Creates a link to the `disable!` method (relative reference)
95
110
  - `active?` - Formats the method name in monospace (backticks for code formatting)
@@ -98,14 +113,14 @@ end
98
113
 
99
114
  ### Best Practices
100
115
 
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.
116
+ 1. Be Consistent: Use the same format for similar types of documentation.
117
+ 2. Include Types: Always specify types for parameters, returns, and attributes.
118
+ 3. Be Descriptive: Provide clear, actionable descriptions.
119
+ 4. Document Exceptions: Always document what exceptions might be raised.
120
+ 5. Use Examples: Include usage examples when the behavior isn't obvious.
121
+ 6. Keep Updated: Update documentation when you change the code.
122
+ 7. Use @namespace wisely: Apply to organizational modules to achieve 100% coverage.
123
+ 8. Avoid redundancy: For simple attributes and methods, attach descriptions directly to pragmas rather than repeating obvious information.
109
124
 
110
125
  #### Simple Attributes and Methods
111
126
 
@@ -155,7 +170,7 @@ Type signatures are used to specify the expected types of parameters, return val
155
170
  Documents class attributes, instance variables, and `attr_*` declarations. Prefer to have one attribute per line for clarity.
156
171
 
157
172
  ```ruby
158
- # Represents a person with basic attributes.
173
+ # A person with basic attributes.
159
174
  class Person
160
175
  # @attribute [String] The person's full name.
161
176
  attr_reader :name
@@ -247,14 +262,14 @@ Documents block parameters and behavior.
247
262
 
248
263
  ```ruby
249
264
  # @yields {|item| ...} Each item in the collection.
250
- # @parameter item [Object] The current item being processed.
265
+ # @parameter item [Object] The current item being processed.
251
266
  def each_item(&block)
252
267
  items.each(&block)
253
268
  end
254
269
 
255
270
  # @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.
271
+ # @parameter user [User] The current user.
272
+ # @parameter index [Integer] The user's position in the list.
258
273
  def each_user_with_index(&block)
259
274
  users.each_with_index(&block)
260
275
  end
@@ -308,6 +323,39 @@ def fetch_data
308
323
  end
309
324
  ```
310
325
 
326
+ ### Example Code
327
+
328
+ #### `@example Title?`
329
+
330
+ 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:
331
+
332
+ ```ruby
333
+ # @example Create a new thing
334
+ # thing = Thing.new
335
+ # thing.process
336
+ def process
337
+ # ...
338
+ end
339
+ ```
340
+
341
+ Behaviour:
342
+
343
+ - The optional title is captured verbatim (e.g., `"Create a new thing"`).
344
+ - Indented lines following the directive are captured as the example code.
345
+ - When parsed, examples are available as `Decode::Comment::Example` nodes with:
346
+ - `title` – `String?`, the optional example title.
347
+ - `text` – `Array(String)?`, the raw code lines (including leading indentation).
348
+ - `code` – `String?`, the code as a single string with leading indentation removed (convenience).
349
+
350
+ Multiple `@example` pragmas can be used on the same definition to show different scenarios.
351
+
352
+ ```ruby
353
+ definition.documentation.filter(Decode::Comment::Example) do |example|
354
+ puts "Title: #{example.title.inspect}"
355
+ puts example.code # => joined string with indentation removed
356
+ end
357
+ ```
358
+
311
359
  ### Namespace Documentation
312
360
 
313
361
  #### `@namespace`
@@ -44,4 +44,4 @@ module Decode
44
44
  attr :type
45
45
  end
46
46
  end
47
- end
47
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2025, by Samuel Williams.
5
+
6
+ require_relative "tag"
7
+
8
+ module Decode
9
+ module Comment
10
+ # Represents a code example with an optional title.
11
+ #
12
+ # - `@example Title`
13
+ # - `@example`
14
+ #
15
+ # Should contain nested text lines representing the example code.
16
+ class Example < Tag
17
+ # Parse an example directive from text.
18
+ # @parameter directive [String] The directive name.
19
+ # @parameter text [String?] The optional title text.
20
+ # @parameter lines [Array(String)] The remaining lines.
21
+ # @parameter tags [Tags] The tags parser.
22
+ # @parameter level [Integer] The indentation level.
23
+ def self.parse(directive, text, lines, tags, level = 0)
24
+ node = self.new(directive, text)
25
+
26
+ tags.parse(lines, level + 1) do |child|
27
+ node.add(child)
28
+ end
29
+
30
+ return node
31
+ end
32
+
33
+ # Initialize a new example tag.
34
+ # @parameter directive [String] The directive name.
35
+ # @parameter title [String?] The optional title for the example.
36
+ def initialize(directive, title = nil)
37
+ super(directive)
38
+
39
+ # @type ivar @title: String?
40
+ @title = title&.strip unless title&.empty?
41
+ end
42
+
43
+ # @attribute [String?] The title of the example.
44
+ attr :title
45
+
46
+ # Get the example code as a single string with leading indentation removed.
47
+ # @returns [String?] The example code joined with newlines, or nil if no code.
48
+ def code
49
+ lines = text
50
+ return unless lines
51
+
52
+ # Get the indentation from the first line
53
+ if indentation = lines.first[/\A\s+/]
54
+ # Remove the base indentation from all lines
55
+ lines = lines.map{|line| line.sub(indentation, "")}
56
+ end
57
+
58
+ return lines.join("\n")
59
+ end
60
+ end
61
+ end
62
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2024, by Samuel Williams.
4
+ # Copyright, 2024-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "parameter"
7
7
 
@@ -21,6 +21,7 @@ module Decode
21
21
  def self.build(directive, match)
22
22
  raise NotImplementedError, "Subclasses must implement build method"
23
23
  end
24
+
24
25
  # Build a pattern for bracketed content, supporting nested brackets.
25
26
  # @parameter name [Symbol] The name of the group.
26
27
  # @returns [String] The pattern.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2020-2025, by Samuel Williams.
4
+ # Copyright, 2020-2026, by Samuel Williams.
5
5
 
6
6
  require_relative "location"
7
7
 
@@ -166,6 +166,14 @@ module Decode
166
166
  false
167
167
  end
168
168
 
169
+ # Whether this definition represents an alias to another definition.
170
+ # Tools can use this to filter aliases from outputs without parsing text.
171
+ #
172
+ # @returns [bool] False by default; specific definition types may override.
173
+ def alias?
174
+ false
175
+ end
176
+
169
177
  # Whether this represents a single entity to be documented (along with it's contents).
170
178
  #
171
179
  # @returns [bool]
@@ -15,6 +15,7 @@ require_relative "comment/raises"
15
15
  require_relative "comment/returns"
16
16
  require_relative "comment/throws"
17
17
  require_relative "comment/yields"
18
+ require_relative "comment/example"
18
19
 
19
20
  module Decode
20
21
  # Structured access to a set of comment lines.
@@ -27,6 +27,8 @@ module Decode
27
27
 
28
28
  tags["public"] = Comment::Pragma
29
29
  tags["private"] = Comment::Pragma
30
+
31
+ tags["example"] = Comment::Example
30
32
  end
31
33
 
32
34
  # Initialize a new generic language.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2025, by Samuel Williams.
4
+ # Copyright, 2025-2026, by Samuel Williams.
5
5
 
6
6
  require_relative "definition"
7
7
 
@@ -21,6 +21,18 @@ module Decode
21
21
 
22
22
  attr :old_name
23
23
 
24
+ # Whether this definition represents an alias.
25
+ # @returns [bool] Always true for aliases.
26
+ def alias?
27
+ true
28
+ end
29
+
30
+ # The original name this alias refers to.
31
+ # @returns [Symbol]
32
+ def aliased_name
33
+ @old_name
34
+ end
35
+
24
36
  # Aliases don't require separate documentation as they reference existing methods.
25
37
  # @returns [bool] Always false for aliases.
26
38
  def coverage_relevant?