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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +1 -1
- data/bake/decode/documentation.rb +378 -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 +91 -43
- 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/definition.rb +9 -1
- data/lib/decode/documentation.rb +1 -0
- data/lib/decode/language/generic.rb +2 -0
- data/lib/decode/language/ruby/alias.rb +13 -1
- data/lib/decode/language/ruby/class.rb +14 -1
- data/lib/decode/language/ruby/generic.rb +2 -0
- data/lib/decode/language/ruby/module.rb +19 -1
- data/lib/decode/language/ruby/parser.rb +115 -81
- data/lib/decode/rbs/class.rb +6 -5
- data/lib/decode/rbs/method.rb +11 -11
- data/lib/decode/rbs/module.rb +6 -6
- data/lib/decode/rbs/type.rb +4 -4
- data/lib/decode/scope.rb +1 -1
- data/lib/decode/version.rb +1 -1
- data/license.md +1 -1
- data/readme.md +27 -1
- data/releases.md +8 -0
- data.tar.gz.sig +0 -0
- metadata +7 -5
- metadata.gz.sig +0 -0
- data/context/coverage.md +0 -325
- data/context/types.md +0 -127
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
|
-
```
|