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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/context/documentation-coverage.md +254 -0
- data/context/getting-started.md +34 -222
- data/context/index.yaml +22 -0
- data/context/ruby-documentation.md +59 -26
- data/lib/decode/comment/constant.rb +1 -1
- data/lib/decode/comment/example.rb +62 -0
- data/lib/decode/comment/option.rb +1 -1
- data/lib/decode/comment/tag.rb +1 -0
- data/lib/decode/documentation.rb +1 -0
- data/lib/decode/language/generic.rb +2 -0
- data/lib/decode/language/ruby/generic.rb +2 -0
- data/lib/decode/language/ruby/parser.rb +2 -2
- data/lib/decode/rbs/type.rb +2 -2
- data/lib/decode/scope.rb +1 -1
- data/lib/decode/version.rb +1 -1
- data/readme.md +7 -1
- data/releases.md +4 -0
- data.tar.gz.sig +1 -3
- metadata +5 -4
- metadata.gz.sig +0 -0
- data/context/coverage.md +0 -325
- data/context/types.md +0 -127
|
@@ -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
|
data/lib/decode/comment/tag.rb
CHANGED
|
@@ -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.
|
data/lib/decode/documentation.rb
CHANGED
data/lib/decode/rbs/type.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright,
|
|
4
|
+
# Copyright, 2025, by Samuel Williams.
|
|
5
5
|
|
|
6
6
|
require "rbs"
|
|
7
7
|
require "console"
|
|
@@ -49,4 +49,4 @@ module Decode
|
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
|
-
end
|
|
52
|
+
end
|
data/lib/decode/scope.rb
CHANGED
data/lib/decode/version.rb
CHANGED
data/readme.md
CHANGED
|
@@ -14,14 +14,20 @@ Please see the [project documentation](https://socketry.github.io/decode/) for m
|
|
|
14
14
|
|
|
15
15
|
- [Getting Started](https://socketry.github.io/decode/guides/getting-started/index) - This guide explains how to use `decode` for source code analysis.
|
|
16
16
|
|
|
17
|
-
- [
|
|
17
|
+
- [Documentation Coverage](https://socketry.github.io/decode/guides/documentation-coverage/index) - This guide explains how to test and monitor documentation coverage in your Ruby projects using the Decode gem's built-in bake tasks.
|
|
18
18
|
|
|
19
19
|
- [Extract Symbols](https://socketry.github.io/decode/guides/extract-symbols/index) - This example demonstrates how to extract symbols using the index. An instance of <code class="language-ruby">Decode::Index</code> is used for loading symbols from source code files. These symbols are available as a flat list and as a trie structure. You can look up specific symbols using a reference using <code class="language-ruby">Decode::Index\#lookup</code>.
|
|
20
20
|
|
|
21
|
+
- [Ruby Documentation](https://socketry.github.io/decode/guides/ruby-documentation/index) - 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.
|
|
22
|
+
|
|
21
23
|
## Releases
|
|
22
24
|
|
|
23
25
|
Please see the [project releases](https://socketry.github.io/decode/releases/index) for all releases.
|
|
24
26
|
|
|
27
|
+
### v0.26.0
|
|
28
|
+
|
|
29
|
+
- Add support for `@example` pragmas in Ruby documentation comments.
|
|
30
|
+
|
|
25
31
|
### v0.25.0
|
|
26
32
|
|
|
27
33
|
- Singleton classes are not relevant for coverage, so they are now ignored by the coverage reporter.
|
data/releases.md
CHANGED
data.tar.gz.sig
CHANGED
|
@@ -1,3 +1 @@
|
|
|
1
|
-
|
|
2
|
-
�R#=`|��9��R�ݍ�_���,M��
|
|
3
|
-
��3I �n�j��C�PƎ`�IC�e������#�R-e�[y +�T���c���lt�(.��D_�5J�KO�%c=�~
|
|
1
|
+
s�]f����w��b�C˦�MOJ��ƛ瞾ן��\#hnR}�?|6�\�i��`��sN����k3���b�d�)�2*2�~��6iw�!E���a�~��ՠ��SG¨b��3@��Sx|��Q���4���h��P�e1���w3By�[���e_М�U5��K�aHVX�jc��ҝ�+v������k���O�����y��^2��{X�#��.m�"��7���4?[�c��=��3��������|Q�ln��Ў��x��Hl�6�e���H�륹H���D�����'����_A���䈡Ԡ�$���m![p%`aF\��E3�P�������Q�(NO:������h���4}�g���H��ZMy$�4
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: decode
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.26.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samuel Williams
|
|
@@ -73,13 +73,14 @@ files:
|
|
|
73
73
|
- agent.md
|
|
74
74
|
- bake/decode/index.rb
|
|
75
75
|
- bake/decode/rbs.rb
|
|
76
|
-
- context/coverage.md
|
|
76
|
+
- context/documentation-coverage.md
|
|
77
77
|
- context/getting-started.md
|
|
78
|
+
- context/index.yaml
|
|
78
79
|
- context/ruby-documentation.md
|
|
79
|
-
- context/types.md
|
|
80
80
|
- lib/decode.rb
|
|
81
81
|
- lib/decode/comment/attribute.rb
|
|
82
82
|
- lib/decode/comment/constant.rb
|
|
83
|
+
- lib/decode/comment/example.rb
|
|
83
84
|
- lib/decode/comment/node.rb
|
|
84
85
|
- lib/decode/comment/option.rb
|
|
85
86
|
- lib/decode/comment/parameter.rb
|
|
@@ -156,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
156
157
|
- !ruby/object:Gem::Version
|
|
157
158
|
version: '0'
|
|
158
159
|
requirements: []
|
|
159
|
-
rubygems_version: 3.
|
|
160
|
+
rubygems_version: 3.7.2
|
|
160
161
|
specification_version: 4
|
|
161
162
|
summary: Code analysis for documentation generation.
|
|
162
163
|
test_files: []
|
metadata.gz.sig
CHANGED
|
Binary file
|
data/context/coverage.md
DELETED
|
@@ -1,325 +0,0 @@
|
|
|
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
|
-
### Understanding Coverage Output
|
|
26
|
-
|
|
27
|
-
When you run the coverage command, you'll see output like:
|
|
28
|
-
|
|
29
|
-
```
|
|
30
|
-
15 definitions have documentation, out of 20 public definitions.
|
|
31
|
-
|
|
32
|
-
Missing documentation for:
|
|
33
|
-
- MyGem::SomeClass#method_name
|
|
34
|
-
- MyGem::AnotherClass
|
|
35
|
-
- MyGem::Utility.helper_method
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
The coverage check:
|
|
39
|
-
- **Counts only public definitions** (public methods, classes, modules).
|
|
40
|
-
- **Reports the ratio** of documented vs total public definitions.
|
|
41
|
-
- **Lists missing documentation** by qualified name.
|
|
42
|
-
- **Fails with an error** if coverage is incomplete.
|
|
43
|
-
|
|
44
|
-
### What Counts as "Documented"
|
|
45
|
-
|
|
46
|
-
A definition is considered documented if it has:
|
|
47
|
-
- Any comment preceding it.
|
|
48
|
-
- Documentation pragmas (like `@parameter`, `@returns`).
|
|
49
|
-
- A `@namespace` pragma (for organizational modules).
|
|
50
|
-
|
|
51
|
-
```ruby
|
|
52
|
-
# Represents a user in the system.
|
|
53
|
-
class MyClass
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# @namespace
|
|
57
|
-
module OrganizationalModule
|
|
58
|
-
# Contains helper functionality.
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# Process user data and return formatted results.
|
|
62
|
-
# @parameter name [String] The user's name.
|
|
63
|
-
# @returns [bool] Success status.
|
|
64
|
-
def process(name)
|
|
65
|
-
# Validation logic here:
|
|
66
|
-
return false if name.empty?
|
|
67
|
-
|
|
68
|
-
# Processing logic:
|
|
69
|
-
true
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
class UndocumentedClass
|
|
73
|
-
end
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## Analyzing Symbols
|
|
77
|
-
|
|
78
|
-
### List All Symbols
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
# See the structure of your codebase
|
|
82
|
-
bake decode:index:symbols lib
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
This shows the hierarchical structure of your code:
|
|
86
|
-
|
|
87
|
-
```
|
|
88
|
-
[] -> []
|
|
89
|
-
["MyGem"] -> [#<Decode::Language::Ruby::Module:...>]
|
|
90
|
-
MyGem
|
|
91
|
-
["MyGem", "User"] -> [#<Decode::Language::Ruby::Class:...>]
|
|
92
|
-
MyGem::User
|
|
93
|
-
["MyGem", "User", "initialize"] -> [#<Decode::Language::Ruby::Method:...>]
|
|
94
|
-
MyGem::User#initialize
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### Extract Documentation
|
|
98
|
-
|
|
99
|
-
```bash
|
|
100
|
-
# Extract all documentation from your codebase
|
|
101
|
-
bake decode:index:documentation lib
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
This outputs formatted documentation for all documented definitions:
|
|
105
|
-
|
|
106
|
-
~~~markdown
|
|
107
|
-
## `MyGem::User#initialize`
|
|
108
|
-
|
|
109
|
-
Initialize a new user with the given email address.
|
|
110
|
-
|
|
111
|
-
## `MyGem::User#authenticate`
|
|
112
|
-
|
|
113
|
-
Authenticate the user with a password.
|
|
114
|
-
Returns true if authentication is successful.
|
|
115
|
-
~~~
|
|
116
|
-
|
|
117
|
-
## Achieving 100% Coverage
|
|
118
|
-
|
|
119
|
-
### Strategy for Complete Coverage
|
|
120
|
-
|
|
121
|
-
1. **Document all public APIs**
|
|
122
|
-
```ruby
|
|
123
|
-
# Represents a user management system.
|
|
124
|
-
class User
|
|
125
|
-
# @attribute [String] The user's email address.
|
|
126
|
-
attr_reader :email
|
|
127
|
-
|
|
128
|
-
# Initialize a new user.
|
|
129
|
-
# @parameter email [String] The user's email address.
|
|
130
|
-
def initialize(email)
|
|
131
|
-
# Store the email address:
|
|
132
|
-
@email = email
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
2. **Use @namespace for organizational modules**
|
|
138
|
-
```ruby
|
|
139
|
-
# @namespace
|
|
140
|
-
module MyGem
|
|
141
|
-
# Contains the main functionality.
|
|
142
|
-
end
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
3. **Document edge cases**
|
|
146
|
-
```ruby
|
|
147
|
-
# @private
|
|
148
|
-
def internal_helper
|
|
149
|
-
# Internal implementation details.
|
|
150
|
-
end
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
### Common Coverage Issues
|
|
154
|
-
|
|
155
|
-
**Issue: Missing namespace documentation**
|
|
156
|
-
```ruby
|
|
157
|
-
# This module has no documentation and will show as missing coverage:
|
|
158
|
-
module MyGem
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
# Solution: Add @namespace pragma:
|
|
162
|
-
# @namespace
|
|
163
|
-
module MyGem
|
|
164
|
-
# Provides core functionality.
|
|
165
|
-
end
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
**Issue: Undocumented methods**
|
|
169
|
-
|
|
170
|
-
Problem: Methods without any comments will show as missing coverage:
|
|
171
|
-
```ruby
|
|
172
|
-
def process_data
|
|
173
|
-
# Implementation here
|
|
174
|
-
end
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
Solution: Add description and pragmas:
|
|
178
|
-
```ruby
|
|
179
|
-
# Process the input data and return results.
|
|
180
|
-
# @parameter data [Hash] Input data to process.
|
|
181
|
-
# @returns [Array] Processed results.
|
|
182
|
-
def process_data(data)
|
|
183
|
-
# Process the input:
|
|
184
|
-
results = data.map { |item| transform(item) }
|
|
185
|
-
|
|
186
|
-
# Return processed results:
|
|
187
|
-
results
|
|
188
|
-
end
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
**Issue: Missing attr documentation**
|
|
192
|
-
|
|
193
|
-
Problem: Attributes without documentation will show as missing coverage:
|
|
194
|
-
```ruby
|
|
195
|
-
attr_reader :name
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
Solution: Document with @attribute pragma:
|
|
199
|
-
```ruby
|
|
200
|
-
# @attribute [String] The user's full name.
|
|
201
|
-
attr_reader :name
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
## Integrating into CI/CD
|
|
205
|
-
|
|
206
|
-
### GitHub Actions Example
|
|
207
|
-
|
|
208
|
-
```yaml
|
|
209
|
-
name: Documentation Coverage
|
|
210
|
-
|
|
211
|
-
on: [push, pull_request]
|
|
212
|
-
|
|
213
|
-
jobs:
|
|
214
|
-
docs:
|
|
215
|
-
runs-on: ubuntu-latest
|
|
216
|
-
steps:
|
|
217
|
-
- uses: actions/checkout@v3
|
|
218
|
-
- uses: ruby/setup-ruby@v1
|
|
219
|
-
with:
|
|
220
|
-
bundler-cache: true
|
|
221
|
-
- name: Check documentation coverage
|
|
222
|
-
run: bake decode:index:coverage lib
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
### Rake Task Integration
|
|
226
|
-
|
|
227
|
-
Add to your `Rakefile`:
|
|
228
|
-
|
|
229
|
-
```ruby
|
|
230
|
-
require 'decode'
|
|
231
|
-
|
|
232
|
-
desc "Check documentation coverage"
|
|
233
|
-
task :doc_coverage do
|
|
234
|
-
system("bake decode:index:coverage lib") || exit(1)
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
task default: [:test, :doc_coverage]
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
## Monitoring Coverage Over Time
|
|
241
|
-
|
|
242
|
-
### Generate Coverage Reports
|
|
243
|
-
|
|
244
|
-
```ruby
|
|
245
|
-
# Generate a coverage percentage for the specified directory.
|
|
246
|
-
# @parameter root [String] The root directory to analyze.
|
|
247
|
-
# @returns [Float] The coverage percentage.
|
|
248
|
-
def coverage_percentage(root)
|
|
249
|
-
index = Decode::Index.new
|
|
250
|
-
index.update(Dir.glob(File.join(root, "**/*.rb")))
|
|
251
|
-
|
|
252
|
-
documented = 0
|
|
253
|
-
total = 0
|
|
254
|
-
|
|
255
|
-
index.trie.traverse do |path, node, descend|
|
|
256
|
-
node.values&.each do |definition|
|
|
257
|
-
if definition.coverage_relevant?
|
|
258
|
-
total += 1
|
|
259
|
-
documented += 1 if definition.comments&.any?
|
|
260
|
-
end
|
|
261
|
-
end
|
|
262
|
-
descend.call if node.values.nil?
|
|
263
|
-
end
|
|
264
|
-
|
|
265
|
-
(documented.to_f / total * 100).round(2)
|
|
266
|
-
end
|
|
267
|
-
|
|
268
|
-
puts "Coverage: #{coverage_percentage('lib')}%"
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
### Exclude Patterns
|
|
272
|
-
|
|
273
|
-
If you need to exclude certain files from coverage:
|
|
274
|
-
|
|
275
|
-
```ruby
|
|
276
|
-
# Custom coverage script with exclusions.
|
|
277
|
-
paths = Dir.glob("lib/**/*.rb").reject do |path|
|
|
278
|
-
# Exclude vendor files and test files:
|
|
279
|
-
path.include?('vendor/') || path.end_with?('_test.rb')
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
index = Decode::Index.new
|
|
283
|
-
index.update(paths)
|
|
284
|
-
# ... continue with coverage analysis
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
## Best Practices
|
|
288
|
-
|
|
289
|
-
1. **Run coverage checks regularly** - Include in your CI pipeline
|
|
290
|
-
2. **Set coverage targets** - Aim for 100% coverage of public APIs
|
|
291
|
-
3. **Document incrementally** - Add documentation as you write code
|
|
292
|
-
4. **Use meaningful descriptions** - Don't just add empty comments
|
|
293
|
-
5. **Leverage @namespace** - For modules that only serve as containers
|
|
294
|
-
6. **Review coverage reports** - Use the missing documentation list to prioritize
|
|
295
|
-
|
|
296
|
-
## Troubleshooting
|
|
297
|
-
|
|
298
|
-
### Common Error Messages
|
|
299
|
-
|
|
300
|
-
**"Insufficient documentation!"**
|
|
301
|
-
- Some public definitions are missing documentation
|
|
302
|
-
- Check the list of missing items and add appropriate comments
|
|
303
|
-
|
|
304
|
-
**No output from coverage command**
|
|
305
|
-
- Verify the path exists: `bake decode:index:coverage lib`
|
|
306
|
-
- Check that Ruby files exist in the specified directory
|
|
307
|
-
|
|
308
|
-
**Coverage shows 0/0 definitions**
|
|
309
|
-
- The directory might not contain any Ruby files
|
|
310
|
-
- Try a different path or check your file extensions
|
|
311
|
-
|
|
312
|
-
### Debug Coverage Issues
|
|
313
|
-
|
|
314
|
-
```bash
|
|
315
|
-
# First, see what symbols are being detected
|
|
316
|
-
bake decode:index:symbols lib
|
|
317
|
-
|
|
318
|
-
# Then check what documentation exists
|
|
319
|
-
bake decode:index:documentation lib
|
|
320
|
-
|
|
321
|
-
# Finally, run coverage to see what's missing
|
|
322
|
-
bake decode:index:coverage lib
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
This workflow helps you understand what the tool is detecting and why certain items might be missing documentation.
|
data/context/types.md
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
# Setting Up RBS Types and Steep Type Checking for Ruby Gems
|
|
2
|
-
|
|
3
|
-
This guide covers the process for establishing robust type checking in Ruby gems using RBS and Steep, focusing on automated generation from source documentation and proper validation.
|
|
4
|
-
|
|
5
|
-
## Core Process
|
|
6
|
-
|
|
7
|
-
### Documentation-Driven RBS Generation
|
|
8
|
-
|
|
9
|
-
Generate RBS files from documentation:
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
bake decode:rbs:generate lib > sig/example/gem.rbs`
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
At a minimum, add `@parameter`, `@attribute` and `@returns` documentation to all public methods.
|
|
16
|
-
|
|
17
|
-
#### Parametric Types
|
|
18
|
-
|
|
19
|
-
Use `@rbs generic` comments to define type parameters for classes and modules:
|
|
20
|
-
|
|
21
|
-
```ruby
|
|
22
|
-
# @rbs generic T
|
|
23
|
-
class Container
|
|
24
|
-
# @parameter item [T] The item to store
|
|
25
|
-
def initialize(item)
|
|
26
|
-
@item = item
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# @returns [T] The stored item
|
|
30
|
-
def get
|
|
31
|
-
@item
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Use `@rbs` comments for parametric method signatures:
|
|
37
|
-
|
|
38
|
-
```ruby
|
|
39
|
-
# From above:
|
|
40
|
-
class Container
|
|
41
|
-
# @rbs () { (T) -> void } -> void
|
|
42
|
-
def each
|
|
43
|
-
yield @item
|
|
44
|
-
end
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
#### Interfaces
|
|
48
|
-
|
|
49
|
-
Create interfaces in `sig/example/gem/interface.rbs`:
|
|
50
|
-
|
|
51
|
-
```rbs
|
|
52
|
-
module Example
|
|
53
|
-
module Gem
|
|
54
|
-
interface _Interface
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
You can use the interface in `@parameter`, `@attribute` and `@returns` types.
|
|
61
|
-
|
|
62
|
-
### Testing
|
|
63
|
-
|
|
64
|
-
Run tests using the `steep` gem.
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
steep check
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
**Process**: Start with basic generation, then refine based on Steep feedback.
|
|
71
|
-
|
|
72
|
-
1. Generate initial RBS from documentation
|
|
73
|
-
2. Run `steep check lib` to identify issues
|
|
74
|
-
3. Fix structural problems (inheritance, missing docs)
|
|
75
|
-
4. Iterate until clean validation
|
|
76
|
-
|
|
77
|
-
### Deploymnet
|
|
78
|
-
|
|
79
|
-
Make sure `bake-test-types` is added to the `test` group in `gems.rb` (or `Gemfile`).
|
|
80
|
-
|
|
81
|
-
```ruby
|
|
82
|
-
group :test do
|
|
83
|
-
# ...
|
|
84
|
-
gem "bake-test"
|
|
85
|
-
gem "bake-test-external"
|
|
86
|
-
gem "bake-test-types"
|
|
87
|
-
# ...
|
|
88
|
-
end
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
Then, create `.github/workflows/test-types.yaml`:
|
|
92
|
-
|
|
93
|
-
```yaml
|
|
94
|
-
name: Test Types
|
|
95
|
-
|
|
96
|
-
on: [push, pull_request]
|
|
97
|
-
|
|
98
|
-
permissions:
|
|
99
|
-
contents: read
|
|
100
|
-
|
|
101
|
-
env:
|
|
102
|
-
CONSOLE_OUTPUT: XTerm
|
|
103
|
-
|
|
104
|
-
jobs:
|
|
105
|
-
test:
|
|
106
|
-
name: ${{matrix.ruby}} on ${{matrix.os}}
|
|
107
|
-
runs-on: ${{matrix.os}}-latest
|
|
108
|
-
|
|
109
|
-
strategy:
|
|
110
|
-
matrix:
|
|
111
|
-
os:
|
|
112
|
-
- ubuntu
|
|
113
|
-
|
|
114
|
-
ruby:
|
|
115
|
-
- "3.4"
|
|
116
|
-
|
|
117
|
-
steps:
|
|
118
|
-
- uses: actions/checkout@v4
|
|
119
|
-
- uses: ruby/setup-ruby@v1
|
|
120
|
-
with:
|
|
121
|
-
ruby-version: ${{matrix.ruby}}
|
|
122
|
-
bundler-cache: true
|
|
123
|
-
|
|
124
|
-
- name: Run tests
|
|
125
|
-
timeout-minutes: 10
|
|
126
|
-
run: bundle exec bake test:types
|
|
127
|
-
```
|