yard-lint 1.5.1 → 1.6.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/CHANGELOG.md +51 -0
- data/README.md +207 -8
- data/bin/yard-lint +45 -11
- data/lib/yard/lint/executor/in_process_registry.rb +38 -12
- data/lib/yard/lint/results/base.rb +3 -0
- data/lib/yard/lint/runner.rb +11 -3
- data/lib/yard/lint/templates/default_config.yml +40 -0
- data/lib/yard/lint/templates/strict_config.yml +39 -0
- data/lib/yard/lint/todo_generator.rb +6 -4
- data/lib/yard/lint/validators/base.rb +125 -0
- data/lib/yard/lint/validators/documentation/line_length/config.rb +21 -0
- data/lib/yard/lint/validators/documentation/line_length/messages_builder.rb +26 -0
- data/lib/yard/lint/validators/documentation/line_length/parser.rb +65 -0
- data/lib/yard/lint/validators/documentation/line_length/result.rb +26 -0
- data/lib/yard/lint/validators/documentation/line_length/validator.rb +59 -0
- data/lib/yard/lint/validators/documentation/line_length.rb +43 -0
- data/lib/yard/lint/validators/documentation/missing_return/config.rb +2 -1
- data/lib/yard/lint/validators/documentation/missing_return/parser.rb +0 -1
- data/lib/yard/lint/validators/documentation/missing_return/validator.rb +1 -0
- data/lib/yard/lint/validators/documentation/orphaned_doc_comment/config.rb +20 -0
- data/lib/yard/lint/validators/documentation/orphaned_doc_comment/messages_builder.rb +23 -0
- data/lib/yard/lint/validators/documentation/orphaned_doc_comment/parser.rb +38 -0
- data/lib/yard/lint/validators/documentation/orphaned_doc_comment/result.rb +24 -0
- data/lib/yard/lint/validators/documentation/orphaned_doc_comment/validator.rb +121 -0
- data/lib/yard/lint/validators/documentation/orphaned_doc_comment.rb +53 -0
- data/lib/yard/lint/validators/documentation/text_substitution/config.rb +24 -0
- data/lib/yard/lint/validators/documentation/text_substitution/messages_builder.rb +33 -0
- data/lib/yard/lint/validators/documentation/text_substitution/parser.rb +57 -0
- data/lib/yard/lint/validators/documentation/text_substitution/result.rb +24 -0
- data/lib/yard/lint/validators/documentation/text_substitution/validator.rb +72 -0
- data/lib/yard/lint/validators/documentation/text_substitution.rb +55 -0
- data/lib/yard/lint/validators/documentation/undocumented_boolean_methods/config.rb +2 -1
- data/lib/yard/lint/validators/documentation/undocumented_boolean_methods/validator.rb +1 -0
- data/lib/yard/lint/validators/documentation/undocumented_method_arguments/config.rb +3 -1
- data/lib/yard/lint/validators/documentation/undocumented_method_arguments/validator.rb +3 -1
- data/lib/yard/lint/validators/documentation/undocumented_method_arguments.rb +1 -2
- data/lib/yard/lint/validators/documentation/undocumented_objects/config.rb +2 -1
- data/lib/yard/lint/validators/documentation/undocumented_objects/validator.rb +1 -0
- data/lib/yard/lint/validators/documentation/undocumented_options/config.rb +2 -1
- data/lib/yard/lint/validators/documentation/undocumented_options/validator.rb +1 -0
- data/lib/yard/lint/validators/documentation/undocumented_options.rb +1 -2
- data/lib/yard/lint/validators/tags/api_tags/result.rb +1 -0
- data/lib/yard/lint/validators/tags/api_tags/validator.rb +12 -0
- data/lib/yard/lint/validators/tags/collection_type/config.rb +1 -1
- data/lib/yard/lint/validators/tags/collection_type/validator.rb +1 -3
- data/lib/yard/lint/validators/tags/example_style/result.rb +1 -0
- data/lib/yard/lint/validators/tags/example_syntax/result.rb +1 -0
- data/lib/yard/lint/validators/tags/invalid_types/config.rb +1 -1
- data/lib/yard/lint/validators/tags/invalid_types/messages_builder.rb +14 -3
- data/lib/yard/lint/validators/tags/invalid_types/parser.rb +63 -3
- data/lib/yard/lint/validators/tags/invalid_types/validator.rb +31 -16
- data/lib/yard/lint/validators/tags/meaningless_tag/validator.rb +16 -1
- data/lib/yard/lint/validators/tags/missing_yield/config.rb +20 -0
- data/lib/yard/lint/validators/tags/missing_yield/messages_builder.rb +22 -0
- data/lib/yard/lint/validators/tags/missing_yield/parser.rb +39 -0
- data/lib/yard/lint/validators/tags/missing_yield/result.rb +24 -0
- data/lib/yard/lint/validators/tags/missing_yield/validator.rb +76 -0
- data/lib/yard/lint/validators/tags/missing_yield.rb +56 -0
- data/lib/yard/lint/validators/tags/non_ascii_type/config.rb +1 -1
- data/lib/yard/lint/validators/tags/non_ascii_type/validator.rb +1 -3
- data/lib/yard/lint/validators/tags/redundant_param_description/validator.rb +4 -2
- data/lib/yard/lint/validators/tags/redundant_param_description.rb +2 -1
- data/lib/yard/lint/validators/tags/type_syntax/config.rb +1 -1
- data/lib/yard/lint/validators/tags/type_syntax/validator.rb +1 -3
- data/lib/yard/lint/validators/tags/type_syntax.rb +1 -2
- data/lib/yard/lint/validators/warnings/duplicated_parameter_name/parser.rb +4 -4
- data/lib/yard/lint/validators/warnings/duplicated_parameter_name.rb +1 -2
- data/lib/yard/lint/validators/warnings/invalid_directive_format.rb +1 -2
- data/lib/yard/lint/version.rb +1 -1
- data/lib/yard/lint.rb +14 -4
- metadata +26 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ef1425a1be17cac04595b6558a742eb4036fc1cc66891e1d8f31eb46094c8914
|
|
4
|
+
data.tar.gz: d5ba0ef812eb0261718d7259d2da0b0f0b2fa37a1674893f6d7d3178be3bf551
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 23d60c91521b5afbadd0a43380682686f7b10aa68a968f5091da2de425f477f71ce3b8a6477ca5d0197d7138979dffc4a0aebe2582b3a64cd4092b18b6222c95
|
|
7
|
+
data.tar.gz: 966fe65d5e72ba1dbf225fe8802f2259dcdb436a66b2571d6caf7aff7d59491e1b337c7fe4db0e68354bceebb192c89d40ed6c1229b5e2bd2f75d2f5cbde456a
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
# YARD-Lint Changelog
|
|
2
2
|
|
|
3
|
+
## 1.6.0 (2026-06-11)
|
|
4
|
+
- **[Feature]** New `--format quickfix` output mode emits one offense per line in the standard `file:line: S: Validator: message` format. Vim users can set `makeprg=yard-lint\ --format\ quickfix\ --no-progress\ %` and navigate offenses with `:cnext`/`:cprev`; Emacs users can use it as their `compile-command` and navigate with `M-g n`/`M-g p`. Produces no output (and exits 0) when there are no offenses.
|
|
5
|
+
- **[Feature]** New opt-in validator `Documentation/LineLength` detects documentation comment lines that exceed a configurable maximum length (#176). Disabled by default (`Enabled: false`) to avoid breaking existing projects; enable with `Documentation/LineLength: Enabled: true` and tune with `MaxLength: 120` (default). Uses YARD's already-parsed docstring to determine which source lines belong to the comment block, avoiding fragile backwards-scanning. Each over-length line produces a separate offense at its exact file location.
|
|
6
|
+
- **[Feature]** `Yard::Lint.run` now accepts an optional `source:` keyword argument for linting in-memory source without reading from disk. `path:` is still required and governs config resolution, exclusion matching, and offense location reporting — only the source bytes come from the caller. The CLI gains a corresponding `--stdin` flag (`cat lib/foo.rb | yard-lint --stdin lib/foo.rb`). Enables LSP/editor integration tools (e.g. `solargraph-yard-lint`) to lint unsaved buffers without waiting for a save. (#173)
|
|
7
|
+
- **[Feature]** `Documentation/UndocumentedMethodArguments` now supports an `AllowedMethods` config option. Methods listed there are silently skipped for `@param` documentation checks. Three pattern forms are supported: exact name (`call`), arity notation (`initialize/1` — matches only that parameter count, with `*` and `&` params excluded from the count), and regex (`/^perform/`). Invalid regex patterns are silently ignored; the empty regex `//` is always rejected. Useful for idiomatic Ruby conventions like service objects where `call(args)` is self-documenting, or `respond_to_missing?` / `method_missing` whose arguments are rarely worth documenting.
|
|
8
|
+
- **[Feature]** All Documentation validators (`Documentation/UndocumentedObjects`, `Documentation/UndocumentedMethodArguments`, `Documentation/UndocumentedBooleanMethods`, `Documentation/UndocumentedOptions`, `Documentation/MissingReturn`) now support an `AllowedParentClasses` config option. When set, any class or method whose enclosing class directly inherits from one of the listed base classes is silently skipped by that validator. Useful for exempting exception hierarchies (`StandardError`), ORM model methods (`ActiveRecord::Base`, `ApplicationRecord`), or any framework base class whose subclasses don't need YARD coverage. Uses exact full-path matching (`"ActiveRecord::Base"`, not `"Base"`). `Object` and `BasicObject` are never matched to avoid accidentally exempting all classes.
|
|
9
|
+
- **[Feature]** New opt-in validator `Tags/MissingYield` detects methods that call `yield` in their body but do not document the block with a `@yield`, `@yieldparam`, or `@yieldreturn` tag. Callers need to know a method yields in order to pass a block; the validator checks raw docstring text rather than YARD's inferred tag list, so YARD's automatic `@yield` inference for bare `yield expr` statements does not suppress the offense. Method calls like `Fiber.yield` and `yielder.yield` are not flagged. Disabled by default - enable with `Tags/MissingYield: Enabled: true`.
|
|
10
|
+
- **[Feature]** New opt-in validator `Documentation/TextSubstitution` detects forbidden characters or strings in YARD documentation and suggests user-defined replacements. Ships with em-dash (—, U+2014) and en-dash (–, U+2013) → hyphen as built-in defaults to catch AI-generated punctuation that projects prefer as plain ASCII hyphens. Fully generic — configure any string-to-string rules via `Substitutions`. Content inside fenced code blocks is skipped. Disabled by default. (#182)
|
|
11
|
+
- **[Feature]** New validator `Documentation/OrphanedDocComment` detects YARD comment blocks with tags (`@param`, `@return`, etc.) that are not attached to any documentable Ruby construct and will be silently dropped by YARD. Triggered when a tagged comment is immediately followed by a non-documentable statement (variable assignment, `require`, `include`, etc.) or sits at end-of-file. Enabled by default. Complementary to `Documentation/BlankLineBeforeDefinition` which handles the blank-lines-before-def case.
|
|
12
|
+
- **[Enhancement]** Each offense now includes a `validator` field with the full config key (e.g. `"Documentation/MissingReturn"`, `"Tags/Order"`) identifying which validator produced it. The text formatter also now displays this path instead of the short offense name, making it easier to locate the right `.yard-lint.yml` setting to adjust.
|
|
13
|
+
- **[Fix]** `Tags/InvalidTypes` no longer reports false positives for YARD's semicolon shorthand in multi-pair fixed-shape Hash types (#171)
|
|
14
|
+
- Types like `Hash{:range => Hash; :severity => Integer; :source, :code, :message => String}` were incorrectly flagged because `;` was not included in the type-name splitter's delimiter set, leaving fragments such as `Hash;` and `Integer;` as tokens that appeared invalid
|
|
15
|
+
- Added `;` to the `extract_type_names` regex so each component is extracted cleanly; invalid types genuinely nested inside semicolon-delimited pairs are still caught
|
|
16
|
+
- **[Enhancement]** Add Ruby warning category opt-in to test helpers
|
|
17
|
+
- **[Fix]** Use `remove_method` instead of `define_singleton_method` to restore `warn` in `InProcessRegistry#capture_warnings`, eliminating a spurious method redefinition warning
|
|
18
|
+
|
|
19
|
+
## 1.5.2 (2026-06-02)
|
|
20
|
+
- **[Fix]** `Tags/InvalidTypes` no longer reports false positives for YARD pseudo-types `undefined`, `unspecified`, and `unknown` (#152)
|
|
21
|
+
- These lowercase pseudo-types are used in real-world YARD docs (e.g. Solargraph uses `Hash{String => undefined}` extensively) to signal that a type is intentionally unspecified
|
|
22
|
+
- They are now treated as valid types alongside the existing `nil`, `void`, `self`, `true`, `false` defaults
|
|
23
|
+
- **[Fix]** `Tags/InvalidTypes` no longer reports false positives for string literal hash keys (e.g. `Hash{"to" => String}`) (#152)
|
|
24
|
+
- String literal keys like `"email"` or `"name"` are valid YARD hash key notation and are now treated as valid alongside the existing symbol literal support (`:key`)
|
|
25
|
+
- **[Fix]** `Tags/InvalidTypes` no longer reports false positives for nested `Hash{K => V}` types (#151, #152)
|
|
26
|
+
- Complex hash types such as `Hash{String => Hash{Symbol => Array<String>}}` were occasionally flagged as invalid; the `extract_type_names` splitter already handled them correctly after the 1.5.2 sanitizer rewrite, and regression tests now lock that behaviour in
|
|
27
|
+
- Invalid types genuinely nested inside hash values (e.g. `Hash{String => bad_type}`) are still caught and surfaced correctly
|
|
28
|
+
- **[Enhancement]** `Tags/InvalidTypes` offense messages now name the invalid type(s) and the tag they appear in (#151)
|
|
29
|
+
- Previously reported a generic `"has at least one tag with an invalid type definition"` message with no further detail
|
|
30
|
+
- Now reports `"has invalid type(s): @param body: \`bad_type\`; @return: \`wrong_type\`"` - the exact offending type and the tag (including param name for `@param`) where it was found
|
|
31
|
+
- **[Fix]** Do not flag `@param` on `Struct.new` / `Data.define` constants in `Tags/MeaninglessTag` (#152)
|
|
32
|
+
- Solargraph uses `@param` annotations on these constants to type the synthesised accessors; flagging them was a false positive
|
|
33
|
+
- `@option` on these constants is still reported as meaningless
|
|
34
|
+
- **[Fix]** Fix `--auto-gen-config` crash (`NoMethodError`) when a YARD warning is emitted without file context (#150)
|
|
35
|
+
- A `@!macro [new]` body with an invalid tag format (e.g. `@return name [Type]`) that is also referenced inside the defining method's body causes YARD to expand the macro with `object=nil`, emitting `Invalid tag format` without a file path → `offense[:location] = nil` → `make_relative_path(nil)` → crash
|
|
36
|
+
- `TodoGenerator#make_relative_path` now returns `nil` for `nil` input; `run_linting` uses `filter_map` to skip nil locations when building exclusion lists
|
|
37
|
+
- `Runner#filter_result_offenses` now always drops nil-location offenses before exclusion-pattern filtering (they would otherwise appear as `:0` in output)
|
|
38
|
+
- Fix `Warnings/DuplicatedParameterName::Parser`: was inheriting from `OneLineBase` despite YARD emitting the warning across two lines (same format as `UnknownParameterName`), causing `offense[:location]` to always be `nil`; switched to `TwoLineBase` and corrected the location regex to match YARD's backtick-open/single-quote-close path format
|
|
39
|
+
- **[Fix]** Stop false positives for allowed defaults (`self`, `nil`, `true`, `false`, `void`) inside generic types in `Tags/InvalidTypes` validator
|
|
40
|
+
- Types like `Array<self>`, `Hash{Symbol => nil}`, `Array<true>` were incorrectly flagged as `InvalidTagType` because the sanitize logic concatenated type components (e.g., `Array<self>` became `Arrayself`, which is not in `ALLOWED_DEFAULTS`)
|
|
41
|
+
- Replaced the `tr`-based sanitizer with a proper type name splitter that checks each component individually
|
|
42
|
+
- **[Fix]** Validate types inside `@overload` blocks across all type validators (`Tags/TypeSyntax`, `Tags/InvalidTypes`, `Tags/CollectionType`, `Tags/NonAsciiType`)
|
|
43
|
+
- YARD stores `@overload` inner tags on the overload's own docstring, making them invisible to validators that only traverse `object.docstring.tags`
|
|
44
|
+
- Added `all_typed_tags` helper to `Validators::Base` that collects matching tags from both the docstring and any `@overload` blocks
|
|
45
|
+
- **[Fix]** Add `@raise` and `@yieldparam` to `ValidatedTags` in all type validators
|
|
46
|
+
- `@raise` tag types (e.g., `@raise [ArgumentError]`) were never validated for type syntax or correctness by any validator
|
|
47
|
+
- `@yieldparam` was missing from `Tags/InvalidTypes`, `Tags/TypeSyntax`, and `Tags/CollectionType` (only `Tags/NonAsciiType` included it)
|
|
48
|
+
- Both tags are now validated consistently across `Tags/InvalidTypes`, `Tags/TypeSyntax`, `Tags/CollectionType`, and `Tags/NonAsciiType`
|
|
49
|
+
- **[Fix]** Skip attribute methods in `Tags/ApiTags` validator (#128)
|
|
50
|
+
- Methods generated by `attr_*`, `@!attribute` directives, `Struct.new`, and `Data.define` are no longer flagged for missing `@api` tags
|
|
51
|
+
- YARD's `Data.define` and `Struct.new` handlers hard-replace the generated methods' docstrings, stripping any `@api` tag inherited from the enclosing class, and `@!attribute` directives written above a `Data.define` constant attach to the wrong namespace - leaving users with no way to attach per-method `@api` tags to those accessors
|
|
52
|
+
- Matches the approach taken for `UndocumentedMethodArguments` in #115
|
|
53
|
+
|
|
3
54
|
## 1.5.1 (2026-04-09)
|
|
4
55
|
- **[Fix]** Remove `mise.toml` and `proxy_types` from the repository and exclude non-production files (`.ruby-version`, `Rakefile`, `misc/`, `renovate.json`, `package.json`, `package-lock.json`, lock files) from RubyGems releases
|
|
5
56
|
|
data/README.md
CHANGED
|
@@ -19,18 +19,18 @@ Accurate documentation isn't just for human developers anymore. [Research shows]
|
|
|
19
19
|
|
|
20
20
|
YARD-Lint validates your YARD documentation for:
|
|
21
21
|
|
|
22
|
-
- **Documentation Completeness** - Undocumented classes, modules, methods, parameters, boolean return values, and missing `@return` tags
|
|
22
|
+
- **Documentation Completeness** - Undocumented classes, modules, methods, parameters, boolean return values, and missing `@return` tags; orphaned doc comments with YARD tags that YARD silently drops
|
|
23
23
|
- **Type Accuracy** - Invalid type definitions, malformed type syntax, non-ASCII characters in types, tuple types, and literal types (symbols, strings, numbers)
|
|
24
|
-
- **Tag Validation** - Incorrect tag ordering, meaningless tags, invalid tag positions, unknown tags with suggestions, forbidden tag patterns
|
|
24
|
+
- **Tag Validation** - Incorrect tag ordering, meaningless tags, invalid tag positions, unknown tags with suggestions, forbidden tag patterns, undocumented `yield` calls (opt-in)
|
|
25
25
|
- **Code Examples** - Syntax validation in `@example` tags, optional style validation with RuboCop/StandardRB
|
|
26
26
|
- **Semantic Correctness** - Abstract methods with implementations, redundant descriptions
|
|
27
|
-
- **Style & Formatting** - Empty comment lines, blank lines before definitions, informal notation patterns, tag group separators
|
|
27
|
+
- **Style & Formatting** - Empty comment lines, blank lines before definitions, informal notation patterns, tag group separators, configurable documentation line length (opt-in)
|
|
28
28
|
- **Smart Suggestions** - "Did you mean" suggestions for typos in parameter names, tags, and configuration settings
|
|
29
29
|
- **Configuration Safety** - Validates `.yard-lint.yml` for typos and invalid settings before processing
|
|
30
30
|
- **Performance** - In-process YARD execution with shared registry (~10x faster than shell-based execution)
|
|
31
31
|
- **Incremental Adoption** - `--auto-gen-config` generates a baseline todo file to adopt on legacy codebases without fixing everything first
|
|
32
32
|
|
|
33
|
-
**See the complete list:** [All Features](https://github.com/mensfeld/yard-lint/wiki/Features) | [
|
|
33
|
+
**See the complete list:** [All Features](https://github.com/mensfeld/yard-lint/wiki/Features) | [34 Validators](https://github.com/mensfeld/yard-lint/wiki/Validators)
|
|
34
34
|
|
|
35
35
|
## Installation
|
|
36
36
|
|
|
@@ -142,6 +142,63 @@ yard-lint lib/ --only Tags/Order,Documentation/UndocumentedObjects
|
|
|
142
142
|
|
|
143
143
|
**Learn more:** [Advanced Usage Guide](https://github.com/mensfeld/yard-lint/wiki/Advanced-Usage)
|
|
144
144
|
|
|
145
|
+
### Lint from stdin (LSP / Editor Integration)
|
|
146
|
+
|
|
147
|
+
Pass source bytes directly without reading from disk. The `path` argument is still required - it governs config resolution, exclusion matching, and offense location reporting.
|
|
148
|
+
|
|
149
|
+
**CLI:**
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
# Lint source piped through stdin - path is used for config/reporting only
|
|
153
|
+
cat lib/foo.rb | yard-lint --stdin lib/foo.rb
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Ruby API:**
|
|
157
|
+
|
|
158
|
+
```ruby
|
|
159
|
+
# Lint an in-memory buffer - file does not need to exist on disk
|
|
160
|
+
result = Yard::Lint.run(
|
|
161
|
+
path: 'lib/foo.rb', # used for config, exclusions, and offense locations
|
|
162
|
+
source: editor_buffer_content, # actual source bytes to lint
|
|
163
|
+
progress: false
|
|
164
|
+
)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
This is how [solargraph-yard-lint](https://github.com/lekemula/solargraph-yard-lint) surfaces yard-lint offenses on unsaved editor buffers - the file path provides context while the live buffer content is linted directly, matching the behaviour of RuboCop's `--stdin` flag.
|
|
168
|
+
|
|
169
|
+
### Quickfix Output (Vim / Emacs)
|
|
170
|
+
|
|
171
|
+
Use `--format quickfix` to get one offense per line in the standard `file:line: S: Validator: message` format that editors parse natively for their quickfix/error lists:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
yard-lint --format quickfix lib/
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Example output:
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
lib/foo.rb:42: E: Documentation/UndocumentedObjects: Class Foo is not documented
|
|
181
|
+
lib/foo.rb:57: W: Tags/InvalidTypes: has invalid type(s): @return: `Sting`
|
|
182
|
+
lib/bar.rb:12: C: Tags/Order: Tags are not in the correct order
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**Vim** — set `makeprg` and use `:make` to populate the quickfix list:
|
|
186
|
+
|
|
187
|
+
```vim
|
|
188
|
+
set makeprg=yard-lint\ --format\ quickfix\ --no-progress\ %
|
|
189
|
+
set errorformat=%f:%l:\ %t:\ %m
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Then `:make` lints the current file and `:cnext` / `:cprev` jump between offenses. Note: Vim only recognises `E` and `W` as named types for `:clist E`/`:clist W` filtering — `C` (convention) offenses are stored and navigable but appear without a named type in filtered views.
|
|
193
|
+
|
|
194
|
+
**Emacs** — set `compile-command`:
|
|
195
|
+
|
|
196
|
+
```elisp
|
|
197
|
+
(setq compile-command "yard-lint --format quickfix --no-progress lib/")
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Then `M-x compile` and `M-g n` / `M-g p` navigate between offenses.
|
|
201
|
+
|
|
145
202
|
## Configuration Basics
|
|
146
203
|
|
|
147
204
|
Create a `.yard-lint.yml` file in your project root:
|
|
@@ -173,10 +230,19 @@ Documentation/UndocumentedObjects:
|
|
|
173
230
|
ExcludedMethods:
|
|
174
231
|
- 'initialize/0'
|
|
175
232
|
- '/^_/'
|
|
233
|
+
# Skip classes inheriting from these base classes (exact full-path match)
|
|
234
|
+
AllowedParentClasses:
|
|
235
|
+
- StandardError
|
|
236
|
+
- ActiveRecord::Base
|
|
176
237
|
|
|
177
238
|
Documentation/UndocumentedMethodArguments:
|
|
178
239
|
Enabled: true
|
|
179
240
|
Severity: warning
|
|
241
|
+
# Skip @param checks for specific methods (exact name, name/arity, /regex/)
|
|
242
|
+
AllowedMethods:
|
|
243
|
+
- call # service objects: call(args) is self-documenting
|
|
244
|
+
- perform # background jobs
|
|
245
|
+
- initialize/1 # only this specific arity of initialize
|
|
180
246
|
|
|
181
247
|
Tags/Order:
|
|
182
248
|
Enabled: true
|
|
@@ -197,8 +263,11 @@ Tags/Order:
|
|
|
197
263
|
Tags/InvalidTypes:
|
|
198
264
|
Enabled: true
|
|
199
265
|
Severity: warning
|
|
266
|
+
# ExtraTypes: declare non-standard type names that should not be flagged.
|
|
267
|
+
# Useful for project aliases, LSP extensions (e.g. Solargraph's `generic`),
|
|
268
|
+
# or any informal type name your team uses in YARD docs.
|
|
200
269
|
ExtraTypes:
|
|
201
|
-
-
|
|
270
|
+
- generic # Solargraph generic type parameter (lsegal/yard#1683)
|
|
202
271
|
- MyNamespace::CustomType
|
|
203
272
|
|
|
204
273
|
# Opt-in: Require @return tags on all methods
|
|
@@ -212,6 +281,11 @@ Documentation/MissingReturn:
|
|
|
212
281
|
Tags/ExampleStyle:
|
|
213
282
|
Enabled: true
|
|
214
283
|
Severity: convention
|
|
284
|
+
|
|
285
|
+
# Opt-in: Enforce max line length in documentation comments
|
|
286
|
+
Documentation/LineLength:
|
|
287
|
+
Enabled: true
|
|
288
|
+
MaxLength: 100
|
|
215
289
|
```
|
|
216
290
|
|
|
217
291
|
**Key features:**
|
|
@@ -222,6 +296,113 @@ Tags/ExampleStyle:
|
|
|
222
296
|
|
|
223
297
|
**Learn more:** [Complete Configuration Guide](https://github.com/mensfeld/yard-lint/wiki/Configuration)
|
|
224
298
|
|
|
299
|
+
## Catching Orphaned Documentation Comments
|
|
300
|
+
|
|
301
|
+
YARD silently ignores comment blocks that contain YARD tags (`@param`, `@return`, etc.) when they are not immediately followed by a documentable construct (method, class, module, constant, attribute). This happens with local variable assignments, `require` calls, `include`/`extend` statements, bare `private`/`public` keywords, or comments at the end of a file - the documentation is simply lost with no warning.
|
|
302
|
+
|
|
303
|
+
The `Documentation/OrphanedDocComment` validator (enabled by default) catches this:
|
|
304
|
+
|
|
305
|
+
```ruby
|
|
306
|
+
# Bad - YARD drops this silently; local variable is not documentable
|
|
307
|
+
# @param name [String] the name
|
|
308
|
+
# @return [void]
|
|
309
|
+
local_var = "value"
|
|
310
|
+
|
|
311
|
+
# Bad - require is not documentable
|
|
312
|
+
# @param id [Integer] user id
|
|
313
|
+
# @return [User]
|
|
314
|
+
require 'some_gem'
|
|
315
|
+
|
|
316
|
+
# Bad - orphaned at end of file
|
|
317
|
+
# @param id [Integer] user id
|
|
318
|
+
# @return [User]
|
|
319
|
+
|
|
320
|
+
# Good - properly attached to a method
|
|
321
|
+
# @param name [String] the name
|
|
322
|
+
# @return [void]
|
|
323
|
+
def greet(name); end
|
|
324
|
+
|
|
325
|
+
# Good - constant assignments are documentable, not flagged
|
|
326
|
+
# @return [Integer] the answer
|
|
327
|
+
ANSWER = 42
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
This validator is complementary to `Documentation/BlankLineBeforeDefinition` (which handles the case where blank lines separate a doc comment from a `def` - YARD still attaches it despite the gap).
|
|
331
|
+
|
|
332
|
+
## Documenting yield (opt-in)
|
|
333
|
+
|
|
334
|
+
The `Tags/MissingYield` validator (opt-in, disabled by default) detects methods that call `yield` in their body but do not document the block with a `@yield`, `@yieldparam`, or `@yieldreturn` tag. Callers need to know a method yields in order to pass a block.
|
|
335
|
+
|
|
336
|
+
Enable it in `.yard-lint.yml`:
|
|
337
|
+
|
|
338
|
+
```yaml
|
|
339
|
+
Tags/MissingYield:
|
|
340
|
+
Enabled: true
|
|
341
|
+
Severity: warning
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
```ruby
|
|
345
|
+
# Bad - method yields but block is not documented
|
|
346
|
+
# @param items [Array] the items to process
|
|
347
|
+
def each(items)
|
|
348
|
+
items.each { |item| yield item }
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
# Good - block documented with @yield
|
|
352
|
+
# @param items [Array] the items to process
|
|
353
|
+
# @yield [item] each item in the collection
|
|
354
|
+
def each(items)
|
|
355
|
+
items.each { |item| yield item }
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
# Good - @yieldparam is also accepted
|
|
359
|
+
# @param items [Array] the items to process
|
|
360
|
+
# @yieldparam item [Object] each item
|
|
361
|
+
def each(items)
|
|
362
|
+
items.each { |item| yield item }
|
|
363
|
+
end
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Method calls like `Fiber.yield` and `yielder.yield` (Enumerator::Yielder) are not flagged - only the `yield` keyword triggers the check.
|
|
367
|
+
|
|
368
|
+
## Handling Non-Standard Types
|
|
369
|
+
|
|
370
|
+
By default `Tags/InvalidTypes` accepts all built-in Ruby classes, constants, and a set of YARD pseudo-types (`nil`, `true`, `false`, `self`, `void`, `undefined`, `unspecified`, `unknown`). If your project uses additional type names that are not real Ruby classes - project-specific aliases, LSP extensions, or informal conventions - you can declare them via `ExtraTypes` so yard-lint does not report them as `InvalidTagType` offenses.
|
|
371
|
+
|
|
372
|
+
### Project-Specific Type Aliases
|
|
373
|
+
|
|
374
|
+
```yaml
|
|
375
|
+
Tags/InvalidTypes:
|
|
376
|
+
ExtraTypes:
|
|
377
|
+
- Callable # informal "anything that responds to #call"
|
|
378
|
+
- Awaitable # async type alias used across the project
|
|
379
|
+
- Result # dry-monad-style Result type used in prose docs
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### LSP / Tool-Specific Extensions
|
|
383
|
+
|
|
384
|
+
[Solargraph](https://solargraph.org) supports a `generic` type-parameter notation (e.g. `Hash{Class<generic<T>> => Set<generic<T>>}`) that is [proposed for adoption](https://github.com/lsegal/yard/issues/1683) but not yet part of the YARD standard. Until it is, add it to `ExtraTypes` to prevent false positives:
|
|
385
|
+
|
|
386
|
+
```yaml
|
|
387
|
+
Tags/InvalidTypes:
|
|
388
|
+
ExtraTypes:
|
|
389
|
+
- generic
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Built-In Pseudo-Types (no configuration needed)
|
|
393
|
+
|
|
394
|
+
The following lowercase YARD pseudo-types are accepted out of the box and do **not** need to be listed in `ExtraTypes`:
|
|
395
|
+
|
|
396
|
+
| Type | Meaning |
|
|
397
|
+
|------|---------|
|
|
398
|
+
| `nil` | Explicitly nil |
|
|
399
|
+
| `true` / `false` | Boolean literals |
|
|
400
|
+
| `self` | Returns the receiver |
|
|
401
|
+
| `void` | No meaningful return value |
|
|
402
|
+
| `undefined` | Type is intentionally unspecified (used by Solargraph) |
|
|
403
|
+
| `unspecified` | Alias for undefined |
|
|
404
|
+
| `unknown` | Type is unknown |
|
|
405
|
+
|
|
225
406
|
## CI Integration
|
|
226
407
|
|
|
227
408
|
### GitHub Actions
|
|
@@ -253,7 +434,7 @@ jobs:
|
|
|
253
434
|
```bash
|
|
254
435
|
#!/bin/bash
|
|
255
436
|
# .git/hooks/pre-commit
|
|
256
|
-
bundle exec yard-lint lib/ --staged
|
|
437
|
+
bundle exec yard-lint lib/ --staged
|
|
257
438
|
```
|
|
258
439
|
|
|
259
440
|
### GitLab CI
|
|
@@ -279,10 +460,11 @@ Configuration:
|
|
|
279
460
|
-c, --config FILE Path to config file (default: .yard-lint.yml)
|
|
280
461
|
|
|
281
462
|
Output:
|
|
282
|
-
-f, --format FORMAT Output format (text, json)
|
|
463
|
+
-f, --format FORMAT Output format (text, json, quickfix)
|
|
283
464
|
-q, --quiet Quiet mode (only show summary)
|
|
284
465
|
--stats Show documentation coverage statistics
|
|
285
466
|
--[no-]progress Show progress indicator (default: auto-detect TTY)
|
|
467
|
+
--stdin Read source from stdin; PATH still required for config/reporting
|
|
286
468
|
|
|
287
469
|
Coverage:
|
|
288
470
|
--min-coverage N Minimum documentation coverage required (0-100)
|
|
@@ -311,6 +493,23 @@ Information:
|
|
|
311
493
|
|
|
312
494
|
**Learn more:** [Advanced Usage](https://github.com/mensfeld/yard-lint/wiki/Advanced-Usage) - CLI reference, JSON output, coverage
|
|
313
495
|
|
|
496
|
+
## Offense Structure
|
|
497
|
+
|
|
498
|
+
Every offense (in text, JSON, and quickfix output) includes a `validator` field with the full config key that produced it, making it easy to find the right `.yard-lint.yml` setting to adjust:
|
|
499
|
+
|
|
500
|
+
```json
|
|
501
|
+
{
|
|
502
|
+
"name": "OrphanedDocComment",
|
|
503
|
+
"validator": "Documentation/OrphanedDocComment",
|
|
504
|
+
"severity": "warning",
|
|
505
|
+
"message": "Documentation comment with @param, @return is orphaned - YARD will ignore it",
|
|
506
|
+
"location": "lib/my_class.rb",
|
|
507
|
+
"location_line": 42
|
|
508
|
+
}
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
The text formatter also shows the validator path (e.g., `[Documentation/OrphanedDocComment]`) instead of just the short offense name.
|
|
512
|
+
|
|
314
513
|
## Documentation
|
|
315
514
|
|
|
316
515
|
### Quick Links
|
|
@@ -318,7 +517,7 @@ Information:
|
|
|
318
517
|
- **[Wiki Home](https://github.com/mensfeld/yard-lint/wiki)** - Full documentation
|
|
319
518
|
- **[Installation](https://github.com/mensfeld/yard-lint/wiki/Installation)** - Installation guide
|
|
320
519
|
- **[Configuration](https://github.com/mensfeld/yard-lint/wiki/Configuration)** - Complete configuration reference
|
|
321
|
-
- **[Validators](https://github.com/mensfeld/yard-lint/wiki/Validators)** - All
|
|
520
|
+
- **[Validators](https://github.com/mensfeld/yard-lint/wiki/Validators)** - All 34 validators documented
|
|
322
521
|
- **[Features](https://github.com/mensfeld/yard-lint/wiki/Features)** - All features explained
|
|
323
522
|
|
|
324
523
|
### Workflows
|
data/bin/yard-lint
CHANGED
|
@@ -17,7 +17,7 @@ OptionParser.new do |opts|
|
|
|
17
17
|
config_file = file
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
opts.on('-f', '--format FORMAT', 'Output format (text, json)') do |format|
|
|
20
|
+
opts.on('-f', '--format FORMAT', 'Output format (text, json, quickfix)') do |format|
|
|
21
21
|
options[:format] = format
|
|
22
22
|
end
|
|
23
23
|
|
|
@@ -37,6 +37,10 @@ OptionParser.new do |opts|
|
|
|
37
37
|
options[:progress] = value
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
+
opts.on('--stdin', 'Read source from stdin; PATH argument is required for config/reporting') do
|
|
41
|
+
options[:stdin] = true
|
|
42
|
+
end
|
|
43
|
+
|
|
40
44
|
opts.separator ''
|
|
41
45
|
opts.separator 'Diff mode options (mutually exclusive):'
|
|
42
46
|
|
|
@@ -111,12 +115,14 @@ OptionParser.new do |opts|
|
|
|
111
115
|
puts ' yard-lint --staged # Lint only staged files'
|
|
112
116
|
puts ' yard-lint --changed # Lint only uncommitted files'
|
|
113
117
|
puts ' yard-lint --format json lib/ # Output in JSON format'
|
|
118
|
+
puts ' yard-lint --format quickfix lib/ # Output in quickfix format (Vim/Emacs)'
|
|
114
119
|
puts ' yard-lint --init # Generate default config'
|
|
115
120
|
puts ' yard-lint --init --strict # Generate strict config'
|
|
116
121
|
puts ' yard-lint --update # Update config with new validators'
|
|
117
122
|
puts ' yard-lint --auto-gen-config # Generate todo file for existing violations'
|
|
118
123
|
puts ' yard-lint --regenerate-todo # Regenerate todo file'
|
|
119
124
|
puts ' yard-lint --auto-gen-config --exclude-limit 10 # Custom grouping threshold'
|
|
125
|
+
puts ' cat lib/foo.rb | yard-lint --stdin lib/foo.rb # Lint source piped from stdin'
|
|
120
126
|
exit
|
|
121
127
|
end
|
|
122
128
|
end.parse!
|
|
@@ -199,6 +205,16 @@ end
|
|
|
199
205
|
# Get path argument (defaults to current directory)
|
|
200
206
|
path = ARGV[0] || '.'
|
|
201
207
|
|
|
208
|
+
# Read stdin source when --stdin flag is given
|
|
209
|
+
stdin_source = nil
|
|
210
|
+
if options[:stdin]
|
|
211
|
+
if path == '.' || File.directory?(path)
|
|
212
|
+
puts 'Error: --stdin requires an explicit file path argument (e.g. yard-lint --stdin lib/foo.rb)'
|
|
213
|
+
exit 1
|
|
214
|
+
end
|
|
215
|
+
stdin_source = $stdin.read
|
|
216
|
+
end
|
|
217
|
+
|
|
202
218
|
# Clear YARD registry to ensure fresh run on each CLI invocation
|
|
203
219
|
YARD::Registry.clear
|
|
204
220
|
|
|
@@ -235,14 +251,21 @@ if options[:only]
|
|
|
235
251
|
config.only_validators = options[:only]
|
|
236
252
|
end
|
|
237
253
|
|
|
254
|
+
# Suppress progress for quickfix to avoid contaminating machine-readable output
|
|
255
|
+
options[:progress] = false if options[:format] == 'quickfix' && options[:progress].nil?
|
|
256
|
+
|
|
238
257
|
# Run the linter
|
|
239
258
|
begin
|
|
240
259
|
result = Yard::Lint.run(
|
|
241
260
|
path: path,
|
|
242
261
|
config: config,
|
|
243
262
|
progress: options[:progress],
|
|
244
|
-
diff: diff_mode
|
|
263
|
+
diff: diff_mode,
|
|
264
|
+
source: stdin_source
|
|
245
265
|
)
|
|
266
|
+
rescue ArgumentError => e
|
|
267
|
+
puts "Error: #{e.message}"
|
|
268
|
+
exit 1
|
|
246
269
|
rescue Yard::Lint::Git::Error => e
|
|
247
270
|
puts "Git error: #{e.message}"
|
|
248
271
|
exit 1
|
|
@@ -251,6 +274,11 @@ rescue Yard::Lint::Errors::FileNotFoundError => e
|
|
|
251
274
|
exit 1
|
|
252
275
|
end
|
|
253
276
|
|
|
277
|
+
# Maps a severity string to its single-character quickfix/display code
|
|
278
|
+
severity_char = lambda do |s|
|
|
279
|
+
{ 'error' => 'E', 'warning' => 'W', 'convention' => 'C', 'never' => 'C' }.fetch(s.to_s, '?')
|
|
280
|
+
end
|
|
281
|
+
|
|
254
282
|
# Format and display results
|
|
255
283
|
case options[:format]
|
|
256
284
|
when 'json'
|
|
@@ -260,6 +288,19 @@ when 'json'
|
|
|
260
288
|
offenses: result.offenses
|
|
261
289
|
})
|
|
262
290
|
exit result.exit_code
|
|
291
|
+
when 'quickfix'
|
|
292
|
+
if config.min_coverage
|
|
293
|
+
coverage = result.documentation_coverage
|
|
294
|
+
if coverage && coverage[:coverage] < config.min_coverage
|
|
295
|
+
warn "Error: Documentation coverage #{coverage[:coverage].round(2)}% is below minimum #{config.min_coverage}%"
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
result.offenses.each do |offense|
|
|
299
|
+
char = severity_char.call(offense[:severity])
|
|
300
|
+
message = offense[:message].to_s.gsub(/\n/, ' ')
|
|
301
|
+
puts "#{offense[:location]}:#{offense[:location_line]}: #{char}: #{offense[:validator]}: #{message}"
|
|
302
|
+
end
|
|
303
|
+
exit result.exit_code
|
|
263
304
|
when 'text', nil
|
|
264
305
|
# Calculate coverage stats if requested or configured
|
|
265
306
|
coverage = result.documentation_coverage if options[:stats] || options[:min_coverage] || config.min_coverage
|
|
@@ -306,15 +347,8 @@ when 'text', nil
|
|
|
306
347
|
puts "Found #{result.count} offense(s):\n\n"
|
|
307
348
|
|
|
308
349
|
result.offenses.each do |offense|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
when 'warning' then 'W'
|
|
312
|
-
when 'convention' then 'C'
|
|
313
|
-
else '?'
|
|
314
|
-
end
|
|
315
|
-
|
|
316
|
-
puts "[#{severity_symbol}] #{offense[:location]}:#{offense[:location_line]}"
|
|
317
|
-
puts " #{offense[:name]}: #{offense[:message]}"
|
|
350
|
+
puts "[#{severity_char.call(offense[:severity])}] #{offense[:location]}:#{offense[:location_line]}"
|
|
351
|
+
puts " #{offense[:validator]}: #{offense[:message]}"
|
|
318
352
|
puts
|
|
319
353
|
end
|
|
320
354
|
end
|
|
@@ -21,8 +21,10 @@ module Yard
|
|
|
21
21
|
# Parse Ruby source files and populate the YARD registry.
|
|
22
22
|
# Captures any warnings emitted by YARD during parsing for later dispatch.
|
|
23
23
|
# @param files [Array<String>] absolute or relative paths to Ruby source files
|
|
24
|
+
# @param source [String, nil] in-memory source; when given, `files.first` is used
|
|
25
|
+
# as the virtual filename for registry/location reporting only
|
|
24
26
|
# @return [void]
|
|
25
|
-
def parse(files)
|
|
27
|
+
def parse(files, source: nil)
|
|
26
28
|
@mutex.synchronize do
|
|
27
29
|
return if @parsed
|
|
28
30
|
|
|
@@ -33,16 +35,28 @@ module Yard
|
|
|
33
35
|
original_level = YARD::Logger.instance.level
|
|
34
36
|
YARD::Logger.instance.level = 4 # Only show fatal errors
|
|
35
37
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
if source
|
|
39
|
+
virtual_path = files.first
|
|
40
|
+
# First pass: register directive/macro definitions from the in-memory source.
|
|
41
|
+
# We set parser.file manually so registered objects carry the virtual path.
|
|
42
|
+
parse_source_string(source, virtual_path)
|
|
43
|
+
# Clear checksums so the second pass is not skipped
|
|
44
|
+
YARD::Registry.checksums.clear
|
|
45
|
+
# Second pass: full parse with all directives available
|
|
46
|
+
@warnings = capture_warnings { parse_source_string(source, virtual_path) }
|
|
47
|
+
else
|
|
48
|
+
# First pass: parse all files to process directive definitions
|
|
49
|
+
YARD.parse(files)
|
|
50
|
+
|
|
51
|
+
# Clear checksums to force reparsing without clearing the registry.
|
|
52
|
+
# This allows macro definitions from the first pass to be available
|
|
53
|
+
# during the second pass, enabling proper directive expansion regardless of parse order.
|
|
54
|
+
YARD::Registry.checksums.clear
|
|
55
|
+
|
|
56
|
+
# Second pass: reparse files now that all directive definitions are available
|
|
57
|
+
@warnings = capture_warnings { YARD.parse(files) }
|
|
58
|
+
end
|
|
43
59
|
|
|
44
|
-
# Second pass: reparse files now that all directive definitions are available
|
|
45
|
-
@warnings = capture_warnings { YARD.parse(files) }
|
|
46
60
|
@parsed = true
|
|
47
61
|
|
|
48
62
|
YARD::Logger.instance.level = original_level
|
|
@@ -110,6 +124,18 @@ module Yard
|
|
|
110
124
|
|
|
111
125
|
private
|
|
112
126
|
|
|
127
|
+
# Parse Ruby source from a string and register objects under a virtual path.
|
|
128
|
+
# YARD::Parser::SourceParser#parse accepts a StringIO but keeps @file as '(stdin)'
|
|
129
|
+
# unless we set it explicitly before parsing.
|
|
130
|
+
# @param source [String] Ruby source code to parse
|
|
131
|
+
# @param virtual_path [String] filename to assign to registered objects
|
|
132
|
+
# @return [void]
|
|
133
|
+
def parse_source_string(source, virtual_path)
|
|
134
|
+
parser = YARD::Parser::SourceParser.new(:ruby)
|
|
135
|
+
parser.file = virtual_path
|
|
136
|
+
parser.parse(StringIO.new(source))
|
|
137
|
+
end
|
|
138
|
+
|
|
113
139
|
# Capture warnings during a block execution
|
|
114
140
|
# @yield Block to execute while capturing warnings
|
|
115
141
|
# @return [Array<String>] captured warnings
|
|
@@ -130,8 +156,8 @@ module Yard
|
|
|
130
156
|
|
|
131
157
|
captured
|
|
132
158
|
ensure
|
|
133
|
-
|
|
134
|
-
|
|
159
|
+
sc = YARD::Logger.instance.singleton_class
|
|
160
|
+
sc.remove_method(:warn) if sc.public_instance_methods(false).include?(:warn)
|
|
135
161
|
end
|
|
136
162
|
end
|
|
137
163
|
end
|
|
@@ -96,6 +96,8 @@ module Yard
|
|
|
96
96
|
# @return [String] validator name for config lookup
|
|
97
97
|
def validator_name
|
|
98
98
|
# Extract from class path: Validators::Tags::Order::Result => 'Tags/Order'
|
|
99
|
+
return '' unless self.class.name
|
|
100
|
+
|
|
99
101
|
parts = self.class.name.split('::')
|
|
100
102
|
validators_index = parts.index('Validators')
|
|
101
103
|
return '' unless validators_index
|
|
@@ -125,6 +127,7 @@ module Yard
|
|
|
125
127
|
severity: configured_severity,
|
|
126
128
|
type: self.class.offense_type,
|
|
127
129
|
name: computed_offense_name,
|
|
130
|
+
validator: validator_name,
|
|
128
131
|
message: build_message(offense_data),
|
|
129
132
|
location: offense_data[:location] || offense_data[:file],
|
|
130
133
|
location_line: offense_data[:line] || offense_data[:location_line] || 0
|
data/lib/yard/lint/runner.rb
CHANGED
|
@@ -15,9 +15,11 @@ module Yard
|
|
|
15
15
|
|
|
16
16
|
# @param selection [Array<String>] array with ruby files to check
|
|
17
17
|
# @param config [Yard::Lint::Config] configuration object
|
|
18
|
-
|
|
18
|
+
# @param source [String, nil] in-memory source content (overrides disk reads)
|
|
19
|
+
def initialize(selection, config = Config.new, source: nil)
|
|
19
20
|
@selection = Array(selection).flatten
|
|
20
21
|
@config = config
|
|
22
|
+
@source = source
|
|
21
23
|
@result_builder = ResultBuilder.new(config)
|
|
22
24
|
@progress_formatter = nil
|
|
23
25
|
end
|
|
@@ -45,7 +47,7 @@ module Yard
|
|
|
45
47
|
|
|
46
48
|
# Initialize in-process infrastructure
|
|
47
49
|
registry = Executor::InProcessRegistry.new
|
|
48
|
-
registry.parse(selection)
|
|
50
|
+
registry.parse(selection, source: @source)
|
|
49
51
|
|
|
50
52
|
query_executor = Executor::QueryExecutor.new(registry)
|
|
51
53
|
warning_dispatcher = Executor::WarningDispatcher.new
|
|
@@ -108,12 +110,18 @@ module Yard
|
|
|
108
110
|
end
|
|
109
111
|
|
|
110
112
|
# Filter result offenses based on per-validator exclusions
|
|
111
|
-
#
|
|
113
|
+
# Also always removes offenses with no file location (e.g. YARD warnings
|
|
114
|
+
# emitted without file context such as from macro expansion with nil object)
|
|
115
|
+
# since they carry no actionable information and would display as `:0`.
|
|
112
116
|
# @param validator_name [String] full validator name
|
|
113
117
|
# @param result [Results::Base] result object with offenses
|
|
114
118
|
# @return [Results::Base, nil] result with filtered offenses, or nil if no offenses remain
|
|
115
119
|
def filter_result_offenses(validator_name, result)
|
|
116
120
|
validator_excludes = config.validator_all_excludes(validator_name)
|
|
121
|
+
|
|
122
|
+
# Drop offenses with no file location regardless of exclusion config
|
|
123
|
+
result.offenses = result.offenses.reject { |o| (o[:location] || o[:file]).nil? }
|
|
124
|
+
return nil if result.offenses.empty?
|
|
117
125
|
return result if validator_excludes.empty?
|
|
118
126
|
|
|
119
127
|
working_dir = Dir.pwd
|