yard-lint 1.5.1 → 1.5.2
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 +35 -0
- data/README.md +42 -1
- data/lib/yard/lint/runner.rb +7 -1
- data/lib/yard/lint/todo_generator.rb +6 -4
- data/lib/yard/lint/validators/base.rb +19 -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/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/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/type_syntax/config.rb +1 -1
- data/lib/yard/lint/validators/tags/type_syntax/validator.rb +1 -3
- data/lib/yard/lint/validators/warnings/duplicated_parameter_name/parser.rb +4 -4
- data/lib/yard/lint/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1c96b4e1a2adb1c849b9716bbf413db8a9515cab506a350219351f56f140e19c
|
|
4
|
+
data.tar.gz: c5857861bf183876d1030d9b07b7ed295cb08f6951629d651a54a2aec4e4df54
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1c3b748cfcc894cd34715e4cda65a62b321fb1d96372a3b49934c2516dc8f74e60ab1cf3e632cca6491da37951a0b0713149f57545aae6d495b6e45530bc169b
|
|
7
|
+
data.tar.gz: 95132fedf072bb07466bc1d83e8a3b0bcc37df8e5ad85a811e20ddeaf8c30c354af89282de66df03cbcfc2fdae7721637772863828eba3a2b228e95993985faa
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# YARD-Lint Changelog
|
|
2
2
|
|
|
3
|
+
## 1.5.2 (2026-06-02)
|
|
4
|
+
- **[Fix]** `Tags/InvalidTypes` no longer reports false positives for YARD pseudo-types `undefined`, `unspecified`, and `unknown` (#152)
|
|
5
|
+
- 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
|
|
6
|
+
- They are now treated as valid types alongside the existing `nil`, `void`, `self`, `true`, `false` defaults
|
|
7
|
+
- **[Fix]** `Tags/InvalidTypes` no longer reports false positives for string literal hash keys (e.g. `Hash{"to" => String}`) (#152)
|
|
8
|
+
- 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`)
|
|
9
|
+
- **[Fix]** `Tags/InvalidTypes` no longer reports false positives for nested `Hash{K => V}` types (#151, #152)
|
|
10
|
+
- 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
|
|
11
|
+
- Invalid types genuinely nested inside hash values (e.g. `Hash{String => bad_type}`) are still caught and surfaced correctly
|
|
12
|
+
- **[Enhancement]** `Tags/InvalidTypes` offense messages now name the invalid type(s) and the tag they appear in (#151)
|
|
13
|
+
- Previously reported a generic `"has at least one tag with an invalid type definition"` message with no further detail
|
|
14
|
+
- 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
|
|
15
|
+
- **[Fix]** Do not flag `@param` on `Struct.new` / `Data.define` constants in `Tags/MeaninglessTag` (#152)
|
|
16
|
+
- Solargraph uses `@param` annotations on these constants to type the synthesised accessors; flagging them was a false positive
|
|
17
|
+
- `@option` on these constants is still reported as meaningless
|
|
18
|
+
- **[Fix]** Fix `--auto-gen-config` crash (`NoMethodError`) when a YARD warning is emitted without file context (#150)
|
|
19
|
+
- 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
|
|
20
|
+
- `TodoGenerator#make_relative_path` now returns `nil` for `nil` input; `run_linting` uses `filter_map` to skip nil locations when building exclusion lists
|
|
21
|
+
- `Runner#filter_result_offenses` now always drops nil-location offenses before exclusion-pattern filtering (they would otherwise appear as `:0` in output)
|
|
22
|
+
- 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
|
|
23
|
+
- **[Fix]** Stop false positives for allowed defaults (`self`, `nil`, `true`, `false`, `void`) inside generic types in `Tags/InvalidTypes` validator
|
|
24
|
+
- 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`)
|
|
25
|
+
- Replaced the `tr`-based sanitizer with a proper type name splitter that checks each component individually
|
|
26
|
+
- **[Fix]** Validate types inside `@overload` blocks across all type validators (`Tags/TypeSyntax`, `Tags/InvalidTypes`, `Tags/CollectionType`, `Tags/NonAsciiType`)
|
|
27
|
+
- YARD stores `@overload` inner tags on the overload's own docstring, making them invisible to validators that only traverse `object.docstring.tags`
|
|
28
|
+
- Added `all_typed_tags` helper to `Validators::Base` that collects matching tags from both the docstring and any `@overload` blocks
|
|
29
|
+
- **[Fix]** Add `@raise` and `@yieldparam` to `ValidatedTags` in all type validators
|
|
30
|
+
- `@raise` tag types (e.g., `@raise [ArgumentError]`) were never validated for type syntax or correctness by any validator
|
|
31
|
+
- `@yieldparam` was missing from `Tags/InvalidTypes`, `Tags/TypeSyntax`, and `Tags/CollectionType` (only `Tags/NonAsciiType` included it)
|
|
32
|
+
- Both tags are now validated consistently across `Tags/InvalidTypes`, `Tags/TypeSyntax`, `Tags/CollectionType`, and `Tags/NonAsciiType`
|
|
33
|
+
- **[Fix]** Skip attribute methods in `Tags/ApiTags` validator (#128)
|
|
34
|
+
- Methods generated by `attr_*`, `@!attribute` directives, `Struct.new`, and `Data.define` are no longer flagged for missing `@api` tags
|
|
35
|
+
- 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
|
|
36
|
+
- Matches the approach taken for `UndocumentedMethodArguments` in #115
|
|
37
|
+
|
|
3
38
|
## 1.5.1 (2026-04-09)
|
|
4
39
|
- **[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
40
|
|
data/README.md
CHANGED
|
@@ -197,8 +197,11 @@ Tags/Order:
|
|
|
197
197
|
Tags/InvalidTypes:
|
|
198
198
|
Enabled: true
|
|
199
199
|
Severity: warning
|
|
200
|
+
# ExtraTypes: declare non-standard type names that should not be flagged.
|
|
201
|
+
# Useful for project aliases, LSP extensions (e.g. Solargraph's `generic`),
|
|
202
|
+
# or any informal type name your team uses in YARD docs.
|
|
200
203
|
ExtraTypes:
|
|
201
|
-
-
|
|
204
|
+
- generic # Solargraph generic type parameter (lsegal/yard#1683)
|
|
202
205
|
- MyNamespace::CustomType
|
|
203
206
|
|
|
204
207
|
# Opt-in: Require @return tags on all methods
|
|
@@ -222,6 +225,44 @@ Tags/ExampleStyle:
|
|
|
222
225
|
|
|
223
226
|
**Learn more:** [Complete Configuration Guide](https://github.com/mensfeld/yard-lint/wiki/Configuration)
|
|
224
227
|
|
|
228
|
+
## Handling Non-Standard Types
|
|
229
|
+
|
|
230
|
+
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.
|
|
231
|
+
|
|
232
|
+
### Project-Specific Type Aliases
|
|
233
|
+
|
|
234
|
+
```yaml
|
|
235
|
+
Tags/InvalidTypes:
|
|
236
|
+
ExtraTypes:
|
|
237
|
+
- Callable # informal "anything that responds to #call"
|
|
238
|
+
- Awaitable # async type alias used across the project
|
|
239
|
+
- Result # dry-monad-style Result type used in prose docs
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### LSP / Tool-Specific Extensions
|
|
243
|
+
|
|
244
|
+
[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:
|
|
245
|
+
|
|
246
|
+
```yaml
|
|
247
|
+
Tags/InvalidTypes:
|
|
248
|
+
ExtraTypes:
|
|
249
|
+
- generic
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Built-In Pseudo-Types (no configuration needed)
|
|
253
|
+
|
|
254
|
+
The following lowercase YARD pseudo-types are accepted out of the box and do **not** need to be listed in `ExtraTypes`:
|
|
255
|
+
|
|
256
|
+
| Type | Meaning |
|
|
257
|
+
|------|---------|
|
|
258
|
+
| `nil` | Explicitly nil |
|
|
259
|
+
| `true` / `false` | Boolean literals |
|
|
260
|
+
| `self` | Returns the receiver |
|
|
261
|
+
| `void` | No meaningful return value |
|
|
262
|
+
| `undefined` | Type is intentionally unspecified (used by Solargraph) |
|
|
263
|
+
| `unspecified` | Alias for undefined |
|
|
264
|
+
| `unknown` | Type is unknown |
|
|
265
|
+
|
|
225
266
|
## CI Integration
|
|
226
267
|
|
|
227
268
|
### GitHub Actions
|
data/lib/yard/lint/runner.rb
CHANGED
|
@@ -108,12 +108,18 @@ module Yard
|
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
# Filter result offenses based on per-validator exclusions
|
|
111
|
-
#
|
|
111
|
+
# Also always removes offenses with no file location (e.g. YARD warnings
|
|
112
|
+
# emitted without file context such as from macro expansion with nil object)
|
|
113
|
+
# since they carry no actionable information and would display as `:0`.
|
|
112
114
|
# @param validator_name [String] full validator name
|
|
113
115
|
# @param result [Results::Base] result object with offenses
|
|
114
116
|
# @return [Results::Base, nil] result with filtered offenses, or nil if no offenses remain
|
|
115
117
|
def filter_result_offenses(validator_name, result)
|
|
116
118
|
validator_excludes = config.validator_all_excludes(validator_name)
|
|
119
|
+
|
|
120
|
+
# Drop offenses with no file location regardless of exclusion config
|
|
121
|
+
result.offenses = result.offenses.reject { |o| (o[:location] || o[:file]).nil? }
|
|
122
|
+
return nil if result.offenses.empty?
|
|
117
123
|
return result if validator_excludes.empty?
|
|
118
124
|
|
|
119
125
|
working_dir = Dir.pwd
|
|
@@ -95,8 +95,8 @@ module Yard
|
|
|
95
95
|
validator_result = result_builder.build(validator_name, raw_results)
|
|
96
96
|
next unless validator_result && validator_result.offenses.any?
|
|
97
97
|
|
|
98
|
-
# Extract file paths from offenses
|
|
99
|
-
file_paths = validator_result.offenses.
|
|
98
|
+
# Extract file paths from offenses, skipping those without a location
|
|
99
|
+
file_paths = validator_result.offenses.filter_map do |offense|
|
|
100
100
|
make_relative_path(offense[:location])
|
|
101
101
|
end.uniq.sort
|
|
102
102
|
|
|
@@ -128,9 +128,11 @@ module Yard
|
|
|
128
128
|
end
|
|
129
129
|
|
|
130
130
|
# Convert absolute path to relative path from current directory
|
|
131
|
-
# @param path [String] absolute or relative file path
|
|
132
|
-
# @return [String] relative path from current directory
|
|
131
|
+
# @param path [String, nil] absolute or relative file path
|
|
132
|
+
# @return [String, nil] relative path from current directory, or nil if path is nil
|
|
133
133
|
def make_relative_path(path)
|
|
134
|
+
return path if path.nil?
|
|
135
|
+
|
|
134
136
|
pwd = Dir.pwd
|
|
135
137
|
path.start_with?(pwd) ? path.sub("#{pwd}/", '') : path
|
|
136
138
|
end
|
|
@@ -78,6 +78,25 @@ module Yard
|
|
|
78
78
|
|
|
79
79
|
private
|
|
80
80
|
|
|
81
|
+
# Collect tags matching the given tag names from a docstring, including
|
|
82
|
+
# tags nested inside @overload blocks. YARD stores @overload inner tags
|
|
83
|
+
# on the overload's own docstring, so they are invisible to
|
|
84
|
+
# `docstring.tags` — this helper traverses them.
|
|
85
|
+
# @param docstring [YARD::Docstring] the docstring to search
|
|
86
|
+
# @param tag_names [Array<String>] tag names to collect (e.g., %w[param return])
|
|
87
|
+
# @return [Array<YARD::Tags::Tag>] matching tags from the docstring and any overloads
|
|
88
|
+
def all_typed_tags(docstring, tag_names)
|
|
89
|
+
tags = docstring.tags.select { |tag| tag_names.include?(tag.tag_name) }
|
|
90
|
+
|
|
91
|
+
docstring.tags(:overload).each do |overload|
|
|
92
|
+
overload.docstring.tags.each do |tag|
|
|
93
|
+
tags << tag if tag_names.include?(tag.tag_name)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
tags
|
|
98
|
+
end
|
|
99
|
+
|
|
81
100
|
# Retrieves configuration value with fallback to default
|
|
82
101
|
# Automatically determines the validator name from the class namespace
|
|
83
102
|
#
|
|
@@ -25,6 +25,18 @@ module Yard
|
|
|
25
25
|
collector.puts "invalid:#{api_value}"
|
|
26
26
|
end
|
|
27
27
|
elsif require_api_tags?
|
|
28
|
+
# Skip missing-tag reports for attribute methods (attr_reader/writer/accessor,
|
|
29
|
+
# @!attribute directives, Struct.new and Data.define generated readers/writers).
|
|
30
|
+
# These are auto-generated accessors where per-method @api tags either flow
|
|
31
|
+
# through the declaration's docstring automatically or cannot be attached at
|
|
32
|
+
# all — for example, YARD's Data.define handler creates getters with only a
|
|
33
|
+
# @return tag (hard-replacing their docstring and stripping any inherited @api
|
|
34
|
+
# from the enclosing class), and @!attribute directives written above a
|
|
35
|
+
# Data.define constant attach to the enclosing namespace, not the Data class
|
|
36
|
+
# itself. Note: attribute methods that *do* carry an explicit @api tag still
|
|
37
|
+
# hit the branch above and get their value validated. See issue #128.
|
|
38
|
+
return if object.type == :method && object.is_attribute?
|
|
39
|
+
|
|
28
40
|
# Only check public methods/classes if require_api_tags is enabled
|
|
29
41
|
visibility = object.visibility.to_s
|
|
30
42
|
if visibility == 'public' && !object.root?
|
|
@@ -11,7 +11,7 @@ module Yard
|
|
|
11
11
|
self.defaults = {
|
|
12
12
|
'Enabled' => true,
|
|
13
13
|
'Severity' => 'convention',
|
|
14
|
-
'ValidatedTags' => %w[param option return yieldreturn],
|
|
14
|
+
'ValidatedTags' => %w[param option return yieldreturn yieldparam raise],
|
|
15
15
|
'EnforcedStyle' => 'long' # 'long' (Hash{K => V}) or 'short' ({K => V})
|
|
16
16
|
}.freeze
|
|
17
17
|
end
|
|
@@ -19,9 +19,7 @@ module Yard
|
|
|
19
19
|
validated_tags = config_or_default('ValidatedTags')
|
|
20
20
|
style = enforced_style
|
|
21
21
|
|
|
22
|
-
object.docstring.
|
|
23
|
-
.select { |tag| validated_tags.include?(tag.tag_name) }
|
|
24
|
-
.each do |tag|
|
|
22
|
+
all_typed_tags(object.docstring, validated_tags).each do |tag|
|
|
25
23
|
next unless tag.types
|
|
26
24
|
|
|
27
25
|
tag.types.each do |type_str|
|
|
@@ -9,11 +9,22 @@ module Yard
|
|
|
9
9
|
class MessagesBuilder
|
|
10
10
|
class << self
|
|
11
11
|
# Build message for invalid tag types
|
|
12
|
-
# @param offense [Hash] offense data with :method_name
|
|
12
|
+
# @param offense [Hash] offense data with :method_name and :tag_violations keys
|
|
13
13
|
# @return [String] formatted message
|
|
14
14
|
def call(offense)
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
violations = offense[:tag_violations]
|
|
16
|
+
|
|
17
|
+
if violations&.any?
|
|
18
|
+
details = violations.map do |v|
|
|
19
|
+
label = v[:param] ? "#{v[:tag]} #{v[:param]}" : v[:tag]
|
|
20
|
+
types = v[:types].map { |t| "`#{t}`" }.join(', ')
|
|
21
|
+
"#{label}: #{types}"
|
|
22
|
+
end.join('; ')
|
|
23
|
+
|
|
24
|
+
"The `#{offense[:method_name]}` has invalid type(s): #{details}"
|
|
25
|
+
else
|
|
26
|
+
"The `#{offense[:method_name]}` has at least one tag with an invalid type definition."
|
|
27
|
+
end
|
|
17
28
|
end
|
|
18
29
|
end
|
|
19
30
|
end
|
|
@@ -5,9 +5,69 @@ module Yard
|
|
|
5
5
|
module Validators
|
|
6
6
|
module Tags
|
|
7
7
|
module InvalidTypes
|
|
8
|
-
# Parser for invalid
|
|
9
|
-
#
|
|
10
|
-
|
|
8
|
+
# Parser for invalid tag types output.
|
|
9
|
+
# The validator emits two lines per offense:
|
|
10
|
+
# /path/to/file.rb:10: ClassName#method_name
|
|
11
|
+
# @tagname param_name:BadType1,BadType2|@tagname2:BadType3
|
|
12
|
+
class Parser < Parsers::Base
|
|
13
|
+
# @return [Regexp] matches "file:line: ClassName#method"
|
|
14
|
+
LOCATION_REGEX = /^(.+):(\d+):\s+(.+)[#.](.+)$/
|
|
15
|
+
# @return [Regexp] matches the tag violations line (starts with @)
|
|
16
|
+
TAG_VIOLATIONS_REGEX = /^@/
|
|
17
|
+
|
|
18
|
+
# @param yard_output [String] raw validator output
|
|
19
|
+
# @return [Array<Hash>] parsed offenses
|
|
20
|
+
def call(yard_output)
|
|
21
|
+
lines = yard_output.split("\n").reject(&:empty?)
|
|
22
|
+
results = []
|
|
23
|
+
i = 0
|
|
24
|
+
|
|
25
|
+
while i < lines.size
|
|
26
|
+
match = lines[i].match(LOCATION_REGEX)
|
|
27
|
+
|
|
28
|
+
unless match
|
|
29
|
+
i += 1
|
|
30
|
+
next
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
offense = {
|
|
34
|
+
location: match[1],
|
|
35
|
+
line: match[2].to_i,
|
|
36
|
+
class_name: match[3],
|
|
37
|
+
method_name: match[4],
|
|
38
|
+
tag_violations: []
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
next_line = lines[i + 1]
|
|
42
|
+
if next_line&.match?(TAG_VIOLATIONS_REGEX)
|
|
43
|
+
offense[:tag_violations] = parse_tag_violations(next_line)
|
|
44
|
+
i += 2
|
|
45
|
+
else
|
|
46
|
+
i += 1
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
results << offense
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
results
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
# Parse "tagname param:Type1,Type2|tagname2:Type3" into structured data
|
|
58
|
+
# @param line [String] the violations line
|
|
59
|
+
# @return [Array<Hash>] each entry has :tag, :param (may be nil), :types
|
|
60
|
+
def parse_tag_violations(line)
|
|
61
|
+
line.split('|').map do |entry|
|
|
62
|
+
label, types_str = entry.split(':', 2)
|
|
63
|
+
parts = label.split(' ', 2)
|
|
64
|
+
{
|
|
65
|
+
tag: parts[0],
|
|
66
|
+
param: parts[1],
|
|
67
|
+
types: (types_str || '').split(',').reject(&:empty?)
|
|
68
|
+
}
|
|
69
|
+
end
|
|
70
|
+
end
|
|
11
71
|
end
|
|
12
72
|
end
|
|
13
73
|
end
|
|
@@ -19,6 +19,9 @@ module Yard
|
|
|
19
19
|
nil
|
|
20
20
|
self
|
|
21
21
|
void
|
|
22
|
+
undefined
|
|
23
|
+
unspecified
|
|
24
|
+
unknown
|
|
22
25
|
].freeze
|
|
23
26
|
|
|
24
27
|
private_constant :ALLOWED_DEFAULTS
|
|
@@ -33,35 +36,47 @@ module Yard
|
|
|
33
36
|
extra_types = config_or_default('ExtraTypes')
|
|
34
37
|
allowed_types = ALLOWED_DEFAULTS + extra_types
|
|
35
38
|
|
|
36
|
-
#
|
|
37
|
-
|
|
39
|
+
# Collect per-tag violations to surface in the offense message.
|
|
40
|
+
# Each entry is "tagname param_name:Type1,Type2" (param_name omitted when nil).
|
|
41
|
+
tag_violations = all_typed_tags(object.docstring, checked_tags).filter_map do |tag|
|
|
42
|
+
bad = (tag.types || [])
|
|
43
|
+
.compact
|
|
44
|
+
.flat_map { |type| extract_type_names(type) }
|
|
45
|
+
.uniq
|
|
46
|
+
.reject { |type| allowed_types.include?(type) }
|
|
47
|
+
.reject { |type| type_defined?(type) }
|
|
48
|
+
.reject { |type| type.include?('#') }
|
|
49
|
+
next if bad.empty?
|
|
38
50
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
.flat_map(&:types)
|
|
43
|
-
.compact
|
|
44
|
-
.uniq
|
|
45
|
-
.map(&sanitize)
|
|
46
|
-
.reject { |type| allowed_types.include?(type) }
|
|
47
|
-
.reject { |type| type_defined?(type) }
|
|
48
|
-
.reject { |type| type.include?('#') }
|
|
51
|
+
label = tag.name ? "@#{tag.tag_name} #{tag.name}" : "@#{tag.tag_name}"
|
|
52
|
+
"#{label}:#{bad.join(',')}"
|
|
53
|
+
end
|
|
49
54
|
|
|
50
|
-
return if
|
|
55
|
+
return if tag_violations.empty?
|
|
51
56
|
|
|
52
57
|
collector.puts "#{object.file}:#{object.line}: #{object.title}"
|
|
58
|
+
collector.puts tag_violations.join('|')
|
|
53
59
|
end
|
|
54
60
|
|
|
55
61
|
private
|
|
56
62
|
|
|
63
|
+
# Extract individual type names from a compound type string.
|
|
64
|
+
# Instead of stripping all syntax characters and concatenating (which
|
|
65
|
+
# turns "Array<self>" into "Arrayself"), this splits on syntax boundaries
|
|
66
|
+
# and returns each type name individually.
|
|
67
|
+
# @param type_str [String] the raw type string (e.g., "Array<self>", "Hash{Symbol => String}")
|
|
68
|
+
# @return [Array<String>] individual type names (e.g., ["Array", "self"], ["Hash", "Symbol", "String"])
|
|
69
|
+
def extract_type_names(type_str)
|
|
70
|
+
type_str.split(/[=><,{}\s()]+/).reject(&:empty?)
|
|
71
|
+
end
|
|
72
|
+
|
|
57
73
|
# Check if a type is defined in Ruby runtime or YARD registry
|
|
58
74
|
# In in-process mode, parsed classes are in YARD registry but not loaded into Ruby
|
|
59
75
|
# @param type [String] type name to check
|
|
60
76
|
# @return [Boolean] true if type is defined (or at least recognized as a valid type)
|
|
61
77
|
def type_defined?(type)
|
|
62
|
-
# Symbol types
|
|
63
|
-
|
|
64
|
-
return true if type.start_with?(':')
|
|
78
|
+
# Symbol and string literal types (:foo, "bar") are valid hash key notations
|
|
79
|
+
return true if type.start_with?(':', '"', "'")
|
|
65
80
|
|
|
66
81
|
# Check Ruby runtime first
|
|
67
82
|
# The shell query uses: !(Kernel.const_defined?(type) rescue nil).nil?
|
|
@@ -22,8 +22,13 @@ module Yard
|
|
|
22
22
|
|
|
23
23
|
return unless invalid_types.include?(object_type)
|
|
24
24
|
|
|
25
|
+
# @param is meaningful on Struct.new / Data.define constants because
|
|
26
|
+
# Solargraph uses those annotations to type the synthesized accessors.
|
|
27
|
+
effective_tags = struct_or_data_class?(object) ? tags_to_check - ['param'] : tags_to_check
|
|
28
|
+
return if effective_tags.empty?
|
|
29
|
+
|
|
25
30
|
object.docstring.tags.each do |tag|
|
|
26
|
-
next unless
|
|
31
|
+
next unless effective_tags.include?(tag.tag_name)
|
|
27
32
|
|
|
28
33
|
collector.puts "#{object.file}:#{object.line}: #{object.title}"
|
|
29
34
|
collector.puts "#{object_type}|#{tag.tag_name}"
|
|
@@ -42,6 +47,16 @@ module Yard
|
|
|
42
47
|
def invalid_object_types
|
|
43
48
|
config_or_default('InvalidObjectTypes')
|
|
44
49
|
end
|
|
50
|
+
|
|
51
|
+
# @param object [YARD::CodeObjects::Base] the code object to inspect
|
|
52
|
+
# @return [Boolean] true when the object is a class synthesised by Struct.new
|
|
53
|
+
# or Data.define, where @param documents the generated accessors
|
|
54
|
+
def struct_or_data_class?(object)
|
|
55
|
+
return false unless object.type == :class
|
|
56
|
+
|
|
57
|
+
sc_path = object.superclass&.path
|
|
58
|
+
sc_path == 'Struct' || sc_path == 'Data'
|
|
59
|
+
end
|
|
45
60
|
end
|
|
46
61
|
end
|
|
47
62
|
end
|
|
@@ -23,9 +23,7 @@ module Yard
|
|
|
23
23
|
validated_tags = config.validator_config('Tags/NonAsciiType', 'ValidatedTags') ||
|
|
24
24
|
%w[param option return yieldreturn yieldparam]
|
|
25
25
|
|
|
26
|
-
object.docstring.
|
|
27
|
-
.select { |tag| validated_tags.include?(tag.tag_name) }
|
|
28
|
-
.each do |tag|
|
|
26
|
+
all_typed_tags(object.docstring, validated_tags).each do |tag|
|
|
29
27
|
next unless tag.types
|
|
30
28
|
|
|
31
29
|
tag.types.each do |type_str|
|
|
@@ -31,9 +31,7 @@ module Yard
|
|
|
31
31
|
validated_tags = config.validator_config('Tags/TypeSyntax', 'ValidatedTags') ||
|
|
32
32
|
%w[param option return yieldreturn]
|
|
33
33
|
|
|
34
|
-
object.docstring.
|
|
35
|
-
.select { |tag| validated_tags.include?(tag.tag_name) }
|
|
36
|
-
.each do |tag|
|
|
34
|
+
all_typed_tags(object.docstring, validated_tags).each do |tag|
|
|
37
35
|
next unless tag.types
|
|
38
36
|
|
|
39
37
|
tag.types.each do |type_str|
|
|
@@ -6,13 +6,13 @@ module Yard
|
|
|
6
6
|
module Warnings
|
|
7
7
|
module DuplicatedParameterName
|
|
8
8
|
# Parser for DuplicatedParameterName warnings
|
|
9
|
-
class Parser < ::Yard::Lint::Parsers::
|
|
9
|
+
class Parser < ::Yard::Lint::Parsers::TwoLineBase
|
|
10
10
|
# Set of regexps for detecting warnings reported by YARD stats
|
|
11
11
|
self.regexps = {
|
|
12
12
|
general: /^\[warn\]: @param tag has duplicate parameter name/,
|
|
13
|
-
message: /\[warn\]: (.*)
|
|
14
|
-
location: /in file `(
|
|
15
|
-
line: /line (\d
|
|
13
|
+
message: /\[warn\]: (.*)$/,
|
|
14
|
+
location: /in file `(.*?)'\s*near/,
|
|
15
|
+
line: /near line (\d+)/
|
|
16
16
|
}.freeze
|
|
17
17
|
end
|
|
18
18
|
end
|
data/lib/yard/lint/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: yard-lint
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.5.
|
|
4
|
+
version: 1.5.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Maciej Mensfeld
|
|
@@ -278,7 +278,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
278
278
|
- !ruby/object:Gem::Version
|
|
279
279
|
version: '0'
|
|
280
280
|
requirements: []
|
|
281
|
-
rubygems_version: 4.0.
|
|
281
|
+
rubygems_version: 4.0.10
|
|
282
282
|
specification_version: 4
|
|
283
283
|
summary: YARD documentation linter and validator
|
|
284
284
|
test_files: []
|