yard-lint 1.10.0 → 1.10.1
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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0c63ea819ad85e3c0878e26d37ea3b59bb61598804d3963425ff5882931b1a22
|
|
4
|
+
data.tar.gz: 5b613e3ba58f6773abd4b47b23c64e94d223ddecde10a743db5de1525b0f5ec2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 608923c037bde8d53573ae6f7d3487d1b156ba04ae94c143675c5c5f6c541ccb6266df7acf1748e7fd54e9e3bb92942a28fd2d62d560b92b6ee6e5373f60c822
|
|
7
|
+
data.tar.gz: 91863e353c9be138fa4bd93db36ce4cdf85209a85863dca25f6d7c1f3a794673018946d7e8160fedf801a4c80cf7377359f675462d87c7955aaf4b80fcffa68f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
## 1.10.1 (2026-07-24)
|
|
2
|
+
- **[Bugfix]** `Documentation/BlankLineBeforeDefinition` no longer reports a foreign comment block above a definition as documentation that was accidentally detached from it. When the object is documented (non-empty docstring) but that docstring did not come from the comment block sitting above this definition, the block is not a detached docstring - it is a file-level license/copyright banner, an encoding note, or an unrelated comment above a namespace reopening whose documentation lives in another file. The check compares the object's docstring against the block's text, so it recognizes any such banner without hardcoding its wording. Definitions whose documentation was genuinely lost (an undocumented object with a comment block detached above it) are still reported.
|
|
3
|
+
|
|
1
4
|
## 1.10.0 (2026-07-24)
|
|
2
5
|
- **[Feature]** Added `Documentation/DuplicateNamespaceComment` (enabled by default, severity `warning`) - detects namespaces (modules and classes) that carry a YARD documentation comment in more than one file. When a namespace is reopened across files and documented in several of them, YARD merges the reopenings into a single object and keeps only one docstring, silently discarding the rest (the last documented reopening wins, with no warning), so competing descriptions are lost. This is a common accident for shared namespaces (e.g. `Users` or `Users::Operations`) spread across many files; it does not affect a leaf object such as `Users::Operations::Create` that lives in a single file. Because YARD does not record which reopening carried a comment, the validator re-reads each definition site to detect the documented ones (ignoring blank-line-detached comments and directive/magic comments), and reports one offense per namespace documented in two or more files, listing every documented location and noting when the docstrings differ (meaning content is actually lost). Configurable via the standard `Enabled` and `Severity` keys.
|
|
3
6
|
|
|
@@ -21,9 +21,19 @@ module Yard
|
|
|
21
21
|
source_lines = File.readlines(object.file)
|
|
22
22
|
definition_line = object.line - 1
|
|
23
23
|
|
|
24
|
-
blank_count,
|
|
24
|
+
blank_count, doc_block_line = analyze_spacing(source_lines, definition_line)
|
|
25
25
|
|
|
26
|
-
return if blank_count.zero? ||
|
|
26
|
+
return if blank_count.zero? || doc_block_line.nil?
|
|
27
|
+
|
|
28
|
+
# Only a comment block that is genuinely THIS object's documentation can have
|
|
29
|
+
# been detached from it by the blank line. When the object is documented (its
|
|
30
|
+
# docstring is non-empty) but that docstring did not come from the comment block
|
|
31
|
+
# sitting above this definition, the block is a foreign comment - a file-level
|
|
32
|
+
# license/copyright banner, an encoding note, or an unrelated comment above a
|
|
33
|
+
# namespace reopening that is documented in another file - and the blank line is
|
|
34
|
+
# intentional. This is decided by comparing the object's docstring against the
|
|
35
|
+
# block's text, so it covers any such banner without hardcoding its wording.
|
|
36
|
+
return if foreign_comment_block?(object, source_lines, doc_block_line)
|
|
27
37
|
|
|
28
38
|
violation_type = blank_count >= 2 ? 'orphaned' : 'single'
|
|
29
39
|
|
|
@@ -38,10 +48,10 @@ module Yard
|
|
|
38
48
|
# Analyze spacing between documentation and definition
|
|
39
49
|
# @param source_lines [Array<String>] lines of source file
|
|
40
50
|
# @param definition_line [Integer] 0-indexed line of definition
|
|
41
|
-
# @return [Array<Integer,
|
|
51
|
+
# @return [Array<Integer, Integer, nil>] blank count and the 0-indexed line of the
|
|
52
|
+
# nearest documentation comment above the definition (nil when there is none)
|
|
42
53
|
def analyze_spacing(source_lines, definition_line)
|
|
43
54
|
blank_count = 0
|
|
44
|
-
has_doc_block = false
|
|
45
55
|
|
|
46
56
|
(definition_line - 1).downto(0) do |i|
|
|
47
57
|
line = source_lines[i].to_s.rstrip
|
|
@@ -56,15 +66,65 @@ module Yard
|
|
|
56
66
|
# spurious blank-line offenses for undocumented definitions.
|
|
57
67
|
next if non_documentation_comment?(stripped)
|
|
58
68
|
|
|
59
|
-
|
|
60
|
-
break
|
|
69
|
+
return [blank_count, i]
|
|
61
70
|
else
|
|
62
71
|
# Non-comment, non-blank line - no documentation above
|
|
63
72
|
break
|
|
64
73
|
end
|
|
65
74
|
end
|
|
66
75
|
|
|
67
|
-
[blank_count,
|
|
76
|
+
[blank_count, nil]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Whether the comment block above the definition is NOT the source of the object's
|
|
80
|
+
# documentation - a file banner or an unrelated comment rather than a docstring
|
|
81
|
+
# this definition lost to the blank line.
|
|
82
|
+
#
|
|
83
|
+
# An object with no docstring at all has genuinely orphaned documentation, so the
|
|
84
|
+
# block above is still reported. When the object IS documented, the block only
|
|
85
|
+
# counts as detached documentation if the docstring's text actually came from it;
|
|
86
|
+
# a license header or a comment above a reopening documented elsewhere carries
|
|
87
|
+
# different text and is left alone.
|
|
88
|
+
# @param object [YARD::CodeObjects::Base] the code object being checked
|
|
89
|
+
# @param source_lines [Array<String>] lines of source file
|
|
90
|
+
# @param doc_line [Integer] 0-indexed line of the nearest comment above the definition
|
|
91
|
+
# @return [Boolean]
|
|
92
|
+
def foreign_comment_block?(object, source_lines, doc_line)
|
|
93
|
+
docstring = object.docstring.to_s.strip
|
|
94
|
+
return false if docstring.empty?
|
|
95
|
+
|
|
96
|
+
block = comment_block_text(source_lines, doc_line)
|
|
97
|
+
first_line = normalize(docstring.lines.first.to_s)
|
|
98
|
+
return false if first_line.empty?
|
|
99
|
+
|
|
100
|
+
!normalize(block).include?(first_line)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Text of the contiguous comment block that contains `doc_line`, stripped of the
|
|
104
|
+
# comment markers and joined into a single string.
|
|
105
|
+
# @param source_lines [Array<String>] lines of source file
|
|
106
|
+
# @param doc_line [Integer] 0-indexed line within the comment block
|
|
107
|
+
# @return [String]
|
|
108
|
+
def comment_block_text(source_lines, doc_line)
|
|
109
|
+
first = doc_line
|
|
110
|
+
first -= 1 while first.positive? && comment_line?(source_lines[first - 1])
|
|
111
|
+
last = doc_line
|
|
112
|
+
last += 1 while last + 1 < source_lines.length && comment_line?(source_lines[last + 1])
|
|
113
|
+
|
|
114
|
+
source_lines[first..last].map { |line| line.sub(/\A\s*#+\s?/, '').strip }.join(' ')
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# @param line [String, nil] a source line
|
|
118
|
+
# @return [Boolean] whether the line is a comment line
|
|
119
|
+
def comment_line?(line)
|
|
120
|
+
line.to_s.strip.start_with?('#')
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Collapse whitespace so wrapped docstrings and their source comments compare equal.
|
|
124
|
+
# @param text [String]
|
|
125
|
+
# @return [String]
|
|
126
|
+
def normalize(text)
|
|
127
|
+
text.strip.gsub(/\s+/, ' ')
|
|
68
128
|
end
|
|
69
129
|
|
|
70
130
|
# Check if a comment line is a Ruby magic comment
|
data/lib/yard/lint/version.rb
CHANGED