docscribe 1.1.0 → 1.2.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
- data/README.md +662 -187
- data/exe/docscribe +2 -126
- data/lib/docscribe/cli/config_builder.rb +62 -0
- data/lib/docscribe/cli/init.rb +58 -0
- data/lib/docscribe/cli/options.rb +204 -0
- data/lib/docscribe/cli/run.rb +415 -0
- data/lib/docscribe/cli.rb +31 -0
- data/lib/docscribe/config/defaults.rb +71 -0
- data/lib/docscribe/config/emit.rb +126 -0
- data/lib/docscribe/config/filtering.rb +160 -0
- data/lib/docscribe/config/loader.rb +59 -0
- data/lib/docscribe/config/rbs.rb +51 -0
- data/lib/docscribe/config/sorbet.rb +87 -0
- data/lib/docscribe/config/sorting.rb +23 -0
- data/lib/docscribe/config/template.rb +176 -0
- data/lib/docscribe/config/utils.rb +102 -0
- data/lib/docscribe/config.rb +20 -230
- data/lib/docscribe/infer/ast_walk.rb +28 -0
- data/lib/docscribe/infer/constants.rb +11 -0
- data/lib/docscribe/infer/literals.rb +55 -0
- data/lib/docscribe/infer/names.rb +43 -0
- data/lib/docscribe/infer/params.rb +62 -0
- data/lib/docscribe/infer/raises.rb +68 -0
- data/lib/docscribe/infer/returns.rb +171 -0
- data/lib/docscribe/infer.rb +104 -258
- data/lib/docscribe/inline_rewriter/collector.rb +845 -0
- data/lib/docscribe/inline_rewriter/doc_block.rb +383 -0
- data/lib/docscribe/inline_rewriter/doc_builder.rb +605 -0
- data/lib/docscribe/inline_rewriter/source_helpers.rb +228 -0
- data/lib/docscribe/inline_rewriter/tag_sorter.rb +244 -0
- data/lib/docscribe/inline_rewriter.rb +599 -428
- data/lib/docscribe/parsing.rb +55 -44
- data/lib/docscribe/types/provider_chain.rb +37 -0
- data/lib/docscribe/types/rbs/provider.rb +213 -0
- data/lib/docscribe/types/rbs/type_formatter.rb +132 -0
- data/lib/docscribe/types/signature.rb +65 -0
- data/lib/docscribe/types/sorbet/base_provider.rb +217 -0
- data/lib/docscribe/types/sorbet/rbi_provider.rb +35 -0
- data/lib/docscribe/types/sorbet/source_provider.rb +25 -0
- data/lib/docscribe/version.rb +1 -1
- metadata +37 -3
data/README.md
CHANGED
|
@@ -13,26 +13,63 @@ returns), and respects Ruby visibility semantics — without using YARD to parse
|
|
|
13
13
|
|
|
14
14
|
- No AST reprinting. Your original code, formatting, and constructs (like `class << self`, `heredocs`, `%i[]`) are
|
|
15
15
|
preserved.
|
|
16
|
-
- Inline-first. Comments are inserted
|
|
16
|
+
- Inline-first. Comments are inserted before method headers without reprinting the AST. For methods with a leading
|
|
17
|
+
Sorbet `sig`, new docs are inserted above the first `sig`.
|
|
17
18
|
- Heuristic type inference for params and return values, including conditional returns in rescue branches.
|
|
18
|
-
-
|
|
19
|
+
- Safe and aggressive update modes:
|
|
20
|
+
- safe mode inserts missing docs, merges existing doc-like blocks, and normalizes sortable tags;
|
|
21
|
+
- aggressive mode rebuilds existing doc blocks.
|
|
19
22
|
- Ruby 3.4+ syntax supported using Prism translation (see "Parser backend" below).
|
|
23
|
+
- Optional external type integrations:
|
|
24
|
+
- RBS via `--rbs` / `--sig-dir`;
|
|
25
|
+
- Sorbet via inline `sig` declarations and RBI files with `--sorbet` / `--rbi-dir`.
|
|
26
|
+
- Optional `@!attribute` generation for:
|
|
27
|
+
- `attr_reader` / `attr_writer` / `attr_accessor`;
|
|
28
|
+
- `Struct.new` declarations in both constant-assigned and class-based styles.
|
|
20
29
|
|
|
21
|
-
|
|
22
|
-
|
|
30
|
+
Common workflows:
|
|
31
|
+
|
|
32
|
+
- Inspect what safe doc updates would be applied: `docscribe lib`
|
|
33
|
+
- Apply safe doc updates: `docscribe -a lib`
|
|
34
|
+
- Apply aggressive doc updates: `docscribe -A lib`
|
|
35
|
+
- Use RBS signatures when available: `docscribe -a --rbs --sig-dir sig lib`
|
|
36
|
+
- Use Sorbet signatures when available: `docscribe -a --sorbet --rbi-dir sorbet/rbi lib`
|
|
37
|
+
|
|
38
|
+
## Contents
|
|
23
39
|
|
|
24
40
|
* [Docscribe](#docscribe)
|
|
41
|
+
* [Contents](#contents)
|
|
25
42
|
* [Installation](#installation)
|
|
26
43
|
* [Quick start](#quick-start)
|
|
27
44
|
* [CLI](#cli)
|
|
28
|
-
|
|
29
|
-
* [
|
|
45
|
+
* [Options](#options)
|
|
46
|
+
* [Examples](#examples)
|
|
47
|
+
* [Update strategies](#update-strategies)
|
|
48
|
+
* [Safe strategy](#safe-strategy)
|
|
49
|
+
* [Aggressive strategy](#aggressive-strategy)
|
|
50
|
+
* [Output markers](#output-markers)
|
|
51
|
+
* [Parser backend (Parser gem vs Prism)](#parser-backend-parser-gem-vs-prism)
|
|
52
|
+
* [External type integrations (optional)](#external-type-integrations-optional)
|
|
53
|
+
* [RBS](#rbs)
|
|
54
|
+
* [Sorbet](#sorbet)
|
|
55
|
+
* [Inline Sorbet example](#inline-sorbet-example)
|
|
56
|
+
* [Sorbet RBI example](#sorbet-rbi-example)
|
|
57
|
+
* [Sorbet comment placement](#sorbet-comment-placement)
|
|
58
|
+
* [Generic type formatting](#generic-type-formatting)
|
|
59
|
+
* [Notes and fallback behavior](#notes-and-fallback-behavior)
|
|
30
60
|
* [Type inference](#type-inference)
|
|
31
61
|
* [Rescue-aware returns and @raise](#rescue-aware-returns-and-raise)
|
|
32
62
|
* [Visibility semantics](#visibility-semantics)
|
|
33
63
|
* [API (library) usage](#api-library-usage)
|
|
34
64
|
* [Configuration](#configuration)
|
|
35
|
-
* [
|
|
65
|
+
* [Filtering](#filtering)
|
|
66
|
+
* [`attr_*` example](#attr_-example)
|
|
67
|
+
* [`Struct.new` examples](#structnew-examples)
|
|
68
|
+
* [Constant-assigned struct](#constant-assigned-struct)
|
|
69
|
+
* [Class-based struct](#class-based-struct)
|
|
70
|
+
* [Merge behavior](#merge-behavior)
|
|
71
|
+
* [Param tag style](#param-tag-style)
|
|
72
|
+
* [Create a starter config](#create-a-starter-config)
|
|
36
73
|
* [CI integration](#ci-integration)
|
|
37
74
|
* [Comparison to YARD's parser](#comparison-to-yards-parser)
|
|
38
75
|
* [Limitations](#limitations)
|
|
@@ -45,7 +82,7 @@ source structure and exact control over Ruby semantics.
|
|
|
45
82
|
Add to your Gemfile:
|
|
46
83
|
|
|
47
84
|
```ruby
|
|
48
|
-
gem
|
|
85
|
+
gem "docscribe"
|
|
49
86
|
```
|
|
50
87
|
|
|
51
88
|
Then:
|
|
@@ -100,7 +137,6 @@ echo "...code above..." | docscribe --stdin
|
|
|
100
137
|
Output:
|
|
101
138
|
|
|
102
139
|
```ruby
|
|
103
|
-
|
|
104
140
|
class Demo
|
|
105
141
|
# +Demo#foo+ -> Integer
|
|
106
142
|
#
|
|
@@ -148,11 +184,11 @@ class Demo
|
|
|
148
184
|
end
|
|
149
185
|
```
|
|
150
186
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
-
|
|
154
|
-
- Class methods show with a dot (`+Demo.bump+`, `+Demo.internal+`).
|
|
155
|
-
- Methods inside `class << self` under private are marked `@private
|
|
187
|
+
> [!NOTE]
|
|
188
|
+
> - The tool inserts doc headers before method headers and preserves everything else.
|
|
189
|
+
> - For methods with a leading Sorbet `sig`, docs are inserted above the first `sig`.
|
|
190
|
+
> - Class methods show with a dot (`+Demo.bump+`, `+Demo.internal+`).
|
|
191
|
+
> - Methods inside `class << self` under `private` are marked `@private`.
|
|
156
192
|
|
|
157
193
|
## CLI
|
|
158
194
|
|
|
@@ -160,174 +196,458 @@ Notes:
|
|
|
160
196
|
docscribe [options] [files...]
|
|
161
197
|
```
|
|
162
198
|
|
|
163
|
-
|
|
199
|
+
Docscribe has three main ways to run:
|
|
200
|
+
|
|
201
|
+
- **Inspect mode** (default): checks what safe doc updates would be applied and exits non-zero if files need changes.
|
|
202
|
+
- **Safe autocorrect** (`-a`, `--autocorrect`): writes safe, non-destructive updates in place.
|
|
203
|
+
- **Aggressive autocorrect** (`-A`, `--autocorrect-all`): rewrites existing doc blocks more aggressively.
|
|
204
|
+
- **STDIN mode** (`--stdin`): reads Ruby source from STDIN and prints rewritten source to STDOUT.
|
|
205
|
+
|
|
206
|
+
If you pass no files and don’t use `--stdin`, Docscribe processes the current directory recursively.
|
|
207
|
+
|
|
208
|
+
### Options
|
|
209
|
+
|
|
210
|
+
- `-a`, `--autocorrect`
|
|
211
|
+
Apply safe doc updates in place.
|
|
212
|
+
|
|
213
|
+
- `-A`, `--autocorrect-all`
|
|
214
|
+
Apply aggressive doc updates in place.
|
|
215
|
+
|
|
216
|
+
- `--stdin`
|
|
217
|
+
Read source from STDIN and print rewritten output.
|
|
218
|
+
|
|
219
|
+
- `--verbose`
|
|
220
|
+
Print per-file actions.
|
|
221
|
+
|
|
222
|
+
- `--explain`
|
|
223
|
+
Show detailed reasons for each file that would change.
|
|
224
|
+
|
|
225
|
+
- `--rbs`
|
|
226
|
+
Use RBS signatures for `@param`/`@return` when available (falls back to inference).
|
|
227
|
+
|
|
228
|
+
- `--sig-dir DIR`
|
|
229
|
+
Add an RBS signature directory (repeatable). Implies `--rbs`.
|
|
230
|
+
|
|
231
|
+
- `--include PATTERN`
|
|
232
|
+
Include PATTERN (method id or file path; glob or `/regex/`).
|
|
233
|
+
|
|
234
|
+
- `--exclude PATTERN`
|
|
235
|
+
Exclude PATTERN (method id or file path; glob or `/regex/`). Exclude wins.
|
|
236
|
+
|
|
237
|
+
- `--include-file PATTERN`
|
|
238
|
+
Only process files matching PATTERN (glob or `/regex/`).
|
|
239
|
+
|
|
240
|
+
- `--exclude-file PATTERN`
|
|
241
|
+
Skip files matching PATTERN (glob or `/regex/`). Exclude wins.
|
|
242
|
+
|
|
243
|
+
- `-C`, `--config PATH`
|
|
244
|
+
Path to config YAML (default: `docscribe.yml`).
|
|
164
245
|
|
|
165
|
-
- `--
|
|
166
|
-
|
|
167
|
-
- `--check` Dry-run: exit 1 if any file would change (useful in CI).
|
|
168
|
-
- `--rewrite` Replace any existing comment block above methods (see “Rewrite mode” below).
|
|
169
|
-
- `--version` Print version and exit.
|
|
170
|
-
- `-h`, `--help` Show help.
|
|
246
|
+
- `-v`, `--version`
|
|
247
|
+
Print version and exit.
|
|
171
248
|
|
|
172
|
-
|
|
249
|
+
- `-h`, `--help`
|
|
250
|
+
Show help.
|
|
173
251
|
|
|
174
|
-
|
|
252
|
+
### Examples
|
|
253
|
+
|
|
254
|
+
- Inspect a directory:
|
|
175
255
|
```shell
|
|
176
|
-
docscribe
|
|
256
|
+
docscribe lib
|
|
177
257
|
```
|
|
178
|
-
|
|
258
|
+
|
|
259
|
+
- Apply safe updates:
|
|
260
|
+
```shell
|
|
261
|
+
docscribe -a lib
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
- Apply aggressive updates:
|
|
179
265
|
```shell
|
|
180
|
-
docscribe
|
|
266
|
+
docscribe -A lib
|
|
181
267
|
```
|
|
182
|
-
|
|
268
|
+
|
|
269
|
+
- Preview output for a single file via STDIN:
|
|
183
270
|
```shell
|
|
184
|
-
docscribe --
|
|
271
|
+
cat path/to/file.rb | docscribe --stdin
|
|
185
272
|
```
|
|
186
|
-
|
|
273
|
+
|
|
274
|
+
- Use RBS signatures:
|
|
187
275
|
```shell
|
|
188
|
-
docscribe --
|
|
276
|
+
docscribe -a --rbs --sig-dir sig lib
|
|
189
277
|
```
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
278
|
+
|
|
279
|
+
- Show detailed reasons for files that would change:
|
|
280
|
+
```shell
|
|
281
|
+
docscribe --verbose --explain lib
|
|
193
282
|
```
|
|
194
283
|
|
|
195
|
-
##
|
|
284
|
+
## Update strategies
|
|
285
|
+
|
|
286
|
+
Docscribe supports two update strategies: **safe** and **aggressive**.
|
|
287
|
+
|
|
288
|
+
### Safe strategy
|
|
289
|
+
|
|
290
|
+
Used by:
|
|
291
|
+
|
|
292
|
+
- default inspect mode: `docscribe lib`
|
|
293
|
+
- safe write mode: `docscribe -a lib`
|
|
294
|
+
|
|
295
|
+
Safe strategy:
|
|
296
|
+
|
|
297
|
+
- inserts docs for undocumented methods
|
|
298
|
+
- merges missing tags into existing **doc-like** blocks
|
|
299
|
+
- normalizes configurable tag order inside sortable tag runs
|
|
300
|
+
- preserves existing prose and comments where possible
|
|
301
|
+
|
|
302
|
+
This is the recommended day-to-day mode.
|
|
303
|
+
|
|
304
|
+
### Aggressive strategy
|
|
305
|
+
|
|
306
|
+
Used by:
|
|
307
|
+
|
|
308
|
+
- aggressive write mode: `docscribe -A lib`
|
|
196
309
|
|
|
197
|
-
|
|
198
|
-
- Skips methods that already have a comment directly above them (does not merge into existing comments) unless you pass
|
|
199
|
-
`--rewrite`.
|
|
200
|
-
- Maintains original formatting and constructs; only adds comments.
|
|
310
|
+
Aggressive strategy:
|
|
201
311
|
|
|
202
|
-
|
|
312
|
+
- rebuilds existing doc blocks
|
|
313
|
+
- replaces existing generated documentation more fully
|
|
314
|
+
- is more invasive than safe mode
|
|
203
315
|
|
|
204
|
-
|
|
205
|
-
blank
|
|
206
|
-
lines) and replace it with a fresh generated block.
|
|
207
|
-
- This is useful to refresh docs across a codebase after improving inference or rules.
|
|
208
|
-
- Use with caution (prefer a clean working tree and review diffs).
|
|
316
|
+
Use it when you want to rebaseline or regenerate docs wholesale.
|
|
209
317
|
|
|
210
|
-
### Output markers
|
|
318
|
+
### Output markers
|
|
211
319
|
|
|
212
|
-
|
|
320
|
+
In inspect mode, Docscribe prints one character per file:
|
|
213
321
|
|
|
214
|
-
- `.` = file is up
|
|
215
|
-
- `F` = file would change
|
|
322
|
+
- `.` = file is up to date
|
|
323
|
+
- `F` = file would change
|
|
324
|
+
- `E` = file had an error
|
|
216
325
|
|
|
217
|
-
|
|
326
|
+
In write modes:
|
|
218
327
|
|
|
219
328
|
- `.` = file already OK
|
|
220
|
-
- `C` = file was
|
|
329
|
+
- `C` = file was updated
|
|
330
|
+
- `E` = file had an error
|
|
221
331
|
|
|
222
|
-
Docscribe prints
|
|
332
|
+
With `--verbose`, Docscribe prints per-file statuses instead.
|
|
333
|
+
|
|
334
|
+
With `--explain`, Docscribe also prints detailed reasons, such as:
|
|
335
|
+
|
|
336
|
+
- missing `@param`
|
|
337
|
+
- missing `@return`
|
|
338
|
+
- missing module_function note
|
|
339
|
+
- unsorted tags
|
|
223
340
|
|
|
224
341
|
## Parser backend (Parser gem vs Prism)
|
|
225
342
|
|
|
226
343
|
Docscribe internally works with `parser`-gem-compatible AST nodes and `Parser::Source::*` objects (so it can use
|
|
227
|
-
`Parser::Source::TreeRewriter` without changing
|
|
344
|
+
`Parser::Source::TreeRewriter` without changing formatting).
|
|
228
345
|
|
|
229
346
|
- On Ruby **<= 3.3**, Docscribe parses using the `parser` gem.
|
|
230
|
-
- On Ruby **>= 3.4**, Docscribe parses using **Prism** and translates the tree into the `parser` gem
|
|
231
|
-
stays compatible).
|
|
347
|
+
- On Ruby **>= 3.4**, Docscribe parses using **Prism** and translates the tree into the `parser` gem's AST.
|
|
232
348
|
|
|
233
349
|
You can force a backend with an environment variable:
|
|
234
350
|
|
|
235
|
-
```
|
|
236
|
-
DOCSCRIBE_PARSER_BACKEND=parser bundle exec docscribe
|
|
237
|
-
DOCSCRIBE_PARSER_BACKEND=prism bundle exec docscribe
|
|
351
|
+
```shell
|
|
352
|
+
DOCSCRIBE_PARSER_BACKEND=parser bundle exec docscribe lib
|
|
353
|
+
DOCSCRIBE_PARSER_BACKEND=prism bundle exec docscribe lib
|
|
238
354
|
```
|
|
239
355
|
|
|
240
|
-
##
|
|
356
|
+
## External type integrations (optional)
|
|
241
357
|
|
|
242
|
-
|
|
358
|
+
Docscribe can improve generated `@param` and `@return` types by reading external signatures instead of relying only on
|
|
359
|
+
AST inference.
|
|
243
360
|
|
|
244
|
-
|
|
361
|
+
> [!IMPORTANT]
|
|
362
|
+
> When external type information is available, Docscribe resolves signatures in this order:
|
|
363
|
+
> - inline Sorbet `sig` declarations in the current Ruby source;
|
|
364
|
+
> - Sorbet RBI files;
|
|
365
|
+
> - RBS files;
|
|
366
|
+
> - AST inference fallback.
|
|
367
|
+
>
|
|
368
|
+
> If an external signature cannot be loaded or parsed, Docscribe falls back to normal inference instead of failing.
|
|
245
369
|
|
|
246
|
-
|
|
247
|
-
- `**kwargs` -> `Hash`
|
|
248
|
-
- `&block` -> `Proc`
|
|
249
|
-
- keyword args:
|
|
250
|
-
- verbose: `true` -> `Boolean`
|
|
251
|
-
- options: `{}` -> `Hash`
|
|
252
|
-
- kw: (no default) -> `Object`
|
|
253
|
-
- positional defaults:
|
|
254
|
-
- `42` -> `Integer`, `1.0` -> `Float`, `'x'` -> `String`, `:ok` -> `Symbol`
|
|
255
|
-
- `[]` -> `Array`, `{}` -> `Hash`, `/x/` -> `Regexp`, `true`/`false` -> `Boolean`, `nil` -> `nil`
|
|
370
|
+
### RBS
|
|
256
371
|
|
|
257
|
-
|
|
372
|
+
Docscribe can read method signatures from `.rbs` files and use them to generate more accurate parameter and return
|
|
373
|
+
types.
|
|
258
374
|
|
|
259
|
-
|
|
260
|
-
- `42` -> `Integer`
|
|
261
|
-
- `:ok` -> `Symbol`
|
|
262
|
-
- Unions with nil become optional types (e.g., `String` or `nil` -> `String?`).
|
|
263
|
-
- For control flow (`if`/`case`), it unifies branches conservatively.
|
|
375
|
+
CLI:
|
|
264
376
|
|
|
265
|
-
|
|
377
|
+
```shell
|
|
378
|
+
docscribe -a --rbs --sig-dir sig lib
|
|
379
|
+
```
|
|
266
380
|
|
|
267
|
-
|
|
381
|
+
You can pass `--sig-dir` multiple times:
|
|
268
382
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
- (optional) explicit raise/fail also adds a tag (`raise Foo` -> `@raise [Foo]`, `raise` ->
|
|
273
|
-
`@raise [StandardError]`).
|
|
383
|
+
```shell
|
|
384
|
+
docscribe -a --rbs --sig-dir sig --sig-dir vendor/sigs lib
|
|
385
|
+
```
|
|
274
386
|
|
|
275
|
-
|
|
276
|
-
|
|
387
|
+
Config:
|
|
388
|
+
|
|
389
|
+
```yaml
|
|
390
|
+
rbs:
|
|
391
|
+
enabled: true
|
|
392
|
+
sig_dirs:
|
|
393
|
+
- sig
|
|
394
|
+
collapse_generics: false
|
|
395
|
+
```
|
|
277
396
|
|
|
278
397
|
Example:
|
|
279
398
|
|
|
280
399
|
```ruby
|
|
400
|
+
# Ruby source
|
|
401
|
+
class Demo
|
|
402
|
+
def foo(verbose:, count:)
|
|
403
|
+
"body says String"
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
```
|
|
281
407
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
408
|
+
```ruby.rbs
|
|
409
|
+
# sig/demo.rbs
|
|
410
|
+
class Demo
|
|
411
|
+
def foo: (verbose: bool, count: Integer) -> Integer
|
|
412
|
+
end
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
Generated docs will prefer the RBS signature over inferred Ruby types:
|
|
416
|
+
|
|
417
|
+
```ruby
|
|
418
|
+
|
|
419
|
+
class Demo
|
|
420
|
+
# +Demo#foo+ -> Integer
|
|
421
|
+
#
|
|
422
|
+
# Method documentation.
|
|
423
|
+
#
|
|
424
|
+
# @param [Boolean] verbose Param documentation.
|
|
425
|
+
# @param [Integer] count Param documentation.
|
|
426
|
+
# @return [Integer]
|
|
427
|
+
def foo(verbose:, count:)
|
|
428
|
+
'body says String'
|
|
287
429
|
end
|
|
430
|
+
end
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### Sorbet
|
|
434
|
+
|
|
435
|
+
Docscribe can also read Sorbet signatures from:
|
|
436
|
+
|
|
437
|
+
- inline `sig` declarations in Ruby source
|
|
438
|
+
- RBI files
|
|
439
|
+
|
|
440
|
+
CLI:
|
|
441
|
+
|
|
442
|
+
```shell
|
|
443
|
+
docscribe -a --sorbet lib
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
With RBI directories:
|
|
288
447
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
448
|
+
```shell
|
|
449
|
+
docscribe -a --sorbet --rbi-dir sorbet/rbi lib
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
You can pass `--rbi-dir` multiple times:
|
|
453
|
+
|
|
454
|
+
```shell
|
|
455
|
+
docscribe -a --sorbet --rbi-dir sorbet/rbi --rbi-dir rbi lib
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
Config:
|
|
459
|
+
|
|
460
|
+
```yaml
|
|
461
|
+
sorbet:
|
|
462
|
+
enabled: true
|
|
463
|
+
rbi_dirs:
|
|
464
|
+
- sorbet/rbi
|
|
465
|
+
- rbi
|
|
466
|
+
collapse_generics: false
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### Inline Sorbet example
|
|
470
|
+
|
|
471
|
+
```ruby
|
|
472
|
+
class Demo
|
|
473
|
+
extend T::Sig
|
|
474
|
+
|
|
475
|
+
sig { params(verbose: T::Boolean, count: Integer).returns(Integer) }
|
|
476
|
+
def foo(verbose:, count:)
|
|
477
|
+
'body says String'
|
|
293
478
|
end
|
|
294
479
|
end
|
|
295
480
|
```
|
|
296
481
|
|
|
297
|
-
|
|
482
|
+
Docscribe will use the Sorbet signature instead of the inferred body type:
|
|
298
483
|
|
|
299
484
|
```ruby
|
|
485
|
+
class Demo
|
|
486
|
+
extend T::Sig
|
|
300
487
|
|
|
301
|
-
|
|
302
|
-
# +X#a+ -> Integer
|
|
488
|
+
# +Demo#foo+ -> Integer
|
|
303
489
|
#
|
|
304
490
|
# Method documentation.
|
|
305
491
|
#
|
|
306
|
-
# @
|
|
307
|
-
# @
|
|
492
|
+
# @param [Boolean] verbose Param documentation.
|
|
493
|
+
# @param [Integer] count Param documentation.
|
|
308
494
|
# @return [Integer]
|
|
309
|
-
|
|
310
|
-
def
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
495
|
+
sig { params(verbose: T::Boolean, count: Integer).returns(Integer) }
|
|
496
|
+
def foo(verbose:, count:)
|
|
497
|
+
'body says String'
|
|
498
|
+
end
|
|
499
|
+
end
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### Sorbet RBI example
|
|
503
|
+
|
|
504
|
+
```ruby
|
|
505
|
+
# Ruby source
|
|
506
|
+
class Demo
|
|
507
|
+
def foo(verbose:, count:)
|
|
508
|
+
'body says String'
|
|
314
509
|
end
|
|
510
|
+
end
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
```ruby
|
|
514
|
+
# sorbet/rbi/demo.rbi
|
|
515
|
+
class Demo
|
|
516
|
+
extend T::Sig
|
|
517
|
+
|
|
518
|
+
sig { params(verbose: T::Boolean, count: Integer).returns(Integer) }
|
|
519
|
+
def foo(verbose:, count:); end
|
|
520
|
+
end
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
With:
|
|
524
|
+
|
|
525
|
+
```shell
|
|
526
|
+
docscribe -a --sorbet --rbi-dir sorbet/rbi lib
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
Docscribe will use the RBI signature for generated docs.
|
|
530
|
+
|
|
531
|
+
### Sorbet comment placement
|
|
532
|
+
|
|
533
|
+
For methods with a leading Sorbet `sig`, Docscribe treats the signature as part of the method header.
|
|
534
|
+
|
|
535
|
+
That means:
|
|
536
|
+
|
|
537
|
+
- new docs are inserted **above the first `sig`**
|
|
538
|
+
- existing docs **above the `sig`** are recognized and merged
|
|
539
|
+
- existing legacy docs **between `sig` and `def`** are also recognized
|
|
540
|
+
|
|
541
|
+
Example input:
|
|
542
|
+
|
|
543
|
+
```ruby
|
|
544
|
+
# demo.rb
|
|
545
|
+
class Demo
|
|
546
|
+
extend T::Sig
|
|
547
|
+
|
|
548
|
+
sig { returns(Integer) }
|
|
549
|
+
def foo
|
|
550
|
+
1
|
|
551
|
+
end
|
|
552
|
+
end
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
Example output:
|
|
556
|
+
|
|
557
|
+
```ruby
|
|
558
|
+
# demo.rb
|
|
559
|
+
class Demo
|
|
560
|
+
extend T::Sig
|
|
315
561
|
|
|
316
|
-
# +
|
|
562
|
+
# +Demo#foo+ -> Integer
|
|
317
563
|
#
|
|
318
564
|
# Method documentation.
|
|
319
565
|
#
|
|
320
|
-
# @
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
risky
|
|
325
|
-
rescue
|
|
326
|
-
"n"
|
|
566
|
+
# @return [Integer]
|
|
567
|
+
sig { returns(Integer) }
|
|
568
|
+
def foo
|
|
569
|
+
1
|
|
327
570
|
end
|
|
328
571
|
end
|
|
329
572
|
```
|
|
330
573
|
|
|
574
|
+
### Generic type formatting
|
|
575
|
+
|
|
576
|
+
Both RBS and Sorbet integrations support `collapse_generics`.
|
|
577
|
+
|
|
578
|
+
When disabled:
|
|
579
|
+
|
|
580
|
+
```yaml
|
|
581
|
+
rbs:
|
|
582
|
+
collapse_generics: false
|
|
583
|
+
|
|
584
|
+
sorbet:
|
|
585
|
+
collapse_generics: false
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
Docscribe preserves generic container details where possible, for example:
|
|
589
|
+
|
|
590
|
+
- `Array<String>`
|
|
591
|
+
- `Hash<Symbol, Integer>`
|
|
592
|
+
|
|
593
|
+
When enabled:
|
|
594
|
+
|
|
595
|
+
```yaml
|
|
596
|
+
rbs:
|
|
597
|
+
collapse_generics: true
|
|
598
|
+
|
|
599
|
+
sorbet:
|
|
600
|
+
collapse_generics: true
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
Docscribe simplifies container types to their outer names, for example:
|
|
604
|
+
|
|
605
|
+
- `Array`
|
|
606
|
+
- `Hash`
|
|
607
|
+
|
|
608
|
+
### Notes and fallback behavior
|
|
609
|
+
|
|
610
|
+
- External signature support is the **best effort**.
|
|
611
|
+
- If a signature source cannot be loaded or parsed, Docscribe falls back to AST inference.
|
|
612
|
+
- RBS and Sorbet integrations are used only to improve generated types; Docscribe still rewrites Ruby source directly.
|
|
613
|
+
- Sorbet support does not require changing your documentation style — it only improves generated `@param` and `@return`
|
|
614
|
+
tags when signatures are available.
|
|
615
|
+
|
|
616
|
+
## Type inference
|
|
617
|
+
|
|
618
|
+
Heuristics (best-effort).
|
|
619
|
+
|
|
620
|
+
Parameters:
|
|
621
|
+
|
|
622
|
+
- `*args` -> `Array`
|
|
623
|
+
- `**kwargs` -> `Hash`
|
|
624
|
+
- `&block` -> `Proc`
|
|
625
|
+
- keyword args:
|
|
626
|
+
- `verbose: true` -> `Boolean`
|
|
627
|
+
- `options: {}` -> `Hash`
|
|
628
|
+
- `kw:` (no default) -> `Object`
|
|
629
|
+
- positional defaults:
|
|
630
|
+
- `42` -> `Integer`, `1.0` -> `Float`, `'x'` -> `String`, `:ok` -> `Symbol`
|
|
631
|
+
- `[]` -> `Array`, `{}` -> `Hash`, `/x/` -> `Regexp`, `true`/`false` -> `Boolean`, `nil` -> `nil`
|
|
632
|
+
|
|
633
|
+
Return values:
|
|
634
|
+
|
|
635
|
+
- For simple bodies, Docscribe looks at the last expression or explicit `return`.
|
|
636
|
+
- Unions with `nil` become optional types (e.g. `String` or `nil` -> `String?`).
|
|
637
|
+
- For control flow (`if`/`case`), it unifies branches conservatively.
|
|
638
|
+
|
|
639
|
+
## Rescue-aware returns and @raise
|
|
640
|
+
|
|
641
|
+
Docscribe detects exceptions and rescue branches:
|
|
642
|
+
|
|
643
|
+
- Rescue exceptions become `@raise` tags:
|
|
644
|
+
- `rescue Foo, Bar` -> `@raise [Foo]` and `@raise [Bar]`
|
|
645
|
+
- bare rescue -> `@raise [StandardError]`
|
|
646
|
+
- explicit `raise`/`fail` also adds a tag (`raise Foo` -> `@raise [Foo]`, `raise` -> `@raise [StandardError]`)
|
|
647
|
+
|
|
648
|
+
- Conditional return types for rescue branches:
|
|
649
|
+
- Docscribe adds `@return [Type] if ExceptionA, ExceptionB` for each rescue clause
|
|
650
|
+
|
|
331
651
|
## Visibility semantics
|
|
332
652
|
|
|
333
653
|
We match Ruby's behavior:
|
|
@@ -342,10 +662,26 @@ Inline tags:
|
|
|
342
662
|
- `@private` is added for methods that are private in context.
|
|
343
663
|
- `@protected` is added similarly for protected methods.
|
|
344
664
|
|
|
665
|
+
> [!IMPORTANT]
|
|
666
|
+
> `module_function`: Docscribe documents methods affected by `module_function` as module methods (`M.foo`) rather than
|
|
667
|
+
> instance methods (`M#foo`), because that is usually the callable/public API. If a method was previously private as an
|
|
668
|
+
> instance method, Docscribe will avoid marking the generated docs as `@private` after it is promoted to a module
|
|
669
|
+
> method.
|
|
670
|
+
|
|
671
|
+
```ruby
|
|
672
|
+
module M
|
|
673
|
+
private
|
|
674
|
+
|
|
675
|
+
def foo; end
|
|
676
|
+
|
|
677
|
+
module_function :foo
|
|
678
|
+
end
|
|
679
|
+
```
|
|
680
|
+
|
|
345
681
|
## API (library) usage
|
|
346
682
|
|
|
347
683
|
```ruby
|
|
348
|
-
require
|
|
684
|
+
require "docscribe/inline_rewriter"
|
|
349
685
|
|
|
350
686
|
code = <<~RUBY
|
|
351
687
|
class Demo
|
|
@@ -354,135 +690,274 @@ code = <<~RUBY
|
|
|
354
690
|
end
|
|
355
691
|
RUBY
|
|
356
692
|
|
|
357
|
-
#
|
|
693
|
+
# Basic insertion behavior
|
|
358
694
|
out = Docscribe::InlineRewriter.insert_comments(code)
|
|
359
695
|
puts out
|
|
360
696
|
|
|
361
|
-
#
|
|
362
|
-
out2 = Docscribe::InlineRewriter.insert_comments(code,
|
|
697
|
+
# Safe merge / normalization of existing doc-like blocks
|
|
698
|
+
out2 = Docscribe::InlineRewriter.insert_comments(code, strategy: :safe)
|
|
699
|
+
|
|
700
|
+
# Aggressive rebuild of existing doc blocks (similar to CLI -A)
|
|
701
|
+
out3 = Docscribe::InlineRewriter.insert_comments(code, strategy: :aggressive)
|
|
363
702
|
```
|
|
364
703
|
|
|
365
704
|
## Configuration
|
|
366
705
|
|
|
367
|
-
Docscribe can be configured via a YAML file (docscribe.yml by default, or pass
|
|
706
|
+
Docscribe can be configured via a YAML file (`docscribe.yml` by default, or pass `--config PATH`).
|
|
707
|
+
|
|
708
|
+
### Filtering
|
|
709
|
+
|
|
710
|
+
Docscribe can filter both *files* and *methods*.
|
|
711
|
+
|
|
712
|
+
File filtering (recommended for excluding specs, vendor code, etc.):
|
|
713
|
+
|
|
714
|
+
```yaml
|
|
715
|
+
filter:
|
|
716
|
+
files:
|
|
717
|
+
exclude: [ "spec" ]
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
Method filtering matches method ids like:
|
|
721
|
+
|
|
722
|
+
- `MyModule::MyClass#instance_method`
|
|
723
|
+
- `MyModule::MyClass.class_method`
|
|
368
724
|
|
|
369
725
|
Example:
|
|
370
726
|
|
|
727
|
+
```yaml
|
|
728
|
+
filter:
|
|
729
|
+
exclude:
|
|
730
|
+
- "*#initialize"
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
CLI overrides are available too:
|
|
734
|
+
|
|
735
|
+
```shell
|
|
736
|
+
# Method filtering (matches method ids like A#foo / A.bar)
|
|
737
|
+
docscribe --exclude '*#initialize' lib
|
|
738
|
+
docscribe --include '/^MyModule::.*#(foo|bar)$/' lib
|
|
739
|
+
|
|
740
|
+
# File filtering (matches paths relative to the project root)
|
|
741
|
+
docscribe --exclude-file 'spec' lib spec
|
|
742
|
+
docscribe --exclude-file '/^spec\//' lib
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
> [!NOTE]
|
|
746
|
+
> `/regex/` passed to `--include`/`--exclude` is treated as a **method-id** pattern. Use `--include-file` /
|
|
747
|
+
`--exclude-file` for file regex filters.
|
|
748
|
+
|
|
749
|
+
Enable attribute-style documentation generation with:
|
|
750
|
+
|
|
371
751
|
```yaml
|
|
372
752
|
emit:
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
753
|
+
attributes: true
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
When enabled, Docscribe can generate YARD `@!attribute` docs for:
|
|
757
|
+
|
|
758
|
+
- `attr_reader`
|
|
759
|
+
- `attr_writer`
|
|
760
|
+
- `attr_accessor`
|
|
761
|
+
- `Struct.new` declarations
|
|
762
|
+
|
|
763
|
+
### `attr_*` example
|
|
764
|
+
|
|
765
|
+
> [!NOTE]
|
|
766
|
+
> - Attribute docs are inserted above the `attr_*` call, not above generated methods (since they don’t exist as `def`
|
|
767
|
+
nodes).
|
|
768
|
+
> - If RBS is enabled, Docscribe will try to use the RBS return type of the reader method as the attribute type.
|
|
769
|
+
|
|
770
|
+
```ruby
|
|
771
|
+
class User
|
|
772
|
+
attr_accessor :name
|
|
773
|
+
end
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
Generated docs:
|
|
777
|
+
|
|
778
|
+
```ruby
|
|
779
|
+
class User
|
|
780
|
+
# @!attribute [rw] name
|
|
781
|
+
# @return [Object]
|
|
782
|
+
# @param [Object] value
|
|
783
|
+
attr_accessor :name
|
|
784
|
+
end
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
### `Struct.new` examples
|
|
788
|
+
|
|
789
|
+
Docscribe supports both common `Struct.new` declaration styles.
|
|
790
|
+
|
|
791
|
+
#### Constant-assigned struct
|
|
792
|
+
|
|
793
|
+
```ruby
|
|
794
|
+
User = Struct.new(:name, :email, keyword_init: true)
|
|
795
|
+
```
|
|
796
|
+
|
|
797
|
+
Generated docs:
|
|
798
|
+
|
|
799
|
+
```ruby
|
|
800
|
+
# @!attribute [rw] name
|
|
801
|
+
# @return [Object]
|
|
802
|
+
# @param [Object] value
|
|
803
|
+
#
|
|
804
|
+
# @!attribute [rw] email
|
|
805
|
+
# @return [Object]
|
|
806
|
+
# @param [Object] value
|
|
807
|
+
User = Struct.new(:name, :email, keyword_init: true)
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
#### Class-based struct
|
|
811
|
+
|
|
812
|
+
```ruby
|
|
813
|
+
class User < Struct.new(:name, :email, keyword_init: true)
|
|
814
|
+
end
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
Generated docs:
|
|
818
|
+
|
|
819
|
+
```ruby
|
|
820
|
+
# @!attribute [rw] name
|
|
821
|
+
# @return [Object]
|
|
822
|
+
# @param [Object] value
|
|
823
|
+
#
|
|
824
|
+
# @!attribute [rw] email
|
|
825
|
+
# @return [Object]
|
|
826
|
+
# @param [Object] value
|
|
827
|
+
class User < Struct.new(:name, :email, keyword_init: true)
|
|
828
|
+
end
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
Docscribe preserves the original declaration style and does not rewrite one form into the other.
|
|
832
|
+
|
|
833
|
+
### Merge behavior
|
|
834
|
+
|
|
835
|
+
Struct member docs use the same attribute documentation pipeline as `attr_*` macros, which means they participate in the
|
|
836
|
+
normal safe/aggressive rewrite flow.
|
|
379
837
|
|
|
838
|
+
In safe mode, Docscribe can:
|
|
839
|
+
|
|
840
|
+
- insert full `@!attribute` docs when no doc-like block exists
|
|
841
|
+
- append missing struct member docs into an existing doc-like block
|
|
842
|
+
|
|
843
|
+
### Param tag style
|
|
844
|
+
|
|
845
|
+
Generated writer-style attribute docs respect `doc.param_tag_style`.
|
|
846
|
+
|
|
847
|
+
For example, with:
|
|
848
|
+
|
|
849
|
+
```yaml
|
|
380
850
|
doc:
|
|
381
|
-
|
|
851
|
+
param_tag_style: "type_name"
|
|
852
|
+
```
|
|
382
853
|
|
|
383
|
-
|
|
384
|
-
instance:
|
|
385
|
-
public:
|
|
386
|
-
return_tag: true
|
|
387
|
-
default_message: "Public API. Please document purpose and params."
|
|
388
|
-
class:
|
|
389
|
-
private:
|
|
390
|
-
return_tag: false
|
|
854
|
+
writer params are emitted as:
|
|
391
855
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
nil_as_optional: true
|
|
395
|
-
treat_options_keyword_as_hash: true
|
|
856
|
+
```ruby
|
|
857
|
+
# @param [Object] value
|
|
396
858
|
```
|
|
397
859
|
|
|
398
|
-
|
|
399
|
-
- methods.<scope>.<visibility> allows per-method overrides:
|
|
400
|
-
- return_tag: true/false
|
|
401
|
-
- default_message: override the message for that bucket
|
|
402
|
-
- inference.* tunes type inference defaults.
|
|
860
|
+
With:
|
|
403
861
|
|
|
404
|
-
|
|
862
|
+
```yaml
|
|
863
|
+
doc:
|
|
864
|
+
param_tag_style: "name_type"
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
they are emitted as:
|
|
405
868
|
|
|
406
|
-
```
|
|
407
|
-
|
|
869
|
+
```ruby
|
|
870
|
+
# @param value [Object]
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
### Create a starter config
|
|
874
|
+
|
|
875
|
+
Create `docscribe.yml` in the current directory:
|
|
876
|
+
|
|
877
|
+
```shell
|
|
878
|
+
docscribe init
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
Write to a custom path:
|
|
882
|
+
|
|
883
|
+
```shell
|
|
884
|
+
docscribe init --config config/docscribe.yml
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
Overwrite if it already exists:
|
|
888
|
+
|
|
889
|
+
```shell
|
|
890
|
+
docscribe init --force
|
|
891
|
+
```
|
|
892
|
+
|
|
893
|
+
Print the template to stdout:
|
|
894
|
+
|
|
895
|
+
```shell
|
|
896
|
+
docscribe init --stdout
|
|
408
897
|
```
|
|
409
898
|
|
|
410
899
|
## CI integration
|
|
411
900
|
|
|
412
|
-
Fail the build if files would
|
|
901
|
+
Fail the build if files would need safe updates:
|
|
413
902
|
|
|
414
903
|
```yaml
|
|
415
904
|
- name: Check inline docs
|
|
416
|
-
run: docscribe
|
|
905
|
+
run: docscribe lib
|
|
417
906
|
```
|
|
418
907
|
|
|
419
|
-
|
|
908
|
+
Apply safe fixes before the test stage:
|
|
420
909
|
|
|
421
910
|
```yaml
|
|
422
|
-
- name:
|
|
423
|
-
run: docscribe
|
|
911
|
+
- name: Apply safe inline docs
|
|
912
|
+
run: docscribe -a lib
|
|
424
913
|
```
|
|
425
914
|
|
|
426
|
-
|
|
915
|
+
Aggressively rebuild docs:
|
|
427
916
|
|
|
428
917
|
```yaml
|
|
429
|
-
- name:
|
|
430
|
-
run: docscribe
|
|
918
|
+
- name: Rebuild inline docs
|
|
919
|
+
run: docscribe -A lib
|
|
431
920
|
```
|
|
432
921
|
|
|
433
922
|
## Comparison to YARD's parser
|
|
434
923
|
|
|
435
924
|
Docscribe and YARD solve different parts of the documentation problem:
|
|
436
925
|
|
|
437
|
-
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
- Semantics:
|
|
449
|
-
- Docscribe models Ruby visibility semantics precisely for inline usage (including `class << self`).
|
|
450
|
-
- YARD has rich semantics around tags and directives; it can leverage your inline comments (including those inserted
|
|
451
|
-
by Docscribe).
|
|
452
|
-
|
|
453
|
-
- Recommended workflow:
|
|
454
|
-
- Use Docscribe to seed and maintain inline docs with inferred tags/types.
|
|
455
|
-
- Optionally use YARD (dev-only) to render HTML from those comments:
|
|
456
|
-
```shell
|
|
457
|
-
yard doc -o docs
|
|
458
|
-
```
|
|
926
|
+
- Docscribe inserts/updates inline comments by rewriting source.
|
|
927
|
+
- YARD can generate HTML docs based on inline comments.
|
|
928
|
+
|
|
929
|
+
Recommended workflow:
|
|
930
|
+
|
|
931
|
+
- Use Docscribe to seed and maintain inline docs with inferred tags/types.
|
|
932
|
+
- Optionally use YARD (dev-only) to render HTML from those comments:
|
|
933
|
+
|
|
934
|
+
```shell
|
|
935
|
+
yard doc -o docs
|
|
936
|
+
```
|
|
459
937
|
|
|
460
938
|
## Limitations
|
|
461
939
|
|
|
462
|
-
-
|
|
463
|
-
|
|
464
|
-
- Type inference is heuristic. Complex flows and meta-programming will fall back to Object or best-effort types.
|
|
465
|
-
-
|
|
466
|
-
- Inline rewrite is textual; ensure a clean working tree before using `--write` or `--rewrite`.
|
|
940
|
+
- Safe mode only merges into existing **doc-like** comment blocks. Ordinary comments that are not recognized as
|
|
941
|
+
documentation are preserved and treated conservatively.
|
|
942
|
+
- Type inference is heuristic. Complex flows and meta-programming will fall back to `Object` or best-effort types.
|
|
943
|
+
- Aggressive mode (`-A`) replaces existing doc blocks and should be reviewed carefully.
|
|
467
944
|
|
|
468
945
|
## Roadmap
|
|
469
946
|
|
|
470
|
-
-
|
|
471
|
-
-
|
|
472
|
-
-
|
|
473
|
-
-
|
|
947
|
+
- Effective config dump;
|
|
948
|
+
- JSON output;
|
|
949
|
+
- Overload-aware signature selection;
|
|
950
|
+
- Manual `@!attribute` merge policy;
|
|
951
|
+
- Richer inference for common APIs;
|
|
952
|
+
- Editor integration.
|
|
474
953
|
|
|
475
954
|
## Contributing
|
|
476
955
|
|
|
477
|
-
Issues and PRs welcome. Please run:
|
|
478
|
-
|
|
479
956
|
```shell
|
|
480
957
|
bundle exec rspec
|
|
481
958
|
bundle exec rubocop
|
|
482
959
|
```
|
|
483
960
|
|
|
484
|
-
See CODE_OF_CONDUCT.md.
|
|
485
|
-
|
|
486
961
|
## License
|
|
487
962
|
|
|
488
963
|
MIT
|