docscribe 1.4.1 → 1.5.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 +588 -104
- data/lib/docscribe/cli/check_for_comments.rb +183 -0
- data/lib/docscribe/cli/config_builder.rb +180 -36
- data/lib/docscribe/cli/formatters/json.rb +294 -0
- data/lib/docscribe/cli/formatters/sarif.rb +235 -0
- data/lib/docscribe/cli/formatters/text.rb +208 -0
- data/lib/docscribe/cli/formatters.rb +26 -0
- data/lib/docscribe/cli/generate.rb +296 -125
- data/lib/docscribe/cli/init.rb +58 -14
- data/lib/docscribe/cli/options.rb +410 -133
- data/lib/docscribe/cli/rbs_gen.rb +529 -0
- data/lib/docscribe/cli/run.rb +503 -189
- data/lib/docscribe/cli/sigs.rb +366 -0
- data/lib/docscribe/cli/update_types.rb +103 -0
- data/lib/docscribe/cli.rb +35 -9
- data/lib/docscribe/config/defaults.rb +16 -12
- data/lib/docscribe/config/emit.rb +18 -0
- data/lib/docscribe/config/filtering.rb +37 -31
- data/lib/docscribe/config/loader.rb +20 -13
- data/lib/docscribe/config/plugin.rb +2 -1
- data/lib/docscribe/config/rbs.rb +68 -27
- data/lib/docscribe/config/sorbet.rb +40 -17
- data/lib/docscribe/config/sorting.rb +2 -1
- data/lib/docscribe/config/template.rb +10 -1
- data/lib/docscribe/config/utils.rb +12 -9
- data/lib/docscribe/config.rb +3 -4
- data/lib/docscribe/infer/ast_walk.rb +1 -1
- data/lib/docscribe/infer/constants.rb +15 -0
- data/lib/docscribe/infer/literals.rb +39 -26
- data/lib/docscribe/infer/names.rb +24 -16
- data/lib/docscribe/infer/params.rb +57 -13
- data/lib/docscribe/infer/raises.rb +23 -15
- data/lib/docscribe/infer/returns.rb +784 -199
- data/lib/docscribe/infer.rb +28 -28
- data/lib/docscribe/inline_rewriter/collector.rb +816 -430
- data/lib/docscribe/inline_rewriter/doc_block.rb +323 -150
- data/lib/docscribe/inline_rewriter/doc_builder.rb +1837 -648
- data/lib/docscribe/inline_rewriter/source_helpers.rb +119 -71
- data/lib/docscribe/inline_rewriter/tag_sorter.rb +165 -107
- data/lib/docscribe/inline_rewriter.rb +1144 -727
- data/lib/docscribe/parsing.rb +29 -10
- data/lib/docscribe/plugin/base/collector_plugin.rb +3 -3
- data/lib/docscribe/plugin/base/tag_plugin.rb +1 -2
- data/lib/docscribe/plugin/context.rb +28 -18
- data/lib/docscribe/plugin/registry.rb +49 -23
- data/lib/docscribe/plugin/tag.rb +9 -14
- data/lib/docscribe/plugin.rb +54 -22
- data/lib/docscribe/types/provider_chain.rb +4 -2
- data/lib/docscribe/types/rbs/collection_loader.rb +2 -3
- data/lib/docscribe/types/rbs/provider.rb +127 -62
- data/lib/docscribe/types/rbs/type_formatter.rb +286 -77
- data/lib/docscribe/types/signature.rb +22 -42
- data/lib/docscribe/types/sorbet/base_provider.rb +51 -27
- data/lib/docscribe/types/sorbet/rbi_provider.rb +3 -3
- data/lib/docscribe/types/sorbet/source_provider.rb +3 -2
- data/lib/docscribe/types/yard/formatter.rb +100 -0
- data/lib/docscribe/types/yard/parser.rb +240 -0
- data/lib/docscribe/types/yard/types.rb +52 -0
- data/lib/docscribe/version.rb +1 -1
- metadata +34 -2
data/README.md
CHANGED
|
@@ -5,6 +5,12 @@
|
|
|
5
5
|
[](https://github.com/unurgunite/docscribe/actions/workflows/ci.yml)
|
|
6
6
|
[](https://github.com/unurgunite/docscribe/blob/master/LICENSE.txt)
|
|
7
7
|
[](#installation)
|
|
8
|
+
[](https://marketplace.visualstudio.com/items?itemName=unurgunite.docscribe-vscode)
|
|
9
|
+
[](https://plugins.jetbrains.com/plugin/32349-docscribe)
|
|
10
|
+
|
|
11
|
+
<p>
|
|
12
|
+
<img src="assets/icons/icon_256x256.png" alt="Docscribe logo" width="96">
|
|
13
|
+
</p>
|
|
8
14
|
|
|
9
15
|

|
|
10
16
|
|
|
@@ -29,6 +35,10 @@ returns), and respects Ruby visibility semantics — without using YARD to parse
|
|
|
29
35
|
- `attr_reader` / `attr_writer` / `attr_accessor`;
|
|
30
36
|
- `Struct.new` declarations in both constant-assigned and class-based styles.
|
|
31
37
|
|
|
38
|
+
> [!NOTE]
|
|
39
|
+
> Docscribe is under **active development**. If you run into any edge cases or have ideas for improvement, feel free to
|
|
40
|
+
> [open an issue](https://github.com/unurgunite/docscribe/issues/new) or submit a pull request.
|
|
41
|
+
|
|
32
42
|
Common workflows:
|
|
33
43
|
|
|
34
44
|
- Inspect what safe doc updates would be applied: `docscribe lib`
|
|
@@ -38,19 +48,48 @@ Common workflows:
|
|
|
38
48
|
- Use RBS signatures when available: `docscribe -a --rbs --sig-dir sig lib`
|
|
39
49
|
- Use Sorbet signatures when available: `docscribe -a --sorbet --rbi-dir sorbet/rbi lib`
|
|
40
50
|
|
|
51
|
+
## Quick start
|
|
52
|
+
|
|
53
|
+
```shell
|
|
54
|
+
# Check what safe doc updates would be applied
|
|
55
|
+
docscribe lib
|
|
56
|
+
|
|
57
|
+
# Apply safe updates (insert missing docs, merge existing)
|
|
58
|
+
docscribe -a lib
|
|
59
|
+
|
|
60
|
+
# Rebuild all doc blocks aggressively
|
|
61
|
+
docscribe -A lib
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
> [!TIP]
|
|
65
|
+
> See [CLI](#cli) for all options and [Update strategies](#update-strategies) for the
|
|
66
|
+
> difference between safe and aggressive modes.
|
|
67
|
+
>
|
|
68
|
+
> Want IDE integration? Check out
|
|
69
|
+
> the [VS Code](https://marketplace.visualstudio.com/items?itemName=unurgunite.docscribe-vscode)
|
|
70
|
+
> and [RubyMine](https://plugins.jetbrains.com/plugin/32349-docscribe) plugins.
|
|
71
|
+
|
|
41
72
|
## Contents
|
|
42
73
|
|
|
43
74
|
* [Docscribe](#docscribe)
|
|
75
|
+
* [Quick start](#quick-start)
|
|
44
76
|
* [Contents](#contents)
|
|
45
77
|
* [Installation](#installation)
|
|
46
|
-
* [
|
|
78
|
+
* [Architecture](#architecture)
|
|
79
|
+
* [Data flow](#data-flow)
|
|
47
80
|
* [CLI](#cli)
|
|
81
|
+
* [Exit codes](#exit-codes)
|
|
48
82
|
* [Options](#options)
|
|
49
83
|
* [Examples](#examples)
|
|
84
|
+
* [`docscribe sigs` — check RBS signature coverage](#docscribe-sigs--check-rbs-signature-coverage)
|
|
85
|
+
* [`docscribe rbs` — generate RBS from YARD](#docscribe-rbs--generate-rbs-from-yard)
|
|
86
|
+
* [`docscribe update_types` — two-pass type-aware documentation update](#docscribe-update_types--two-pass-type-aware-documentation-update)
|
|
87
|
+
* [`docscribe check_for_comments` — find placeholder documentation](#docscribe-check_for_comments--find-placeholder-documentation)
|
|
50
88
|
* [Update strategies](#update-strategies)
|
|
51
89
|
* [Safe strategy](#safe-strategy)
|
|
52
90
|
* [Aggressive strategy](#aggressive-strategy)
|
|
53
91
|
* [Output markers](#output-markers)
|
|
92
|
+
* [Tips & tricks](#tips--tricks)
|
|
54
93
|
* [Parser backend (Parser gem vs Prism)](#parser-backend-parser-gem-vs-prism)
|
|
55
94
|
* [External type integrations (optional)](#external-type-integrations-optional)
|
|
56
95
|
* [RBS](#rbs)
|
|
@@ -75,6 +114,7 @@ Common workflows:
|
|
|
75
114
|
* [Idempotency](#idempotency)
|
|
76
115
|
* [Plugin examples](#plugin-examples)
|
|
77
116
|
* [Configuration](#configuration)
|
|
117
|
+
* [Anonymous block parameters](#anonymous-block-parameters)
|
|
78
118
|
* [Filtering](#filtering)
|
|
79
119
|
* [`attr_*` example](#attr_-example)
|
|
80
120
|
* [`Struct.new` examples](#structnew-examples)
|
|
@@ -84,12 +124,17 @@ Common workflows:
|
|
|
84
124
|
* [Param tag style](#param-tag-style)
|
|
85
125
|
* [Create a starter config](#create-a-starter-config)
|
|
86
126
|
* [Generate a plugin skeleton](#generate-a-plugin-skeleton)
|
|
127
|
+
* [Full configuration reference](#full-configuration-reference)
|
|
87
128
|
* [CI integration](#ci-integration)
|
|
88
129
|
* [Comparison to YARD's parser](#comparison-to-yards-parser)
|
|
89
130
|
* [Limitations](#limitations)
|
|
90
131
|
* [Roadmap](#roadmap)
|
|
132
|
+
* [Editor Integration](#editor-integration)
|
|
133
|
+
* [VS Code](#vs-code)
|
|
134
|
+
* [RubyMine](#rubymine)
|
|
91
135
|
* [Contributing](#contributing)
|
|
92
136
|
* [Discussion & Community](#discussion--community)
|
|
137
|
+
* [Logo Attribution](#logo-attribution)
|
|
93
138
|
* [License](#license)
|
|
94
139
|
|
|
95
140
|
## Installation
|
|
@@ -114,110 +159,193 @@ gem install docscribe
|
|
|
114
159
|
|
|
115
160
|
Requires Ruby 2.7+.
|
|
116
161
|
|
|
117
|
-
##
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
class << self
|
|
138
|
-
private
|
|
139
|
-
|
|
140
|
-
def internal; end
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
Run:
|
|
162
|
+
## Architecture
|
|
163
|
+
|
|
164
|
+
Docscribe is organized into several subsystems. The CLI layer receives user input and orchestrates configuration
|
|
165
|
+
loading, then delegates to the core engine which parses source code, collects methods (using an AST walker), builds YARD
|
|
166
|
+
doc lines — combining heuristic type inference, external RBS/Sorbet signatures, and plugin output — and finally rewrites
|
|
167
|
+
the source via a strategy (safe merge or aggressive replace).
|
|
168
|
+
|
|
169
|
+
```mermaid
|
|
170
|
+
flowchart TB
|
|
171
|
+
subgraph CLI["CLI Layer"]
|
|
172
|
+
Exe["exe/docscribe\nEntry point"]
|
|
173
|
+
Run["CLI::Run\nMain execution\n· expand paths\n· iterate files\n· report results"]
|
|
174
|
+
Options["CLI::Options\nARGV parsing\n(mode, strategy,\nfilters, flags)"]
|
|
175
|
+
InitCmd["CLI::Init\ndocscribe init\nGenerate config"]
|
|
176
|
+
GenCmd["CLI::Generate\ndocscribe generate\nScaffold plugins"]
|
|
177
|
+
SigsCmd["CLI::Sigs\ndocscribe sigs\nCheck RBS coverage"]
|
|
178
|
+
RbsGenCmd["CLI::RbsGen\ndocscribe rbs\nGenerate RBS from YARD"]
|
|
179
|
+
SarifFormatter["CLI::Formatters::Sarif\nSARIF 2.1 JSON\nCode Scanning"]
|
|
180
|
+
ConfigBuilder["CLI::ConfigBuilder\nApply CLI overrides\nto config"]
|
|
181
|
+
end
|
|
146
182
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
183
|
+
subgraph Config["Configuration"]
|
|
184
|
+
ConfigClass["Config\nCentral config object\n· raw hash\n· query methods"]
|
|
185
|
+
Defaults["config/defaults.rb\nDEFAULT hash"]
|
|
186
|
+
Loader["config/loader.rb\nYAML loading\n+ deep merge"]
|
|
187
|
+
Emit["config/emit.rb\nEmission toggles\n(header, tags, etc.)"]
|
|
188
|
+
Filtering["config/filtering.rb\nFile/method\ninclude/exclude"]
|
|
189
|
+
RBSConfig["config/rbs.rb\nRBS provider\nfactory"]
|
|
190
|
+
SorbetConfig["config/sorbet.rb\nSorbet provider\nchain factory"]
|
|
191
|
+
PluginConfig["config/plugin.rb\nPlugin loading\nfrom YAML"]
|
|
192
|
+
end
|
|
150
193
|
|
|
151
|
-
|
|
194
|
+
subgraph Parsing["Parsing"]
|
|
195
|
+
ParsingModule["Parsing\nBackend selection\n(:parser / :prism)"]
|
|
196
|
+
ParserGem["Parser gem\n(whitequark/parser)"]
|
|
197
|
+
Prism["Prism translator\n(Ruby 3.4+)"]
|
|
198
|
+
end
|
|
152
199
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
# @param [Hash] options Param documentation.
|
|
161
|
-
# @return [Integer]
|
|
162
|
-
def foo(a, options: {})
|
|
163
|
-
42
|
|
164
|
-
end
|
|
200
|
+
subgraph Core["Core Engine"]
|
|
201
|
+
InlineRewriter["InlineRewriter\n· parse -> collect\n· deduplicate -> dispatch\n· rewrite"]
|
|
202
|
+
Collector["Collector\n< Parser::AST::Processor\nAST walker\n· find methods/attrs\n· track visibility\n· track containers"]
|
|
203
|
+
DocBuilder["DocBuilder\nGenerate YARD doc lines\n· combine inference\n· external signatures\n· plugin tags"]
|
|
204
|
+
DocBlock["DocBlock\nSafe strategy:\nparse -> merge -> sort\nexisting doc blocks"]
|
|
205
|
+
SourceHelpers["SourceHelpers\nPosition/range\nutilities"]
|
|
206
|
+
end
|
|
165
207
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
208
|
+
subgraph Infer["Inference Engine"]
|
|
209
|
+
InferModule["Infer\nEntry point"]
|
|
210
|
+
Params["Infer::Params\nParameter type\nfrom name + default"]
|
|
211
|
+
Returns["Infer::Returns\nReturn type\nfrom method body"]
|
|
212
|
+
Raises["Infer::Raises\n@raise tags\nfrom raise/rescue"]
|
|
213
|
+
Literals["Infer::Literals\nAST literal ->\ntype string"]
|
|
214
|
+
Names["Infer::Names\n:const node ->\nFQN string"]
|
|
215
|
+
ASTWalk["Infer::ASTWalk\nRecursive DFS\nAST traversal"]
|
|
216
|
+
end
|
|
175
217
|
|
|
176
|
-
|
|
218
|
+
subgraph Plugins["Plugin System"]
|
|
219
|
+
PluginModule["Plugin\nTag/Collector\ndispatch"]
|
|
220
|
+
Registry["Plugin::Registry\nGlobal registry\n· register -> route\n· tag_entries\n· collector_entries"]
|
|
221
|
+
TagPlugin["Base::TagPlugin\nOverride #call(context)\n-> Array<Tag>"]
|
|
222
|
+
CollectorPlugin["Base::CollectorPlugin\nOverride #collect(ast, buffer)\n-> Array<Hash>"]
|
|
223
|
+
TagValue["Plugin::Tag\nStruct (name, text, types)"]
|
|
224
|
+
Context["Plugin::Context\nMethod snapshot struct"]
|
|
225
|
+
end
|
|
177
226
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
227
|
+
subgraph Types["External Type System"]
|
|
228
|
+
ProviderChain["ProviderChain\nComposite:\nquery in order\nfirst match wins"]
|
|
229
|
+
RBSProvider["RBS::Provider\n.rbs files\n-> RBS lib"]
|
|
230
|
+
RBSFormatter["RBS::TypeFormatter\nRBS type ->\nYARD type string"]
|
|
231
|
+
RBSCollection["RBS::CollectionLoader\nrbs_collection\n.lock.yaml"]
|
|
232
|
+
SorbetBase["Sorbet::BaseProvider\nRBS::Prototype::RBI\nbridge"]
|
|
233
|
+
SorbetSource["Sorbet::SourceProvider\nInline sig{}\ndeclarations"]
|
|
234
|
+
SorbetRBI["Sorbet::RBIProvider\n.rbi files\ndirectories"]
|
|
235
|
+
end
|
|
186
236
|
|
|
187
|
-
|
|
188
|
-
|
|
237
|
+
subgraph YardTypes["YARD Type Parser"]
|
|
238
|
+
YParser["Yard::Parser\nParse YARD type\nstrings -> AST"]
|
|
239
|
+
YFormatter["Yard::Formatter\nYARD AST ->\nRBS string"]
|
|
240
|
+
YTypes["Yard::Types\n9 AST node types\n(Named, Generic, etc.)"]
|
|
241
|
+
end
|
|
189
242
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
243
|
+
Exe --> Run
|
|
244
|
+
Run --> Options
|
|
245
|
+
Run --> InitCmd
|
|
246
|
+
Run --> GenCmd
|
|
247
|
+
Run --> SigsCmd
|
|
248
|
+
Run --> RbsGenCmd
|
|
249
|
+
Run --> SarifFormatter
|
|
250
|
+
Run --> ConfigBuilder
|
|
251
|
+
ConfigBuilder --> ConfigClass
|
|
252
|
+
ConfigClass --> Defaults
|
|
253
|
+
ConfigClass --> Loader
|
|
254
|
+
ConfigClass --> Emit
|
|
255
|
+
ConfigClass --> Filtering
|
|
256
|
+
ConfigClass --> RBSConfig
|
|
257
|
+
ConfigClass --> SorbetConfig
|
|
258
|
+
ConfigClass --> PluginConfig
|
|
259
|
+
Run --> InlineRewriter
|
|
260
|
+
InlineRewriter --> ParsingModule
|
|
261
|
+
ParsingModule --> ParserGem
|
|
262
|
+
ParsingModule --> Prism
|
|
263
|
+
InlineRewriter --> Collector
|
|
264
|
+
Collector --> PluginModule
|
|
265
|
+
PluginModule --> Registry
|
|
266
|
+
Registry --> CollectorPlugin
|
|
267
|
+
InlineRewriter --> DocBuilder
|
|
268
|
+
DocBuilder --> InferModule
|
|
269
|
+
InferModule --> Params
|
|
270
|
+
InferModule --> Returns
|
|
271
|
+
InferModule --> Raises
|
|
272
|
+
Params --> Literals
|
|
273
|
+
Returns --> Literals
|
|
274
|
+
Raises --> ASTWalk
|
|
275
|
+
Raises --> Names
|
|
276
|
+
DocBuilder --> ProviderChain
|
|
277
|
+
ProviderChain --> SorbetSource
|
|
278
|
+
ProviderChain --> SorbetRBI
|
|
279
|
+
ProviderChain --> RBSProvider
|
|
280
|
+
SorbetSource --> SorbetBase
|
|
281
|
+
SorbetRBI --> SorbetBase
|
|
282
|
+
RBSProvider --> RBSFormatter
|
|
283
|
+
RBSProvider --> RBSCollection
|
|
284
|
+
DocBuilder --> PluginModule
|
|
285
|
+
PluginModule --> Registry
|
|
286
|
+
Registry --> TagPlugin
|
|
287
|
+
TagPlugin --> TagValue
|
|
288
|
+
TagPlugin --> Context
|
|
289
|
+
InlineRewriter --> DocBlock
|
|
290
|
+
InlineRewriter --> SourceHelpers
|
|
291
|
+
RbsGenCmd --> ParsingModule
|
|
292
|
+
RbsGenCmd --> YParser
|
|
293
|
+
YParser --> YTypes
|
|
294
|
+
YParser --> YFormatter
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Data flow
|
|
298
|
+
|
|
299
|
+
```mermaid
|
|
300
|
+
flowchart LR
|
|
301
|
+
Input["Source files\n(.rb)"] --> Parse["Parsing.parse_buffer\nParser gem / Prism"]
|
|
302
|
+
Parse --> AST["AST + Comments"]
|
|
303
|
+
AST --> Collect["Collector.process\n· Find methods\n· Track visibility\n· Find attr_*"]
|
|
304
|
+
AST --> CollectPlugins["CollectorPlugin#collect\n· Custom AST walks\n· Non-standard constructs"]
|
|
305
|
+
Collect --> Insertions["Insertion list\n(sorted by position)"]
|
|
306
|
+
CollectPlugins --> Insertions
|
|
307
|
+
Insertions --> Dedup["Deduplicate\n(override by position)"]
|
|
308
|
+
Dedup --> Build["DocBuilder.build_doc_lines\nper insertion"]
|
|
309
|
+
Build --> Infer["Infer params / returns / raises\n(heuristic fallback)"]
|
|
310
|
+
Build --> SigQuery["ProviderChain\nquery external types"]
|
|
311
|
+
Build --> TagPlugins["TagPlugin#call\n(add extra @tags)"]
|
|
312
|
+
Infer --> ResultDoc["Generated YARD doc block"]
|
|
313
|
+
SigQuery --> ResultDoc
|
|
314
|
+
TagPlugins --> ResultDoc
|
|
315
|
+
ResultDoc --> Strategy{"Strategy?"}
|
|
316
|
+
Strategy -->|Safe| Merge["DocBlock.merge\npreserve + append + sort"]
|
|
317
|
+
Strategy -->|Aggressive| Replace["Replace entirely"]
|
|
318
|
+
Merge --> Rewritten["Rewriter#process\n-> rewritten source"]
|
|
319
|
+
Replace --> Rewritten
|
|
320
|
+
Rewritten --> Output["Modified .rb file\n/ STDOUT"]
|
|
199
321
|
```
|
|
200
322
|
|
|
201
|
-
> [!NOTE]
|
|
202
|
-
> - The tool inserts doc headers before method headers and preserves everything else.
|
|
203
|
-
> - For methods with a leading Sorbet `sig`, docs are inserted above the first `sig`.
|
|
204
|
-
> - Class methods show with a dot (`+Demo.bump+`, `+Demo.internal+`).
|
|
205
|
-
> - Methods inside `class << self` under `private` are marked `@private`.
|
|
206
|
-
|
|
207
323
|
## CLI
|
|
208
324
|
|
|
209
325
|
```shell
|
|
210
326
|
docscribe [options] [files...]
|
|
327
|
+
docscribe init [options]
|
|
328
|
+
docscribe generate [type] [name] [options]
|
|
329
|
+
docscribe sigs [options] [files...]
|
|
330
|
+
docscribe rbs [options] [files...]
|
|
331
|
+
docscribe update_types [directory]
|
|
332
|
+
docscribe check_for_comments [paths...]
|
|
211
333
|
```
|
|
212
334
|
|
|
213
335
|
Docscribe has three main ways to run:
|
|
214
336
|
|
|
215
|
-
- **Inspect mode** (default): checks what safe doc updates would be applied and exits
|
|
337
|
+
- **Inspect mode** (default): checks what safe doc updates would be applied and exits 1 if files need changes.
|
|
216
338
|
- **Safe autocorrect** (`-a`, `--autocorrect`): writes safe, non-destructive updates in place.
|
|
217
339
|
- **Aggressive autocorrect** (`-A`, `--autocorrect-all`): rewrites existing doc blocks more aggressively.
|
|
218
340
|
- **STDIN mode** (`--stdin`): reads Ruby source from STDIN and prints rewritten source to STDOUT.
|
|
219
341
|
|
|
220
|
-
If you pass no files and don
|
|
342
|
+
If you pass no files and don't use `--stdin`, Docscribe processes the current directory recursively.
|
|
343
|
+
|
|
344
|
+
### Exit codes
|
|
345
|
+
|
|
346
|
+
- **0** — all files are up to date (no changes needed)
|
|
347
|
+
- **1** — some files need documentation updates
|
|
348
|
+
- **2** — execution error (parse error, missing files, etc.)
|
|
221
349
|
|
|
222
350
|
### Options
|
|
223
351
|
|
|
@@ -236,10 +364,28 @@ If you pass no files and don’t use `--stdin`, Docscribe processes the current
|
|
|
236
364
|
Read source from STDIN and print rewritten output.
|
|
237
365
|
|
|
238
366
|
- `--verbose`
|
|
239
|
-
Print per-file actions.
|
|
367
|
+
Print per-file actions. Also enables `--progress`.
|
|
368
|
+
|
|
369
|
+
- `--progress`
|
|
370
|
+
Show progress (`[N/total] path/to/file.rb`) on stderr as each file is processed.
|
|
371
|
+
|
|
372
|
+
- `--quiet` (`-q`)
|
|
373
|
+
Only show status, no details (suppresses change reasons).
|
|
374
|
+
Overrides the default detailed output.
|
|
240
375
|
|
|
241
376
|
- `--explain`
|
|
242
|
-
Show detailed reasons for each file
|
|
377
|
+
Show detailed reasons for each file (default; no-op for compatibility).
|
|
378
|
+
|
|
379
|
+
- `-k`, `--keep-descriptions`
|
|
380
|
+
Preserve existing documentation text when rebuilding doc blocks in aggressive mode.
|
|
381
|
+
|
|
382
|
+
- `-B`, `--no-boilerplate`
|
|
383
|
+
Suppress boilerplate text (`Method documentation.`, `Param documentation.`) in output.
|
|
384
|
+
Equivalent to `emit.include_default_message: false` and `emit.include_param_documentation: false` in config.
|
|
385
|
+
|
|
386
|
+
- `--format FORMAT`
|
|
387
|
+
Output format: `text` (default, human-readable), `json` (machine-readable, RuboCop-compatible), or `sarif` (SARIF 2.1
|
|
388
|
+
JSON, compatible with GitHub Code Scanning).
|
|
243
389
|
|
|
244
390
|
- `--rbs`
|
|
245
391
|
Use RBS signatures for `@param`/`@return` when available (falls back to inference).
|
|
@@ -247,6 +393,12 @@ If you pass no files and don’t use `--stdin`, Docscribe processes the current
|
|
|
247
393
|
- `--sig-dir DIR`
|
|
248
394
|
Add an RBS signature directory (repeatable). Implies `--rbs`.
|
|
249
395
|
|
|
396
|
+
- `--sorbet`
|
|
397
|
+
Use Sorbet signatures for `@param`/`@return` when available (falls back to inference).
|
|
398
|
+
|
|
399
|
+
- `--rbi-dir DIR`
|
|
400
|
+
Add an Sorbet RBI directory (repeatable). Implies `--sorbet`.
|
|
401
|
+
|
|
250
402
|
- `--include PATTERN`
|
|
251
403
|
Include PATTERN (method id or file path; glob or `/regex/`).
|
|
252
404
|
|
|
@@ -307,9 +459,146 @@ If you pass no files and don’t use `--stdin`, Docscribe processes the current
|
|
|
307
459
|
|
|
308
460
|
- Show detailed reasons for files that would change:
|
|
309
461
|
```shell
|
|
310
|
-
docscribe --verbose
|
|
462
|
+
docscribe --verbose lib
|
|
311
463
|
```
|
|
312
464
|
|
|
465
|
+
### `docscribe sigs` — check RBS signature coverage
|
|
466
|
+
|
|
467
|
+
> [!WARNING]
|
|
468
|
+
> `docscribe sigs` requires **Ruby 3.0+** and the `rbs` gem. On Ruby 2.7 it will print an error and exit with code 2.
|
|
469
|
+
|
|
470
|
+
`docscribe sigs` parses Ruby files, extracts method definitions, and checks each
|
|
471
|
+
method against the configured RBS signature directories. Reports methods that lack RBS type signatures.
|
|
472
|
+
|
|
473
|
+
```shell
|
|
474
|
+
# Check lib/ against sig/ signatures
|
|
475
|
+
docscribe sigs lib
|
|
476
|
+
|
|
477
|
+
# Use RBS collection
|
|
478
|
+
docscribe sigs --rbs-collection lib
|
|
479
|
+
|
|
480
|
+
# Multiple signature directories
|
|
481
|
+
docscribe sigs -s sig -s vendor/sigs lib
|
|
482
|
+
|
|
483
|
+
# Verbose output (also prints methods that have signatures)
|
|
484
|
+
docscribe sigs --verbose lib
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
**Flags:**
|
|
488
|
+
|
|
489
|
+
- `-s`, `--sig-dir DIR` — add an RBS signature directory (repeatable). Default: `sig`.
|
|
490
|
+
- `--rbs-collection` — use RBS collection (reads `rbs_collection.lock.yaml`).
|
|
491
|
+
- `--verbose` — also print methods that have signatures.
|
|
492
|
+
- `-h`, `--help` — show help.
|
|
493
|
+
|
|
494
|
+
**Exit codes:**
|
|
495
|
+
|
|
496
|
+
- `0` — all methods have RBS signatures.
|
|
497
|
+
- `1` — some methods lack RBS signatures.
|
|
498
|
+
- `2` — error occurred.
|
|
499
|
+
|
|
500
|
+
### `docscribe rbs` — generate RBS from YARD
|
|
501
|
+
|
|
502
|
+
> [!WARNING]
|
|
503
|
+
> `docscribe rbs` requires **Ruby 3.0+** and the `rbs` gem. On Ruby 2.7 it will print an error and exit with code 2.
|
|
504
|
+
|
|
505
|
+
`docscribe rbs` parses YARD comments (`@param`, `@return`, `@option`) from Ruby files
|
|
506
|
+
and generates corresponding `.rbs` signature files.
|
|
507
|
+
|
|
508
|
+
```shell
|
|
509
|
+
# Generate RBS files in sig/
|
|
510
|
+
docscribe rbs lib
|
|
511
|
+
|
|
512
|
+
# Print to stdout (no files written)
|
|
513
|
+
docscribe rbs -n lib
|
|
514
|
+
|
|
515
|
+
# Specify output directory
|
|
516
|
+
docscribe rbs -o sig/gen lib
|
|
517
|
+
|
|
518
|
+
# Overwrite existing files
|
|
519
|
+
docscribe rbs -f lib
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
**Flags:**
|
|
523
|
+
|
|
524
|
+
- `-o`, `--output DIR` — output directory (default: `sig`).
|
|
525
|
+
- `-n`, `--dry-run` — print generated RBS to stdout, do not write files.
|
|
526
|
+
- `-f`, `--force` — overwrite existing files.
|
|
527
|
+
- `-h`, `--help` — show help.
|
|
528
|
+
|
|
529
|
+
**Exit codes:**
|
|
530
|
+
|
|
531
|
+
- `0` — success.
|
|
532
|
+
- `1` — errors occurred during processing.
|
|
533
|
+
- `2` — execution error (no files found).
|
|
534
|
+
|
|
535
|
+
```ruby
|
|
536
|
+
# Example: lib/user.rb
|
|
537
|
+
class User
|
|
538
|
+
# @param [String] name
|
|
539
|
+
# @param [Integer] age
|
|
540
|
+
# @return [User]
|
|
541
|
+
def initialize(name, age)
|
|
542
|
+
@name = name
|
|
543
|
+
@age = age
|
|
544
|
+
end
|
|
545
|
+
end
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
```shell
|
|
549
|
+
docscribe rbs lib
|
|
550
|
+
# Generated sig/user.rbs
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
```ruby.rbs
|
|
554
|
+
# sig/user.rbs
|
|
555
|
+
class User
|
|
556
|
+
def initialize: (String name, Integer age) -> User
|
|
557
|
+
end
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
### `docscribe update_types` — two-pass type-aware documentation update
|
|
561
|
+
|
|
562
|
+
> [!NOTE]
|
|
563
|
+
> `docscribe update_types` is a convenience alias for the two-pass workflow above. It requires Ruby 3.0+ and the `rbs`
|
|
564
|
+
> gem (because of `--rbs-collection`). The RBS collection must be set up first with
|
|
565
|
+
> `bundle exec rbs collection install`. Type accuracy depends on your RBS signatures — if signatures are incomplete or
|
|
566
|
+
> missing, types will fall back to AST inference.
|
|
567
|
+
|
|
568
|
+
`docscribe update_types` runs two passes to bring both docs and RBS signatures up to date:
|
|
569
|
+
|
|
570
|
+
1. **Pass 1** — `docscribe -AkB --rbs-collection <dir>`: aggressively rebuilds doc blocks, preserves existing
|
|
571
|
+
descriptions, suppresses boilerplate, uses RBS collection types.
|
|
572
|
+
2. **Pass 2** — `docscribe -aB --rbs-collection <dir>`: safe merge cleanup with no boilerplate.
|
|
573
|
+
|
|
574
|
+
```shell
|
|
575
|
+
# Update docs in lib/ using RBS collection
|
|
576
|
+
docscribe update_types lib
|
|
577
|
+
|
|
578
|
+
# Defaults to current directory
|
|
579
|
+
docscribe update_types
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
### `docscribe check_for_comments` — find placeholder documentation
|
|
583
|
+
|
|
584
|
+
`docscribe check_for_comments` scans Ruby source files for YARD comments that still contain default placeholder
|
|
585
|
+
text. Reads the configured placeholder messages from `docscribe.yml` (or built-in defaults). Useful in CI to catch
|
|
586
|
+
files where auto-generated text was never replaced with real documentation.
|
|
587
|
+
|
|
588
|
+
```shell
|
|
589
|
+
# Scan entire project
|
|
590
|
+
docscribe check_for_comments
|
|
591
|
+
|
|
592
|
+
# Scan specific directories
|
|
593
|
+
docscribe check_for_comments lib app
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
Exit code `0` if no placeholders found, `1` if any are detected.
|
|
597
|
+
|
|
598
|
+
**Flags:**
|
|
599
|
+
|
|
600
|
+
- `-h`, `--help` — show help.
|
|
601
|
+
|
|
313
602
|
## Update strategies
|
|
314
603
|
|
|
315
604
|
Docscribe supports two update strategies: **safe** and **aggressive**.
|
|
@@ -344,6 +633,9 @@ Aggressive strategy:
|
|
|
344
633
|
|
|
345
634
|
Use it when you want to rebaseline or regenerate docs wholesale.
|
|
346
635
|
|
|
636
|
+
> [!CAUTION]
|
|
637
|
+
> Aggressive mode rewrites existing doc blocks entirely. Review changes with `git diff` before committing.
|
|
638
|
+
|
|
347
639
|
### Output markers
|
|
348
640
|
|
|
349
641
|
In inspect mode, Docscribe prints one character per file:
|
|
@@ -351,14 +643,20 @@ In inspect mode, Docscribe prints one character per file:
|
|
|
351
643
|
- `.` = file is up to date
|
|
352
644
|
- `F` = file would change
|
|
353
645
|
- `E` = file had an error
|
|
646
|
+
- `M` = type mismatch detected (external RBS/Sorbet signature differs from inferred type)
|
|
354
647
|
|
|
355
648
|
In write modes:
|
|
356
649
|
|
|
357
650
|
- `.` = file already OK
|
|
358
651
|
- `C` = file was updated
|
|
359
652
|
- `E` = file had an error
|
|
653
|
+
- `M` = file updated but type mismatch remains
|
|
360
654
|
|
|
361
|
-
|
|
655
|
+
> [!IMPORTANT]
|
|
656
|
+
> The `M` marker only appears when `--rbs` or `--sorbet` is enabled, since type mismatches are detected by
|
|
657
|
+
> comparing external signatures against inferred types.
|
|
658
|
+
|
|
659
|
+
With `--verbose`, Docscribe prints per-file statuses instead; type mismatches show as `MT` with the specific difference.
|
|
362
660
|
|
|
363
661
|
With `--explain`, Docscribe also prints detailed reasons, such as:
|
|
364
662
|
|
|
@@ -367,6 +665,27 @@ With `--explain`, Docscribe also prints detailed reasons, such as:
|
|
|
367
665
|
- missing module_function note
|
|
368
666
|
- unsorted tags
|
|
369
667
|
|
|
668
|
+
Use `--quiet` to suppress these details and show only file names and the summary line.
|
|
669
|
+
|
|
670
|
+
## Tips & tricks
|
|
671
|
+
|
|
672
|
+
Useful flag combinations for common workflows:
|
|
673
|
+
|
|
674
|
+
- `docscribe -aB lib` — safe autocorrect without boilerplate. Uses safe mode but suppresses default text, leaving only
|
|
675
|
+
type tags (`@param`, `@return`). Clean minimal docs.
|
|
676
|
+
- `docscribe -AkB lib` — aggressive autocorrect with preserved descriptions and no boilerplate. Rebuilds doc blocks,
|
|
677
|
+
keeps your hand-written descriptions, suppresses default text. Best for rebaselining.
|
|
678
|
+
- `docscribe -a --rbs-collection lib` — safe autocorrect using RBS gem collection signatures. Recommended for Rails
|
|
679
|
+
projects.
|
|
680
|
+
- `docscribe -a --sorbet --rbi-dir sorbet/rbi lib` — safe autocorrect using Sorbet RBI signatures.
|
|
681
|
+
- `docscribe update_types lib` — two-pass type-aware update: aggressively rebuilds docs with kept descriptions and RBS
|
|
682
|
+
collection, then safe-merges to clean up.
|
|
683
|
+
See [docscribe update_types](#docscribe-update_types--two-pass-type-aware-documentation-update).
|
|
684
|
+
|
|
685
|
+
> [!NOTE]
|
|
686
|
+
> `docscribe update_types` is a convenient shortcut, but be aware it uses `--rbs-collection` under the hood.
|
|
687
|
+
> If your RBS signatures are incomplete, types may fall back to AST inference.
|
|
688
|
+
|
|
370
689
|
## Parser backend (Parser gem vs Prism)
|
|
371
690
|
|
|
372
691
|
Docscribe internally works with `parser`-gem-compatible AST nodes and `Parser::Source::*` objects (so it can use
|
|
@@ -375,6 +694,11 @@ Docscribe internally works with `parser`-gem-compatible AST nodes and `Parser::S
|
|
|
375
694
|
- On Ruby **<= 3.3**, Docscribe parses using the `parser` gem.
|
|
376
695
|
- On Ruby **>= 3.4**, Docscribe parses using **Prism** and translates the tree into the `parser` gem's AST.
|
|
377
696
|
|
|
697
|
+
> [!NOTE]
|
|
698
|
+
> Prism support is automatic on Ruby 3.4+. On earlier Rubies, the `parser` gem is always used.
|
|
699
|
+
> You can override with `DOCSCRIBE_PARSER_BACKEND=prism` on Ruby 3.1+ if you have the `prism` gem installed,
|
|
700
|
+
> but this is not recommended for production use.
|
|
701
|
+
|
|
378
702
|
You can force a backend with an environment variable:
|
|
379
703
|
|
|
380
704
|
```shell
|
|
@@ -388,16 +712,33 @@ Docscribe can improve generated `@param` and `@return` types by reading external
|
|
|
388
712
|
AST inference.
|
|
389
713
|
|
|
390
714
|
> [!IMPORTANT]
|
|
391
|
-
>
|
|
392
|
-
>
|
|
393
|
-
>
|
|
394
|
-
>
|
|
395
|
-
>
|
|
715
|
+
> Docscribe resolves types in a two-level chain. For **documentation tags** (`@param`, `@return`), the priority is:
|
|
716
|
+
>
|
|
717
|
+
> | Priority | Source | When active |
|
|
718
|
+
> |----------|-------------------------------------------------------------|----------------------------------------------------------|
|
|
719
|
+
> | **1** | Inline Sorbet `sig { ... }` in current file | `--sorbet` or `sorbet.enabled: true` |
|
|
720
|
+
> | **2** | Sorbet RBI files (`.rbi`) | `--sorbet --rbi-dir` or `sorbet.rbi_dirs` |
|
|
721
|
+
> | **3** | RBS files (sig_dirs + collection, loaded into one env) | `--rbs --sig-dir` / `--rbs-collection` or `rbs.*` config |
|
|
722
|
+
> | **3a** | └─ Fallback: sig_dirs only (collection dropped on conflict) | Automatic if priority 3 env load fails |
|
|
723
|
+
> | **4** | AST inference (fallback) | Always active |
|
|
396
724
|
>
|
|
397
|
-
>
|
|
725
|
+
> For **intra-method body inference** (e.g. resolving `Integer#positive?` -> `Boolean`), a separate core RBS provider
|
|
726
|
+
> loads only stdlib/built-in signatures and is active automatically when the `rbs` gem is available — even without
|
|
727
|
+
> `--rbs`.
|
|
728
|
+
>
|
|
729
|
+
> If an external signature cannot be loaded or parsed, Docscribe falls back to the next source in the chain instead of
|
|
730
|
+
> failing.
|
|
398
731
|
|
|
399
732
|
### RBS
|
|
400
733
|
|
|
734
|
+
> [!IMPORTANT]
|
|
735
|
+
> All RBS features require the `rbs` gem. Add `gem "rbs"` to your Gemfile and run `bundle install`,
|
|
736
|
+
> or install it globally with `gem install rbs`.
|
|
737
|
+
>
|
|
738
|
+
> On Ruby 2.7 the `rbs` gem cannot load at all — `--rbs`, `--sig-dir`, `--rbs-collection`,
|
|
739
|
+
> `docscribe sigs`, and `docscribe rbs` will print a warning and fall back to AST-only inference.
|
|
740
|
+
> On Ruby 3.0+, if the gem is missing, Docscribe silently falls back to inference when you pass RBS flags.
|
|
741
|
+
|
|
401
742
|
Docscribe can read method signatures from `.rbs` files and use them to generate more accurate parameter and return
|
|
402
743
|
types.
|
|
403
744
|
|
|
@@ -417,12 +758,23 @@ Config:
|
|
|
417
758
|
|
|
418
759
|
```yaml
|
|
419
760
|
rbs:
|
|
420
|
-
enabled:
|
|
761
|
+
enabled: false
|
|
421
762
|
sig_dirs:
|
|
422
763
|
- sig
|
|
764
|
+
collection: false
|
|
423
765
|
collapse_generics: false
|
|
766
|
+
collapse_object_generics: false
|
|
767
|
+
warn_missing_collection: true
|
|
424
768
|
```
|
|
425
769
|
|
|
770
|
+
- `collection` — enable auto-discovery of RBS collection from `rbs_collection.lock.yaml`. Pass `--rbs-collection` on the
|
|
771
|
+
CLI.
|
|
772
|
+
- `collapse_generics` — strip all generic type arguments (e.g. `Array<String>` -> `Array`).
|
|
773
|
+
- `collapse_object_generics` — only strip generic arguments when all are `Object` (e.g. `Hash<Object, Object>` ->
|
|
774
|
+
`Hash`, but `Hash<Symbol, Object>` stays).
|
|
775
|
+
- `warn_missing_collection` — warn on stderr when `rbs_collection.lock.yaml` is found but collection is not enabled. Set
|
|
776
|
+
to `false` to suppress.
|
|
777
|
+
|
|
426
778
|
Example:
|
|
427
779
|
|
|
428
780
|
```ruby
|
|
@@ -645,24 +997,29 @@ end
|
|
|
645
997
|
|
|
646
998
|
### Generic type formatting
|
|
647
999
|
|
|
648
|
-
Both RBS and Sorbet integrations support
|
|
1000
|
+
Both RBS and Sorbet integrations support generic type collapsing.
|
|
649
1001
|
|
|
650
|
-
|
|
1002
|
+
**`collapse_generics`** — strips all generic type arguments.
|
|
1003
|
+
**`collapse_object_generics`** — only strips arguments when all are `Object` (e.g. `Hash<Object, Object>` -> `Hash`, but
|
|
1004
|
+
`Hash<Symbol, Object>` stays).
|
|
1005
|
+
|
|
1006
|
+
When both disabled:
|
|
651
1007
|
|
|
652
1008
|
```yaml
|
|
653
1009
|
rbs:
|
|
654
1010
|
collapse_generics: false
|
|
1011
|
+
collapse_object_generics: false
|
|
655
1012
|
|
|
656
1013
|
sorbet:
|
|
657
1014
|
collapse_generics: false
|
|
658
1015
|
```
|
|
659
1016
|
|
|
660
|
-
Docscribe preserves generic container details
|
|
1017
|
+
Docscribe preserves generic container details, for example:
|
|
661
1018
|
|
|
662
1019
|
- `Array<String>`
|
|
663
1020
|
- `Hash<Symbol, Integer>`
|
|
664
1021
|
|
|
665
|
-
When enabled:
|
|
1022
|
+
When `collapse_generics` is enabled:
|
|
666
1023
|
|
|
667
1024
|
```yaml
|
|
668
1025
|
rbs:
|
|
@@ -672,7 +1029,7 @@ sorbet:
|
|
|
672
1029
|
collapse_generics: true
|
|
673
1030
|
```
|
|
674
1031
|
|
|
675
|
-
Docscribe simplifies container types to their outer names, for example:
|
|
1032
|
+
Docscribe simplifies all container types to their outer names, for example:
|
|
676
1033
|
|
|
677
1034
|
- `Array`
|
|
678
1035
|
- `Hash`
|
|
@@ -707,6 +1064,11 @@ Return values:
|
|
|
707
1064
|
- For simple bodies, Docscribe looks at the last expression or explicit `return`.
|
|
708
1065
|
- Unions with `nil` become optional types (e.g. `String` or `nil` -> `String?`).
|
|
709
1066
|
- For control flow (`if`/`case`), it unifies branches conservatively.
|
|
1067
|
+
|
|
1068
|
+
> [!TIP]
|
|
1069
|
+
> Docscribe resolves return types for core Ruby methods (`Integer#positive?`, `String#upcase`, etc.)
|
|
1070
|
+
> **even without `--rbs`** — the core RBS provider is always active when the `rbs` gem is available.
|
|
1071
|
+
|
|
710
1072
|
- **RBS core type inference**: when `--rbs` is enabled, Docscribe resolves return types for method calls on core types
|
|
711
1073
|
from their RBS definitions:
|
|
712
1074
|
- `arg.positive?` (`arg = 1`) -> `Boolean` (from `Integer#positive?`)
|
|
@@ -1019,6 +1381,19 @@ Sample plugins available at [examples](examples/plugins):
|
|
|
1019
1381
|
|
|
1020
1382
|
Docscribe can be configured via a YAML file (`docscribe.yml` by default, or pass `--config PATH`).
|
|
1021
1383
|
|
|
1384
|
+
### Anonymous block parameters
|
|
1385
|
+
|
|
1386
|
+
Ruby 3.2+ allows anonymous block arguments (`def foo(&)`). By default, Docscribe generates `@param [Proc] block` for
|
|
1387
|
+
these — but since the parameter has no name, the tag is misleading.
|
|
1388
|
+
|
|
1389
|
+
To suppress the `@param` tag for anonymous block arguments:
|
|
1390
|
+
|
|
1391
|
+
```yaml
|
|
1392
|
+
skip_anonymous_block_params: true
|
|
1393
|
+
```
|
|
1394
|
+
|
|
1395
|
+
When `false` (default), anonymous block params generate `@param [Proc] block`.
|
|
1396
|
+
|
|
1022
1397
|
### Filtering
|
|
1023
1398
|
|
|
1024
1399
|
Docscribe can filter both *files* and *methods*.
|
|
@@ -1242,6 +1617,7 @@ docscribe generate tag SincePlugin --stdout
|
|
|
1242
1617
|
```
|
|
1243
1618
|
|
|
1244
1619
|
The generated file contains:
|
|
1620
|
+
|
|
1245
1621
|
- the correct base class (`Base::TagPlugin` or `Base::CollectorPlugin`)
|
|
1246
1622
|
- inline comments describing every available `Context` attribute (TagPlugin)
|
|
1247
1623
|
or the expected return shape (CollectorPlugin)
|
|
@@ -1252,6 +1628,58 @@ The generated file contains:
|
|
|
1252
1628
|
> The class name must be a valid Ruby constant (`MyPlugin`, `My::Plugin`).
|
|
1253
1629
|
> The output filename is the snake_case equivalent (`my_plugin.rb`, `my/plugin.rb`).
|
|
1254
1630
|
|
|
1631
|
+
### Full configuration reference
|
|
1632
|
+
|
|
1633
|
+
<details>
|
|
1634
|
+
<summary>Click to expand — 43 config keys</summary>
|
|
1635
|
+
|
|
1636
|
+
| Key | Type | Default | Description |
|
|
1637
|
+
|-------------------------------------------|------------|----------------------------------------------------------------------------------------------|----------------------------------------------------------------------------|
|
|
1638
|
+
| `keep_descriptions` | `bool` | `false` | Preserve existing doc text in aggressive mode |
|
|
1639
|
+
| `skip_anonymous_block_params` | `bool` | `false` | Skip `@param [Proc] block` for anonymous `&` params |
|
|
1640
|
+
| `emit.header` | `bool` | `false` | Generate method header line (`+#foo+ -> ...`) |
|
|
1641
|
+
| `emit.include_default_message` | `bool` | `true` | Insert default message (`Method documentation.`) |
|
|
1642
|
+
| `emit.include_param_documentation` | `bool` | `true` | Insert param description text (`Param documentation.`) |
|
|
1643
|
+
| `emit.param_tags` | `bool` | `true` | Generate `@param` tags |
|
|
1644
|
+
| `emit.return_tag` | `bool` | `true` | Generate `@return` tag |
|
|
1645
|
+
| `emit.visibility_tags` | `bool` | `true` | Generate `@private`/`@protected` tags |
|
|
1646
|
+
| `emit.raise_tags` | `bool` | `true` | Generate `@raise` tags (for `raise` in method body) |
|
|
1647
|
+
| `emit.rescue_conditional_returns` | `bool` | `true` | Consider `rescue` branches in return type inference |
|
|
1648
|
+
| `emit.attributes` | `bool` | `false` | Generate `@!attribute` for `attr_*` and `Struct.new` |
|
|
1649
|
+
| `doc.default_message` | `string` | `"Method documentation."` | Default text for method description |
|
|
1650
|
+
| `doc.param_documentation` | `string` | `"Param documentation."` | Default text for param description |
|
|
1651
|
+
| `doc.sort_tags` | `bool` | `true` | Sort tags according to `tag_order` |
|
|
1652
|
+
| `doc.tag_order` | `string[]` | `["todo","note","api","private","protected","param","option","yieldparam","raise","return"]` | Tag sort order |
|
|
1653
|
+
| `doc.param_tag_style` | `string` | `"type_name"` | `@param` style: `type_name` (`[Type] name`) or `name_type` (`name [Type]`) |
|
|
1654
|
+
| `inference.fallback_type` | `string` | `"Object"` | Fallback type when inference yields no result |
|
|
1655
|
+
| `inference.nil_as_optional` | `bool` | `true` | Treat `nil` as an optional type |
|
|
1656
|
+
| `inference.treat_options_keyword_as_hash` | `bool` | `true` | Treat `**options` as `Hash` in `@option` tags |
|
|
1657
|
+
| `filter.include` | `string[]` | `[]` | Only include methods matching pattern |
|
|
1658
|
+
| `filter.exclude` | `string[]` | `[]` | Exclude methods matching pattern |
|
|
1659
|
+
| `filter.visibilities` | `string[]` | `["public","protected","private"]` | Visibilities to process |
|
|
1660
|
+
| `filter.scopes` | `string[]` | `["instance","class"]` | Scopes to process |
|
|
1661
|
+
| `filter.files.include` | `string[]` | `[]` | Only process files matching pattern |
|
|
1662
|
+
| `filter.files.exclude` | `string[]` | `["spec"]` | Skip files matching pattern |
|
|
1663
|
+
| `methods.instance.public` | `object` | `{}` | Overrides for instance public methods |
|
|
1664
|
+
| `methods.instance.protected` | `object` | `{}` | Overrides for instance protected methods |
|
|
1665
|
+
| `methods.instance.private` | `object` | `{}` | Overrides for instance private methods |
|
|
1666
|
+
| `methods.class.public` | `object` | `{}` | Overrides for class public methods |
|
|
1667
|
+
| `methods.class.protected` | `object` | `{}` | Overrides for class protected methods |
|
|
1668
|
+
| `methods.class.private` | `object` | `{}` | Overrides for class private methods |
|
|
1669
|
+
| `rbs.enabled` | `bool` | `false` | Enable RBS integration |
|
|
1670
|
+
| `rbs.collection` | `bool` | `false` | Auto-discover RBS collection from `rbs_collection.lock.yaml` |
|
|
1671
|
+
| `rbs.sig_dirs` | `string[]` | `["sig"]` | RBS signature directories |
|
|
1672
|
+
| `rbs.collection_dirs` | `string[]` | `[]` | RBS collection directories (set automatically) |
|
|
1673
|
+
| `rbs.collapse_generics` | `bool` | `false` | Strip generic arguments (`Array<String>` -> `Array`) |
|
|
1674
|
+
| `rbs.collapse_object_generics` | `bool` | `false` | Strip generics only when all are `Object` |
|
|
1675
|
+
| `rbs.warn_missing_collection` | `bool` | `true` | Warn when `rbs_collection.lock.yaml` found but collection not enabled |
|
|
1676
|
+
| `sorbet.enabled` | `bool` | `false` | Enable Sorbet integration |
|
|
1677
|
+
| `sorbet.rbi_dirs` | `string[]` | `["sorbet/rbi","rbi"]` | RBI file directories |
|
|
1678
|
+
| `sorbet.collapse_generics` | `bool` | `false` | Strip generic arguments from Sorbet signatures |
|
|
1679
|
+
| `plugins.require` | `string[]` | `[]` | Plugin paths for `require` |
|
|
1680
|
+
|
|
1681
|
+
</details>
|
|
1682
|
+
|
|
1255
1683
|
## CI integration
|
|
1256
1684
|
|
|
1257
1685
|
Fail the build if files would need safe updates:
|
|
@@ -1268,11 +1696,33 @@ Apply safe fixes before the test stage:
|
|
|
1268
1696
|
run: docscribe -a lib
|
|
1269
1697
|
```
|
|
1270
1698
|
|
|
1271
|
-
|
|
1699
|
+
Rebuild docs aggressively, preserve descriptions, suppress boilerplate, with verbose output:
|
|
1272
1700
|
|
|
1273
1701
|
```yaml
|
|
1274
1702
|
- name: Rebuild inline docs
|
|
1275
|
-
run: docscribe -
|
|
1703
|
+
run: docscribe -AkB --verbose
|
|
1704
|
+
```
|
|
1705
|
+
|
|
1706
|
+
Run static type checking with Steep (requires Ruby ≥ 3.2):
|
|
1707
|
+
|
|
1708
|
+
```yaml
|
|
1709
|
+
- name: Steep (type check)
|
|
1710
|
+
if: ${{ matrix.ruby >= 3.2 }}
|
|
1711
|
+
run: bundle exec steep check
|
|
1712
|
+
```
|
|
1713
|
+
|
|
1714
|
+
Fail the build if any generated docs still contain default placeholder text:
|
|
1715
|
+
|
|
1716
|
+
```yaml
|
|
1717
|
+
- name: Check for placeholder docs
|
|
1718
|
+
run: docscribe check_for_comments lib/
|
|
1719
|
+
```
|
|
1720
|
+
|
|
1721
|
+
For stricter validation, check for empty doc blocks:
|
|
1722
|
+
|
|
1723
|
+
```yaml
|
|
1724
|
+
- name: Check for empty doc blocks
|
|
1725
|
+
run: "! grep -rn '^ # $' lib/"
|
|
1276
1726
|
```
|
|
1277
1727
|
|
|
1278
1728
|
## Comparison to YARD's parser
|
|
@@ -1301,13 +1751,39 @@ yard doc -o docs
|
|
|
1301
1751
|
## Roadmap
|
|
1302
1752
|
|
|
1303
1753
|
- Method behavior inference from AST;
|
|
1304
|
-
-
|
|
1754
|
+
- Deeper YARD integration — parse `.c` source comments and generate docs for C-extensions;
|
|
1755
|
+
- Custom parser plugins — support non-Ruby languages (Crystal, etc.) via the plugin system;
|
|
1305
1756
|
- Effective config dump;
|
|
1306
|
-
- JSON output;
|
|
1307
1757
|
- Overload-aware signature selection;
|
|
1308
1758
|
- Manual `@!attribute` merge policy;
|
|
1309
1759
|
- Richer inference for common APIs;
|
|
1310
|
-
- Editor integration
|
|
1760
|
+
- Editor integration (LSP, VS Code extension);
|
|
1761
|
+
- Documentation coverage report — percentage of documented methods, params, returns;
|
|
1762
|
+
- Pre-commit hook auto-install (`docscribe init --pre-commit`);
|
|
1763
|
+
- Parallel processing for large codebases.
|
|
1764
|
+
|
|
1765
|
+
## Editor Integration
|
|
1766
|
+
|
|
1767
|
+
Docscribe provides IDE plugins for a better development experience:
|
|
1768
|
+
|
|
1769
|
+
### VS Code
|
|
1770
|
+
|
|
1771
|
+
[](https://marketplace.visualstudio.com/items?itemName=unurgunite.docscribe-vscode)
|
|
1772
|
+
|
|
1773
|
+
- **Repository:** [github.com/FlorexLabs/docscribe-vscode](https://github.com/FlorexLabs/docscribe-vscode)
|
|
1774
|
+
- **Marketplace:** [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=unurgunite.docscribe-vscode)
|
|
1775
|
+
- **Features:** inline diagnostics, quick-fix, auto-check on save, status bar
|
|
1776
|
+
|
|
1777
|
+
### RubyMine
|
|
1778
|
+
|
|
1779
|
+
[](https://plugins.jetbrains.com/plugin/32349-docscribe)
|
|
1780
|
+
|
|
1781
|
+
- **Repository:** [github.com/FlorexLabs/docscribe-rubymine](https://github.com/FlorexLabs/docscribe-rubymine)
|
|
1782
|
+
- **Marketplace:** [JetBrains Marketplace](https://plugins.jetbrains.com/plugin/32349-docscribe)
|
|
1783
|
+
- **Features:** ExternalAnnotator, AnAction, IntentionAction, Settings UI
|
|
1784
|
+
|
|
1785
|
+
> [!NOTE]
|
|
1786
|
+
> Both plugins require **docscribe >= 1.5.0**.
|
|
1311
1787
|
|
|
1312
1788
|
## Contributing
|
|
1313
1789
|
|
|
@@ -1322,6 +1798,14 @@ bundle exec rubocop
|
|
|
1322
1798
|
- [Dev.to article](https://dev.to/unurgunite)
|
|
1323
1799
|
- [GitHub Discussions](https://github.com/unurgunite/docscribe/discussions)
|
|
1324
1800
|
|
|
1801
|
+
## Logo Attribution
|
|
1802
|
+
|
|
1803
|
+
The Docscribe logo uses the Ruby gem icon by [FlorexLabs](https://github.com/FlorexLabs).
|
|
1804
|
+
|
|
1805
|
+
<p>
|
|
1806
|
+
<img src="assets/icons/icon_128x128.png" alt="Docscribe logo">
|
|
1807
|
+
</p>
|
|
1808
|
+
|
|
1325
1809
|
## License
|
|
1326
1810
|
|
|
1327
1811
|
MIT
|