yard-markdown 0.5.0 → 0.7.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/.yard-lint.yml +317 -0
- data/AGENTS.md +54 -0
- data/CHANGELOG.md +17 -0
- data/README.md +39 -3
- data/Rakefile +167 -2
- data/config/mutant.yml +25 -0
- data/example/rdoc/Bird.md +7 -14
- data/example/rdoc/Duck.md +28 -29
- data/example/rdoc/Waterfowl.md +3 -7
- data/example/rdoc/index.csv +5 -10
- data/example/yard/Aquatic.md +4 -9
- data/example/yard/Fish.md +13 -22
- data/example/yard/Salmon.md +37 -39
- data/example/yard/index.csv +5 -9
- data/lib/yard/markdown/anchor_component_helper.rb +20 -0
- data/lib/yard/markdown/aref_helper.rb +31 -0
- data/lib/yard/markdown/collection_rendering_helper.rb +96 -0
- data/lib/yard/markdown/documentation_helper.rb +30 -0
- data/lib/yard/markdown/heading_helper.rb +52 -0
- data/lib/yard/markdown/link_normalization_helper.rb +144 -0
- data/lib/yard/markdown/method_presentation_helper.rb +49 -0
- data/lib/yard/markdown/object_listing_helper.rb +87 -0
- data/lib/yard/markdown/relationship_section_helper.rb +38 -0
- data/lib/yard/markdown/section_assembly_helper.rb +46 -0
- data/lib/yard/markdown/tag_formatting_helper.rb +75 -0
- data/lib/yard-markdown.rb +11 -0
- data/sig/yard/markdown.rbs +346 -4
- data/templates/default/fulldoc/markdown/setup.rb +45 -220
- data/templates/default/module/markdown/setup.rb +125 -0
- metadata +33 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 41e14595e84affb837da2c36afb9a40f0e7ea866472fa32e5aefabc7c32c2ec8
|
|
4
|
+
data.tar.gz: 605f1ad9c9496ebaf48afc7245ab25db98b5e22aed88c7c718bb3968f78b3b5e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '0887584b2fe63298271fad1483237eb303d215068a6da79aee7cb59c463a6c2838a6a72171676e7876f7a7d8c9003c0e23eb0fcb9dbfd88e329f028c5907bdef'
|
|
7
|
+
data.tar.gz: 9d50e908447b65b564315c996af01a43e35d360f2bafd600d34197ed20fc0cf8fde1b506850eb2fd476ee65d33c44ff10de8658abcd51037011060d4e69ec59f
|
data/.yard-lint.yml
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# YARD-Lint Configuration (Strict Mode)
|
|
2
|
+
# See https://github.com/mensfeld/yard-lint for documentation
|
|
3
|
+
#
|
|
4
|
+
# This is a strict configuration suitable for new projects with high documentation standards.
|
|
5
|
+
# All validators are set to 'error' severity (no warnings or conventions).
|
|
6
|
+
# Minimum coverage is set to 100%.
|
|
7
|
+
|
|
8
|
+
# Global settings for all validators
|
|
9
|
+
AllValidators:
|
|
10
|
+
# YARD command-line options (applied to all validators by default)
|
|
11
|
+
YardOptions:
|
|
12
|
+
- --private
|
|
13
|
+
- --protected
|
|
14
|
+
|
|
15
|
+
# Global file exclusion patterns
|
|
16
|
+
Exclude:
|
|
17
|
+
- '\.git'
|
|
18
|
+
- "vendor/**/*"
|
|
19
|
+
- "node_modules/**/*"
|
|
20
|
+
- "spec/**/*"
|
|
21
|
+
- "test/**/*"
|
|
22
|
+
- "tmp/**/*"
|
|
23
|
+
- "example_rdoc.rb"
|
|
24
|
+
- "example_yard.rb"
|
|
25
|
+
|
|
26
|
+
# Exit code behavior (error, warning, convention, never)
|
|
27
|
+
FailOnSeverity: error
|
|
28
|
+
|
|
29
|
+
# Minimum documentation coverage percentage (0-100)
|
|
30
|
+
# Fails if coverage is below this threshold
|
|
31
|
+
MinCoverage: 100.0
|
|
32
|
+
|
|
33
|
+
# Diff mode settings
|
|
34
|
+
DiffMode:
|
|
35
|
+
# Default base ref for --diff (auto-detects main/master if not specified)
|
|
36
|
+
DefaultBaseRef: ~
|
|
37
|
+
|
|
38
|
+
# Documentation validators
|
|
39
|
+
Documentation/UndocumentedObjects:
|
|
40
|
+
Description: "Checks for classes, modules, and methods without documentation."
|
|
41
|
+
Enabled: true
|
|
42
|
+
Severity: error
|
|
43
|
+
ExcludedMethods:
|
|
44
|
+
- "initialize/0" # Exclude parameter-less initialize
|
|
45
|
+
- "/^_/" # Exclude private methods (by convention)
|
|
46
|
+
|
|
47
|
+
Documentation/UndocumentedMethodArguments:
|
|
48
|
+
Description: "Checks for method parameters without @param tags."
|
|
49
|
+
Enabled: true
|
|
50
|
+
Severity: error
|
|
51
|
+
|
|
52
|
+
Documentation/UndocumentedBooleanMethods:
|
|
53
|
+
Description: "Checks that question mark methods document their boolean return."
|
|
54
|
+
Enabled: true
|
|
55
|
+
Severity: error
|
|
56
|
+
|
|
57
|
+
Documentation/UndocumentedOptions:
|
|
58
|
+
Description: "Detects methods with options hash parameters but no @option tags."
|
|
59
|
+
Enabled: true
|
|
60
|
+
Severity: error
|
|
61
|
+
|
|
62
|
+
Documentation/MissingReturn:
|
|
63
|
+
Description: "Requires @return tags on all methods (opt-in for strict documentation)."
|
|
64
|
+
Enabled: true # Enabled in strict mode
|
|
65
|
+
Severity: error
|
|
66
|
+
ExcludedMethods:
|
|
67
|
+
- "initialize" # Exclude all initialize methods
|
|
68
|
+
# - '/^_/' # Uncomment to exclude private methods (by convention)
|
|
69
|
+
|
|
70
|
+
Documentation/MarkdownSyntax:
|
|
71
|
+
Description: "Detects common markdown syntax errors in documentation."
|
|
72
|
+
Enabled: true
|
|
73
|
+
Severity: error
|
|
74
|
+
|
|
75
|
+
Documentation/EmptyCommentLine:
|
|
76
|
+
Description: "Detects empty comment lines at the start or end of documentation blocks."
|
|
77
|
+
Enabled: true
|
|
78
|
+
Severity: error
|
|
79
|
+
EnabledPatterns:
|
|
80
|
+
Leading: true
|
|
81
|
+
Trailing: true
|
|
82
|
+
|
|
83
|
+
Documentation/BlankLineBeforeDefinition:
|
|
84
|
+
Description: "Detects blank lines between YARD documentation and method definition."
|
|
85
|
+
Enabled: true
|
|
86
|
+
Severity: error
|
|
87
|
+
OrphanedSeverity: error
|
|
88
|
+
EnabledPatterns:
|
|
89
|
+
SingleBlankLine: true
|
|
90
|
+
OrphanedDocs: true
|
|
91
|
+
|
|
92
|
+
# Tags validators
|
|
93
|
+
Tags/Order:
|
|
94
|
+
Description: "Enforces consistent ordering of YARD tags."
|
|
95
|
+
Enabled: true
|
|
96
|
+
Severity: error
|
|
97
|
+
EnforcedOrder:
|
|
98
|
+
- param
|
|
99
|
+
- option
|
|
100
|
+
- yield
|
|
101
|
+
- yieldparam
|
|
102
|
+
- yieldreturn
|
|
103
|
+
- return
|
|
104
|
+
- raise
|
|
105
|
+
- see
|
|
106
|
+
- example
|
|
107
|
+
- note
|
|
108
|
+
- todo
|
|
109
|
+
|
|
110
|
+
Tags/InvalidTypes:
|
|
111
|
+
Description: "Validates type definitions in @param, @return, @option tags."
|
|
112
|
+
Enabled: true
|
|
113
|
+
Severity: error
|
|
114
|
+
ValidatedTags:
|
|
115
|
+
- param
|
|
116
|
+
- option
|
|
117
|
+
- return
|
|
118
|
+
|
|
119
|
+
Tags/TypeSyntax:
|
|
120
|
+
Description: "Validates YARD type syntax using YARD parser."
|
|
121
|
+
Enabled: true
|
|
122
|
+
Severity: error
|
|
123
|
+
ValidatedTags:
|
|
124
|
+
- param
|
|
125
|
+
- option
|
|
126
|
+
- return
|
|
127
|
+
- yieldreturn
|
|
128
|
+
|
|
129
|
+
Tags/MeaninglessTag:
|
|
130
|
+
Description: "Detects @param/@option tags on classes, modules, or constants."
|
|
131
|
+
Enabled: true
|
|
132
|
+
Severity: error
|
|
133
|
+
CheckedTags:
|
|
134
|
+
- param
|
|
135
|
+
- option
|
|
136
|
+
InvalidObjectTypes:
|
|
137
|
+
- class
|
|
138
|
+
- module
|
|
139
|
+
- constant
|
|
140
|
+
|
|
141
|
+
Tags/CollectionType:
|
|
142
|
+
Description: "Validates Hash collection syntax consistency."
|
|
143
|
+
Enabled: true
|
|
144
|
+
Severity: error
|
|
145
|
+
EnforcedStyle: long # 'long' for Hash{K => V} (YARD standard), 'short' for {K => V}
|
|
146
|
+
ValidatedTags:
|
|
147
|
+
- param
|
|
148
|
+
- option
|
|
149
|
+
- return
|
|
150
|
+
- yieldreturn
|
|
151
|
+
|
|
152
|
+
Tags/TagTypePosition:
|
|
153
|
+
Description: "Validates type annotation position in tags."
|
|
154
|
+
Enabled: true
|
|
155
|
+
Severity: error
|
|
156
|
+
CheckedTags:
|
|
157
|
+
- param
|
|
158
|
+
- option
|
|
159
|
+
# EnforcedStyle: 'type_after_name' (YARD standard: @param name [Type])
|
|
160
|
+
# or 'type_first' (@param [Type] name)
|
|
161
|
+
EnforcedStyle: type_after_name
|
|
162
|
+
|
|
163
|
+
Tags/ApiTags:
|
|
164
|
+
Description: "Enforces @api tags on public objects."
|
|
165
|
+
Enabled: false # Opt-in validator
|
|
166
|
+
Severity: error
|
|
167
|
+
AllowedApis:
|
|
168
|
+
- public
|
|
169
|
+
- private
|
|
170
|
+
- internal
|
|
171
|
+
|
|
172
|
+
Tags/OptionTags:
|
|
173
|
+
Description: "Requires @option tags for methods with options parameters."
|
|
174
|
+
Enabled: true
|
|
175
|
+
Severity: error
|
|
176
|
+
|
|
177
|
+
Tags/ExampleSyntax:
|
|
178
|
+
Description: "Validates Ruby syntax in @example tags."
|
|
179
|
+
Enabled: true
|
|
180
|
+
Severity: error
|
|
181
|
+
|
|
182
|
+
Tags/ExampleStyle:
|
|
183
|
+
Description: "Validates code style in @example tags using RuboCop/StandardRB."
|
|
184
|
+
Enabled: false # Opt-in validator (requires RuboCop or StandardRB)
|
|
185
|
+
Severity: convention
|
|
186
|
+
# Linter: auto # Uncomment to explicitly configure: 'auto', 'rubocop', 'standard', 'none'
|
|
187
|
+
# SkipPatterns: # Uncomment to skip examples matching patterns
|
|
188
|
+
# - '/skip-lint/i'
|
|
189
|
+
# - '/bad code/i'
|
|
190
|
+
|
|
191
|
+
Tags/RedundantParamDescription:
|
|
192
|
+
Description: "Detects meaningless parameter descriptions that add no value."
|
|
193
|
+
Enabled: true
|
|
194
|
+
Severity: error
|
|
195
|
+
CheckedTags:
|
|
196
|
+
- param
|
|
197
|
+
- option
|
|
198
|
+
Articles:
|
|
199
|
+
- The
|
|
200
|
+
- the
|
|
201
|
+
- A
|
|
202
|
+
- a
|
|
203
|
+
- An
|
|
204
|
+
- an
|
|
205
|
+
MaxRedundantWords: 6
|
|
206
|
+
GenericTerms:
|
|
207
|
+
- object
|
|
208
|
+
- instance
|
|
209
|
+
- value
|
|
210
|
+
- data
|
|
211
|
+
- item
|
|
212
|
+
- element
|
|
213
|
+
EnabledPatterns:
|
|
214
|
+
ArticleParam: true
|
|
215
|
+
PossessiveParam: true
|
|
216
|
+
TypeRestatement: true
|
|
217
|
+
ParamToVerb: true
|
|
218
|
+
IdPattern: true
|
|
219
|
+
DirectionalDate: true
|
|
220
|
+
TypeGeneric: true
|
|
221
|
+
|
|
222
|
+
Tags/InformalNotation:
|
|
223
|
+
Description: 'Detects informal tag notation patterns like "Note:" instead of @note.'
|
|
224
|
+
Enabled: true
|
|
225
|
+
Severity: error
|
|
226
|
+
CaseSensitive: false
|
|
227
|
+
RequireStartOfLine: true
|
|
228
|
+
Patterns:
|
|
229
|
+
Note: "@note"
|
|
230
|
+
Todo: "@todo"
|
|
231
|
+
TODO: "@todo"
|
|
232
|
+
FIXME: "@todo"
|
|
233
|
+
See: "@see"
|
|
234
|
+
See also: "@see"
|
|
235
|
+
Warning: "@deprecated"
|
|
236
|
+
Deprecated: "@deprecated"
|
|
237
|
+
Author: "@author"
|
|
238
|
+
Version: "@version"
|
|
239
|
+
Since: "@since"
|
|
240
|
+
Returns: "@return"
|
|
241
|
+
Raises: "@raise"
|
|
242
|
+
Example: "@example"
|
|
243
|
+
|
|
244
|
+
Tags/NonAsciiType:
|
|
245
|
+
Description: "Detects non-ASCII characters in type annotations."
|
|
246
|
+
Enabled: true
|
|
247
|
+
Severity: error
|
|
248
|
+
ValidatedTags:
|
|
249
|
+
- param
|
|
250
|
+
- option
|
|
251
|
+
- return
|
|
252
|
+
- yieldreturn
|
|
253
|
+
- yieldparam
|
|
254
|
+
|
|
255
|
+
Tags/TagGroupSeparator:
|
|
256
|
+
Description: "Enforces blank line separators between different YARD tag groups."
|
|
257
|
+
Enabled: false # Opt-in validator
|
|
258
|
+
Severity: error
|
|
259
|
+
TagGroups:
|
|
260
|
+
param: [param, option]
|
|
261
|
+
return: [return]
|
|
262
|
+
error: [raise, throws]
|
|
263
|
+
example: [example]
|
|
264
|
+
meta: [see, note, todo, deprecated, since, version, api]
|
|
265
|
+
yield: [yield, yieldparam, yieldreturn]
|
|
266
|
+
RequireAfterDescription: false
|
|
267
|
+
|
|
268
|
+
Tags/ForbiddenTags:
|
|
269
|
+
Description: "Detects forbidden tag and type combinations."
|
|
270
|
+
Enabled: false # Opt-in validator
|
|
271
|
+
Severity: error
|
|
272
|
+
ForbiddenPatterns: []
|
|
273
|
+
# Example patterns:
|
|
274
|
+
# - Tag: return
|
|
275
|
+
# Types:
|
|
276
|
+
# - void
|
|
277
|
+
# - Tag: param
|
|
278
|
+
# Types:
|
|
279
|
+
# - Object
|
|
280
|
+
# - Tag: api # Forbids @api tag entirely (no Types = any occurrence)
|
|
281
|
+
|
|
282
|
+
# Warnings validators - catches YARD parser errors
|
|
283
|
+
Warnings/UnknownTag:
|
|
284
|
+
Description: "Detects unknown YARD tags."
|
|
285
|
+
Enabled: true
|
|
286
|
+
Severity: error
|
|
287
|
+
|
|
288
|
+
Warnings/UnknownDirective:
|
|
289
|
+
Description: "Detects unknown YARD directives."
|
|
290
|
+
Enabled: true
|
|
291
|
+
Severity: error
|
|
292
|
+
|
|
293
|
+
Warnings/InvalidTagFormat:
|
|
294
|
+
Description: "Detects malformed tag syntax."
|
|
295
|
+
Enabled: true
|
|
296
|
+
Severity: error
|
|
297
|
+
|
|
298
|
+
Warnings/InvalidDirectiveFormat:
|
|
299
|
+
Description: "Detects malformed directive syntax."
|
|
300
|
+
Enabled: true
|
|
301
|
+
Severity: error
|
|
302
|
+
|
|
303
|
+
Warnings/DuplicatedParameterName:
|
|
304
|
+
Description: "Detects duplicate @param tags."
|
|
305
|
+
Enabled: true
|
|
306
|
+
Severity: error
|
|
307
|
+
|
|
308
|
+
Warnings/UnknownParameterName:
|
|
309
|
+
Description: "Detects @param tags for non-existent parameters."
|
|
310
|
+
Enabled: true
|
|
311
|
+
Severity: error
|
|
312
|
+
|
|
313
|
+
# Semantic validators
|
|
314
|
+
Semantic/AbstractMethods:
|
|
315
|
+
Description: "Ensures @abstract methods do not have real implementations."
|
|
316
|
+
Enabled: true
|
|
317
|
+
Severity: error
|
data/AGENTS.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
You are working in a Ruby project that uses mutation testing.
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Achieve 100% mutation coverage. Verify with:
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
bundle exec mutant run
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
When iterating, prefer `--fail-fast` so you address one surviving
|
|
12
|
+
mutant at a time:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
bundle exec mutant run --fail-fast
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## When you find an alive mutation
|
|
19
|
+
|
|
20
|
+
Decide which bucket it falls into:
|
|
21
|
+
|
|
22
|
+
- **A) The code does too much** for what the tests ask for. The
|
|
23
|
+
surviving mutation reveals behavior that no test requires. The
|
|
24
|
+
fix is to simplify the implementation.
|
|
25
|
+
- **B) A test is missing.** The behavior is intentional but no test
|
|
26
|
+
observes it. The fix is to add a test.
|
|
27
|
+
|
|
28
|
+
Decide between A) and B) before changing anything. If unsure, ask
|
|
29
|
+
the user.
|
|
30
|
+
|
|
31
|
+
## Constraints
|
|
32
|
+
|
|
33
|
+
- Line coverage must stay at 100%. Verify with:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
SIMPLECOV=1 bundle exec rake test
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
- You may not skip mutants by configuring mutant to ignore them.
|
|
40
|
+
No `expressions:` filters, no `coverage_criteria:` tweaks.
|
|
41
|
+
- You may not use `send` or `__send__` to invoke private methods
|
|
42
|
+
in tests just to satisfy mutant.
|
|
43
|
+
- You may not stub or mock the system under test (`Age`).
|
|
44
|
+
|
|
45
|
+
## Done
|
|
46
|
+
|
|
47
|
+
You are done when both of these are green and don't return any offenses:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
SIMPLECOV=1 bundle exec rake test
|
|
51
|
+
bundle exec mutant run
|
|
52
|
+
bundle exec rake markdown:validate_real_world
|
|
53
|
+
yard-lint lib/
|
|
54
|
+
```
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
All notable changes to this project will be documented in this file.
|
|
3
|
+
|
|
4
|
+
This format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
5
|
+
|
|
6
|
+
## Unreleased
|
|
7
|
+
|
|
8
|
+
## 0.7.0
|
|
9
|
+
## Added
|
|
10
|
+
- Adding yard-lint and all method documentation
|
|
11
|
+
- Generating rbs signature based on yard tags
|
|
12
|
+
- Adding mutant testing into a project
|
|
13
|
+
|
|
14
|
+
## Changed
|
|
15
|
+
- Refactoring and simplification of teamplate, mostly driven by mutantion testing
|
|
16
|
+
- Improve documentation for entire project
|
|
17
|
+
|
data/README.md
CHANGED
|
@@ -33,7 +33,7 @@ It seems important to note, that yard claims to have support for RDoc. That supp
|
|
|
33
33
|
|
|
34
34
|
If you know how to improve that, please get in touch or submit a patch.
|
|
35
35
|
|
|
36
|
-
So in meantime, there is work going on a competing gem for RDoc and it's called [rdoc-
|
|
36
|
+
So in meantime, there is work going on a competing gem for RDoc and it's called [rdoc-markdown gem](https://github.com/skatkov/rdoc-markdown/).
|
|
37
37
|
|
|
38
38
|
## Note on index.csv file
|
|
39
39
|
This gem emits index of all markdown files in a index.csv file.
|
|
@@ -43,6 +43,42 @@ There are decent tools that offer search through structured plain-text files. Bu
|
|
|
43
43
|
In my personal use-case, I use SQLite. All other databases seem to have a good support for CSV imports.
|
|
44
44
|
|
|
45
45
|
## Testing
|
|
46
|
-
Unit tests
|
|
46
|
+
Unit tests verify renderer behavior, index links, and anchor consistency for both YARD-style and RDoc-style sources.
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
Run:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
bundle exec rake test
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Regenerate local sample docs:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
bundle exec rake examples:generate
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Validate generated markdown in sample docs:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
bundle exec rake markdown:validate_examples
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Regenerate the checked-in RBS types derived from YARD docs:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
bundle exec rake types:generate
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
There is also a real-world validation harness for repositories with substantial YARD documentation (`rspec-core`, `sidekiq`):
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
bundle exec rake markdown:validate_real_world
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
This task validates generated markdown against CommonMark + GFM rendering, and reports unresolved local links found in upstream source comments while still validating local anchor/link structure.
|
|
79
|
+
|
|
80
|
+
GitHub Actions CI now runs this task on every push/PR, so `sidekiq` and other real-world fixture gems are verified continuously.
|
|
81
|
+
|
|
82
|
+
CI also regenerates `sig/yard/markdown.rbs` with `sord` and fails if the checked-in RBS file is out of date.
|
|
83
|
+
|
|
84
|
+
For reproducible checks, the task clones pinned tags (`rspec-core` `v3.13.2`, `sidekiq` `v7.3.10`) into `tmp/real-world/repos` before generating output.
|
data/Rakefile
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "open3"
|
|
5
|
+
require "shellwords"
|
|
6
|
+
|
|
3
7
|
require "bundler/gem_tasks"
|
|
4
8
|
require "rake/testtask"
|
|
5
9
|
|
|
10
|
+
require_relative "test/support/markdown_validator"
|
|
11
|
+
|
|
6
12
|
Rake::TestTask.new(:test) do |t|
|
|
7
13
|
t.libs << "test"
|
|
8
14
|
t.libs << "lib"
|
|
@@ -11,6 +17,102 @@ end
|
|
|
11
17
|
|
|
12
18
|
task default: %i[test stree:write]
|
|
13
19
|
|
|
20
|
+
TYPES_OUTPUT_PATH = "sig/yard/markdown.rbs"
|
|
21
|
+
|
|
22
|
+
def shell_escape(path)
|
|
23
|
+
Shellwords.escape(path)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
COMMAND_WARNING_REGEX = /\bwarning:/i
|
|
27
|
+
COMMAND_ERROR_REGEX = /\b(?:error|exception|fatal|loaderror)\b/i
|
|
28
|
+
|
|
29
|
+
def analyze_command_output(text)
|
|
30
|
+
lines = text.each_line.map(&:strip).reject(&:empty?)
|
|
31
|
+
{
|
|
32
|
+
warnings: lines.grep(COMMAND_WARNING_REGEX),
|
|
33
|
+
errors: lines.grep(COMMAND_ERROR_REGEX)
|
|
34
|
+
}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def command_log_path(label)
|
|
38
|
+
safe_label = label.gsub(%r{[^a-zA-Z0-9_-]+}, "_")
|
|
39
|
+
File.join("tmp", "command-logs", "#{safe_label}.log")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def run_command_with_analysis(command, label:)
|
|
43
|
+
puts command
|
|
44
|
+
|
|
45
|
+
stdout, stderr, status = Open3.capture3(command)
|
|
46
|
+
combined_output = [stdout, stderr].reject(&:empty?).join("\n")
|
|
47
|
+
log_path = command_log_path(label)
|
|
48
|
+
|
|
49
|
+
FileUtils.mkdir_p(File.dirname(log_path))
|
|
50
|
+
File.write(log_path, combined_output)
|
|
51
|
+
|
|
52
|
+
puts combined_output unless combined_output.empty?
|
|
53
|
+
|
|
54
|
+
stdout_analysis = analyze_command_output(stdout)
|
|
55
|
+
stderr_analysis = analyze_command_output(stderr)
|
|
56
|
+
combined_analysis = {
|
|
57
|
+
warnings: stdout_analysis[:warnings] + stderr_analysis[:warnings],
|
|
58
|
+
errors: stdout_analysis[:errors] + stderr_analysis[:errors]
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
puts "Output analysis for #{label}: warnings=#{combined_analysis[:warnings].size}, errors=#{combined_analysis[:errors].size}"
|
|
62
|
+
|
|
63
|
+
return if status.success? && combined_analysis[:errors].empty?
|
|
64
|
+
|
|
65
|
+
details = ["#{label} failed output checks (log: #{log_path})"]
|
|
66
|
+
details << "exit status: #{status.exitstatus}" unless status.success?
|
|
67
|
+
details << "errors: #{combined_analysis[:errors].first(5).join(' | ')}" unless combined_analysis[:errors].empty?
|
|
68
|
+
raise details.join("\n")
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def generate_markdown_docs(source, output_dir)
|
|
72
|
+
FileUtils.rm_rf(output_dir)
|
|
73
|
+
FileUtils.mkdir_p(output_dir)
|
|
74
|
+
|
|
75
|
+
command = "yardoc --no-stats --quiet --format markdown --load ./lib/yard-markdown.rb --output-dir #{shell_escape(output_dir)} #{shell_escape(source)}"
|
|
76
|
+
run_command_with_analysis(command, label: "yardoc_#{output_dir}")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def checkout_repo(url, destination, ref: nil)
|
|
80
|
+
FileUtils.rm_rf(destination)
|
|
81
|
+
FileUtils.mkdir_p(File.dirname(destination))
|
|
82
|
+
|
|
83
|
+
command = "git clone --depth 1"
|
|
84
|
+
command += " --branch #{shell_escape(ref)}" if ref
|
|
85
|
+
command += " #{shell_escape(url)} #{shell_escape(destination)}"
|
|
86
|
+
run_command_with_analysis(command, label: "git_clone_#{destination}")
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def generate_types(output_path = TYPES_OUTPUT_PATH)
|
|
90
|
+
FileUtils.mkdir_p(File.dirname(output_path))
|
|
91
|
+
|
|
92
|
+
command = [
|
|
93
|
+
"sord gen",
|
|
94
|
+
"--rbs",
|
|
95
|
+
"--no-sord-comments",
|
|
96
|
+
"--replace-unresolved-with-untyped",
|
|
97
|
+
"--replace-errors-with-untyped",
|
|
98
|
+
shell_escape(output_path)
|
|
99
|
+
].join(" ")
|
|
100
|
+
|
|
101
|
+
run_command_with_analysis(command, label: "sord_generate")
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def ensure_clean_generated_file(path)
|
|
105
|
+
command = "git status --short -- #{shell_escape(path)}"
|
|
106
|
+
stdout, stderr, status = Open3.capture3(command)
|
|
107
|
+
combined_output = [stdout, stderr].reject(&:empty?).join("\n")
|
|
108
|
+
|
|
109
|
+
raise "Unable to verify generated types for #{path}" unless status.success?
|
|
110
|
+
return if combined_output.strip.empty?
|
|
111
|
+
|
|
112
|
+
puts combined_output
|
|
113
|
+
raise "#{path} is out of date. Run `bundle exec rake types:generate` and commit the updated file."
|
|
114
|
+
end
|
|
115
|
+
|
|
14
116
|
|
|
15
117
|
namespace :examples do
|
|
16
118
|
desc "Generate basic example documentation using yard-markdown plugin"
|
|
@@ -21,11 +123,74 @@ namespace :examples do
|
|
|
21
123
|
|
|
22
124
|
desc "Generate example documentation for code annotated with yard"
|
|
23
125
|
task :yard do
|
|
24
|
-
|
|
126
|
+
generate_markdown_docs("example_yard.rb", "example/yard")
|
|
25
127
|
end
|
|
26
128
|
|
|
27
129
|
desc "Generate example documentation for code annotated with rdoc"
|
|
28
130
|
task :rdoc do
|
|
29
|
-
|
|
131
|
+
generate_markdown_docs("example_rdoc.rb", "example/rdoc")
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
namespace :real_world do
|
|
136
|
+
REPOS_DIR = "tmp/real-world/repos"
|
|
137
|
+
RSPEC_REPO = "#{REPOS_DIR}/rspec-core"
|
|
138
|
+
SIDEKIQ_REPO = "#{REPOS_DIR}/sidekiq"
|
|
139
|
+
|
|
140
|
+
desc "Checkout rspec-core repository"
|
|
141
|
+
task :checkout_rspec do
|
|
142
|
+
checkout_repo("https://github.com/rspec/rspec-core.git", RSPEC_REPO, ref: "v3.13.2")
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
desc "Checkout sidekiq repository"
|
|
146
|
+
task :checkout_sidekiq do
|
|
147
|
+
checkout_repo("https://github.com/sidekiq/sidekiq.git", SIDEKIQ_REPO, ref: "v7.3.10")
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
desc "Generate markdown docs for rspec-core"
|
|
151
|
+
task rspec: :checkout_rspec do
|
|
152
|
+
generate_markdown_docs("#{RSPEC_REPO}/lib", "tmp/real-world/rspec-core")
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
desc "Generate markdown docs for sidekiq"
|
|
156
|
+
task sidekiq: :checkout_sidekiq do
|
|
157
|
+
generate_markdown_docs("#{SIDEKIQ_REPO}/lib", "tmp/real-world/sidekiq")
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
desc "Generate markdown docs for rspec-core and sidekiq"
|
|
161
|
+
task :generate do
|
|
162
|
+
Rake::Task["real_world:rspec"].invoke
|
|
163
|
+
Rake::Task["real_world:sidekiq"].invoke
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
namespace :markdown do
|
|
168
|
+
desc "Validate checked-in example markdown output"
|
|
169
|
+
task validate_examples: "examples:generate" do
|
|
170
|
+
["example/yard", "example/rdoc"].each do |dir|
|
|
171
|
+
file_count = MarkdownValidator.new(dir).validate!
|
|
172
|
+
puts "Validated #{file_count} markdown files in #{dir}"
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
desc "Generate and validate markdown output for rspec-core and sidekiq"
|
|
177
|
+
task validate_real_world: "real_world:generate" do
|
|
178
|
+
["tmp/real-world/rspec-core", "tmp/real-world/sidekiq"].each do |dir|
|
|
179
|
+
validator = MarkdownValidator.new(dir, strict_links: false)
|
|
180
|
+
file_count = validator.validate!
|
|
181
|
+
puts "Validated #{file_count} markdown files in #{dir} (unresolved local links: #{validator.unresolved_links})"
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
namespace :types do
|
|
187
|
+
desc "Generate checked-in RBS types from YARD documentation"
|
|
188
|
+
task :generate do
|
|
189
|
+
generate_types
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
desc "Verify checked-in RBS types are up to date"
|
|
193
|
+
task check: :generate do
|
|
194
|
+
ensure_clean_generated_file(TYPES_OUTPUT_PATH)
|
|
30
195
|
end
|
|
31
196
|
end
|
data/config/mutant.yml
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
usage: opensource
|
|
2
|
+
|
|
3
|
+
integration:
|
|
4
|
+
name: minitest
|
|
5
|
+
|
|
6
|
+
includes:
|
|
7
|
+
- lib
|
|
8
|
+
- test
|
|
9
|
+
|
|
10
|
+
requires:
|
|
11
|
+
- ./test/support/mutant_setup.rb
|
|
12
|
+
|
|
13
|
+
matcher:
|
|
14
|
+
subjects:
|
|
15
|
+
- YARD::Markdown::AnchorComponentHelper#
|
|
16
|
+
- YARD::Markdown::ArefHelper#
|
|
17
|
+
- YARD::Markdown::CollectionRenderingHelper#
|
|
18
|
+
- YARD::Markdown::DocumentationHelper#
|
|
19
|
+
- YARD::Markdown::HeadingHelper#
|
|
20
|
+
- YARD::Markdown::LinkNormalizationHelper#
|
|
21
|
+
- YARD::Markdown::MethodPresentationHelper#
|
|
22
|
+
- YARD::Markdown::ObjectListingHelper#
|
|
23
|
+
- YARD::Markdown::RelationshipSectionHelper#
|
|
24
|
+
- YARD::Markdown::SectionAssemblyHelper#
|
|
25
|
+
- YARD::Markdown::TagFormattingHelper#
|