rubocop-yardoc 0.1.0 → 0.2.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 +11 -0
- data/config/default.yml +6 -0
- data/lib/rubocop/cop/mixin/param_help.rb +81 -16
- data/lib/rubocop/cop/mixin/yard_help.rb +1 -1
- data/lib/rubocop/cop/yardoc/base.rb +22 -2
- data/lib/rubocop/cop/yardoc/column_params.rb +16 -62
- data/lib/rubocop/cop/yardoc/param_description_casing.rb +8 -21
- data/lib/rubocop/cop/yardoc/param_documentation.rb +3 -5
- data/lib/rubocop/cop/yardoc/separate_tags_blocks.rb +7 -15
- data/lib/rubocop/cop/yardoc/supported_tags.rb +2 -2
- data/lib/rubocop/cop/yardoc/types_format.rb +45 -0
- data/lib/rubocop/cop/yardoc/valid_types.rb +46 -0
- data/lib/rubocop/cop/yardoc_cops.rb +2 -0
- data/lib/rubocop/yardoc/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b85c7c55d0d3f08bf5634b5275d57a4f4951984bb49df452621ea8314a742ff9
|
|
4
|
+
data.tar.gz: 215d8421801cb366a8193d2e7b706977dbb3512ca6614e6a7f0a15b4501b784c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 017eb5da65048d4090b71e58fc737201c6f709f7f6cbb9fb8c95a0df547eb5a20ea47f5e0eddf1f6c02893ef2a85a82228b88a1082c1d7bb0a375a1f980974f2
|
|
7
|
+
data.tar.gz: 42df0fcef20c8a6f3a6c419343e5a00ab8cd51fb24bb68012e1da624af798bc0c15b76d18b01b381e2cff79dd652e854886094df534c9196c22d5c05d2623e86
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.2.0] - 2026-08-04
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- cop: `Yardoc/TypesFormat` - Ensure types are separated with a comma and a space
|
|
8
|
+
- cop: `Yardoc/ValidTypes` - Ensure the types are parseable by YARD
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
Reworked parts of the code
|
|
13
|
+
|
|
3
14
|
## [0.1.0] - 2026-08-04
|
|
4
15
|
|
|
5
16
|
- Initial release with following cops:
|
data/config/default.yml
CHANGED
|
@@ -4,11 +4,40 @@ module RuboCop
|
|
|
4
4
|
module Cop
|
|
5
5
|
# Helper methods to work with node parameters
|
|
6
6
|
module ParamHelp
|
|
7
|
+
# Matches the [<types>] part of a @param line
|
|
8
|
+
COMMENT_TYPES_REGEX = /^[^\[]+\[([^\[]*)\]/
|
|
9
|
+
|
|
10
|
+
# "@param" tag with data from Yard and parsed source code
|
|
11
|
+
#
|
|
12
|
+
# @param name [String] Parameter name
|
|
13
|
+
# @param tag_source_line [Parser::Source::Comment] Parsed first line of the tag
|
|
14
|
+
# @param types [Array<String>] Types of this parameter
|
|
15
|
+
# @param types_s [String] Original list of types, as declared in the tag line
|
|
16
|
+
# @param tag_range [Parser::Source::Range] Range for "@param" in source
|
|
17
|
+
# @param type_range [Parser::Source::Range] Range for the types position in source
|
|
18
|
+
# @param description_lines [Array<String>] All the lines composing the description
|
|
19
|
+
# @param type_pos [Integer] Position of the types declaration
|
|
20
|
+
# @param desc_pos [Integer] Position of the description declaration
|
|
21
|
+
ParameterTag = Struct.new(:name, :tag_source_line,
|
|
22
|
+
:types, :types_s,
|
|
23
|
+
:tag_range, :type_range,
|
|
24
|
+
:description_lines,
|
|
25
|
+
:type_pos, :desc_pos, keyword_init: true) do
|
|
26
|
+
# First line of description, usually the part on the "@param" line
|
|
27
|
+
#
|
|
28
|
+
# @return [String, nil]
|
|
29
|
+
def description_opening
|
|
30
|
+
description_lines.first
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
7
34
|
# Returns the location of "@<tag_name>" of the `comment_line` in the
|
|
8
35
|
# source buffer
|
|
9
36
|
#
|
|
10
37
|
# @param comment_line [Parser::Source::Comment] Comment line
|
|
11
38
|
# @param tag_name [String] Name of the tag
|
|
39
|
+
#
|
|
40
|
+
# @return [Parser::Source::Range]
|
|
12
41
|
def start_tag_position(comment_line, tag_name)
|
|
13
42
|
comment_range = comment_line.loc.expression
|
|
14
43
|
at_pos = comment_line.text.index('@')
|
|
@@ -18,27 +47,63 @@ module RuboCop
|
|
|
18
47
|
comment_range.begin_pos + at_pos + tag_name.length + 1
|
|
19
48
|
end
|
|
20
49
|
|
|
50
|
+
# Returns the location of the whole type definition of the `comment_line` in the
|
|
51
|
+
# source buffer
|
|
52
|
+
#
|
|
53
|
+
# @param comment_line [Parser::Source::Comment] Comment line
|
|
54
|
+
# @param types [String] Actual type string without the brackets
|
|
55
|
+
#
|
|
56
|
+
# @return [Parser::Source::Range, nil] Nil when no range can be found
|
|
57
|
+
def start_type_position(comment_line, types)
|
|
58
|
+
return nil if types.empty?
|
|
59
|
+
|
|
60
|
+
comment_range = comment_line.loc.expression
|
|
61
|
+
at_pos = comment_line.text.index('[')
|
|
62
|
+
|
|
63
|
+
Parser::Source::Range.new processed_source.buffer,
|
|
64
|
+
comment_range.begin_pos + at_pos,
|
|
65
|
+
comment_range.begin_pos + at_pos + 2 + types.length
|
|
66
|
+
end
|
|
67
|
+
|
|
21
68
|
# Extracts "@param" tags and their position in comment block
|
|
22
69
|
#
|
|
23
|
-
# @param node [RuboCop::AST::Node]
|
|
70
|
+
# @param node [RuboCop::AST::Node] The AST node
|
|
71
|
+
# @param tags [Array<:param, :return>] The AST node
|
|
24
72
|
#
|
|
25
|
-
# @return [Array<
|
|
26
|
-
def param_tags_and_positions(node) # rubocop:disable Metrics/MethodLength
|
|
27
|
-
|
|
28
|
-
|
|
73
|
+
# @return [Array<ParameterTag>]
|
|
74
|
+
def param_tags_and_positions(node, tags: [:param]) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
75
|
+
comments = node_comments(node)
|
|
76
|
+
tags.map!(&:to_s)
|
|
29
77
|
|
|
30
78
|
# Try to match extracted yard tags and source comments
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
79
|
+
yard_tags(node)
|
|
80
|
+
.select { |t| tags.include? t.tag_name }
|
|
81
|
+
.map do |yard_tag|
|
|
82
|
+
source_comment = case yard_tag.tag_name
|
|
83
|
+
when 'param'
|
|
84
|
+
comments.find { |comment| comment.text.match?(/^# @param\s+#{yard_tag.name}/) }
|
|
85
|
+
when 'return'
|
|
86
|
+
comments.find { |comment| comment.text.match?(/^# @return\s+/) }
|
|
87
|
+
else
|
|
88
|
+
next
|
|
89
|
+
end
|
|
90
|
+
description_lines = yard_tag.text ? yard_tag.text.split("\n") : []
|
|
91
|
+
|
|
92
|
+
types_s = source_comment.text.match(COMMENT_TYPES_REGEX)
|
|
93
|
+
types_s = types_s ? types_s[1] : ''
|
|
94
|
+
|
|
95
|
+
desc_pos = description_lines.any? ? source_comment.text.index(description_lines.first) : nil
|
|
96
|
+
|
|
97
|
+
ParameterTag.new name: yard_tag.name,
|
|
98
|
+
tag_source_line: source_comment,
|
|
99
|
+
types: yard_tag.types || [],
|
|
100
|
+
types_s: types_s,
|
|
101
|
+
tag_range: start_tag_position(source_comment, yard_tag.tag_name),
|
|
102
|
+
type_range: start_type_position(source_comment, types_s),
|
|
103
|
+
description_lines: description_lines,
|
|
104
|
+
type_pos: source_comment.text.index("[#{types_s}"),
|
|
105
|
+
desc_pos: desc_pos
|
|
106
|
+
end
|
|
42
107
|
end
|
|
43
108
|
end
|
|
44
109
|
end
|
|
@@ -12,7 +12,7 @@ module RuboCop
|
|
|
12
12
|
#
|
|
13
13
|
# @return [YARD::DocstringParser, nil] Parsed docstring or nil if none found
|
|
14
14
|
def yard_docstring(node)
|
|
15
|
-
comments =
|
|
15
|
+
comments = node_comments(node)
|
|
16
16
|
return nil if comments.nil? || comments.empty?
|
|
17
17
|
|
|
18
18
|
comment_text = comments.map { |c| c.text.sub(/^#\s?/, '') }.join("\n")
|
|
@@ -5,6 +5,18 @@ module RuboCop
|
|
|
5
5
|
module Yardoc
|
|
6
6
|
# Base class that provides shared YARD parsing utilities for all YARD cops.
|
|
7
7
|
class Base < RuboCop::Cop::Base
|
|
8
|
+
# Represents a comment entry (it may be a multi-line comment)
|
|
9
|
+
#
|
|
10
|
+
# @return [Struct] With :comment, :text, :tag, :line, :blank?
|
|
11
|
+
CommentEntry = Struct.new(:comment, :text, :tag, :line, :blank, keyword_init: true) do
|
|
12
|
+
# Whether the comment is empty
|
|
13
|
+
#
|
|
14
|
+
# @return [Boolean]
|
|
15
|
+
def blank?
|
|
16
|
+
blank
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
8
20
|
private
|
|
9
21
|
|
|
10
22
|
# Checks whether a node has any preceding documentation comments.
|
|
@@ -13,8 +25,7 @@ module RuboCop
|
|
|
13
25
|
#
|
|
14
26
|
# @return [Boolean]
|
|
15
27
|
def documented?(node)
|
|
16
|
-
|
|
17
|
-
comments && !comments.empty?
|
|
28
|
+
node_comments(node).any?
|
|
18
29
|
end
|
|
19
30
|
|
|
20
31
|
# Checks whether a name matches any entry in an ignore list from cop configuration.
|
|
@@ -38,6 +49,15 @@ module RuboCop
|
|
|
38
49
|
def ignore_list
|
|
39
50
|
Array(cop_config['Ignore'])
|
|
40
51
|
end
|
|
52
|
+
|
|
53
|
+
# Parsed node comments
|
|
54
|
+
#
|
|
55
|
+
# @param node [RuboCop::AST::Node] The AST node
|
|
56
|
+
#
|
|
57
|
+
# @return [Array<Parser::Source::Comment>]
|
|
58
|
+
def node_comments(node)
|
|
59
|
+
processed_source.ast_with_comments.fetch(node, [])
|
|
60
|
+
end
|
|
41
61
|
end
|
|
42
62
|
end
|
|
43
63
|
end
|
|
@@ -36,7 +36,7 @@ module RuboCop
|
|
|
36
36
|
#
|
|
37
37
|
# @param node [RuboCop::AST::Node] The AST node
|
|
38
38
|
def on_def(node)
|
|
39
|
-
param_lines =
|
|
39
|
+
param_lines = param_tags_and_positions(node)
|
|
40
40
|
return if param_lines.empty?
|
|
41
41
|
|
|
42
42
|
check_types_present(node, param_lines) unless config.for_cop('Yardoc/ParamDocumentation')['Enabled']
|
|
@@ -48,62 +48,35 @@ module RuboCop
|
|
|
48
48
|
|
|
49
49
|
private
|
|
50
50
|
|
|
51
|
-
# Parses raw comment lines into structured param line data.
|
|
52
|
-
#
|
|
53
|
-
# @param node [RuboCop::AST::Node] The AST node
|
|
54
|
-
#
|
|
55
|
-
# @return [Array<Hash>]
|
|
56
|
-
def extract_param_lines(node) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
57
|
-
param_tags_and_positions(node).filter_map do |param|
|
|
58
|
-
stripped = param[:source].sub(/^#\s*/, '')
|
|
59
|
-
|
|
60
|
-
match = stripped.match(/^@param\s+(\S+)(\s+\[([^\]]*)\])?(\s+(.*))?$/)
|
|
61
|
-
next unless match
|
|
62
|
-
|
|
63
|
-
# Use the match values as the Yardoc tag data may be formatted differently
|
|
64
|
-
{
|
|
65
|
-
range: param[:range],
|
|
66
|
-
line: param[:source],
|
|
67
|
-
comment: param[:comment],
|
|
68
|
-
yard_tag: param[:yard_tag],
|
|
69
|
-
name: match[1],
|
|
70
|
-
type: match[3],
|
|
71
|
-
text: match[5] || '',
|
|
72
|
-
type_col: param[:source].index('['),
|
|
73
|
-
desc_col: match[5] ? param[:source].index(match[5]) : nil,
|
|
74
|
-
}
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
51
|
# Checks that every param has a type
|
|
79
52
|
#
|
|
80
53
|
# @param node [RuboCop::AST::Node] The AST node
|
|
81
54
|
# @param param_lines [Array<Hash>] Hashes containing informations about the parameters
|
|
82
55
|
def check_types_present(node, param_lines)
|
|
83
56
|
param_lines.each do |pl|
|
|
84
|
-
next unless pl
|
|
57
|
+
next unless pl.types.empty?
|
|
85
58
|
|
|
86
|
-
add_offense(node, message: format(MSG_TYPE_MISSING, name: pl
|
|
59
|
+
add_offense(node, message: format(MSG_TYPE_MISSING, name: pl.name))
|
|
87
60
|
end
|
|
88
61
|
end
|
|
89
62
|
|
|
90
63
|
# Checks for the alignment of comments types and descriptions
|
|
91
64
|
#
|
|
92
65
|
# @param param_lines [Array<Hash>] Hashes containing informations about the parameters
|
|
93
|
-
def check_alignment(param_lines) # rubocop:disable Metrics/MethodLength
|
|
66
|
+
def check_alignment(param_lines) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
|
94
67
|
return if param_lines.count <= 1
|
|
95
68
|
|
|
96
69
|
longest_type_pos, longest_text_pos = param_tag_bits_positions(param_lines)
|
|
97
70
|
|
|
98
71
|
param_lines.each do |line|
|
|
99
72
|
expected = "# @param #{line[:name]}".ljust(longest_type_pos, ' ') +
|
|
100
|
-
"[#{line
|
|
101
|
-
expected = expected.ljust(longest_text_pos, ' ') + line
|
|
73
|
+
"[#{line.types_s}]"
|
|
74
|
+
expected = expected.ljust(longest_text_pos, ' ') + line.description_opening
|
|
102
75
|
|
|
103
|
-
next if line
|
|
76
|
+
next if line.tag_source_line.text == expected
|
|
104
77
|
|
|
105
|
-
add_offense(line
|
|
106
|
-
corrector.replace(line
|
|
78
|
+
add_offense(line.tag_range, message: MSG_ALIGNMENT) do |corrector|
|
|
79
|
+
corrector.replace(line.tag_source_line, expected)
|
|
107
80
|
end
|
|
108
81
|
end
|
|
109
82
|
end
|
|
@@ -113,11 +86,12 @@ module RuboCop
|
|
|
113
86
|
# @param param_lines [Array<Hash>] Hashes containing informations about the parameters
|
|
114
87
|
#
|
|
115
88
|
# @return [Array<Integer>] Types position, descriptions position
|
|
116
|
-
def param_tag_bits_positions(param_lines)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
89
|
+
def param_tag_bits_positions(param_lines)
|
|
90
|
+
# The + 10 is for "# @param " + the first char of description
|
|
91
|
+
longest_type_pos = param_lines.max_by { |l| l.name.length }.name.length + 10
|
|
92
|
+
longest_text_pos = param_lines.max_by { |l| l.types_s.length }
|
|
93
|
+
# Type may not have been defined; the + 3 is for type brackets and the next space
|
|
94
|
+
longest_text_pos = longest_text_pos ? longest_text_pos.types_s.length + longest_type_pos + 3 : 0
|
|
121
95
|
|
|
122
96
|
[longest_type_pos, longest_text_pos]
|
|
123
97
|
end
|
|
@@ -129,7 +103,7 @@ module RuboCop
|
|
|
129
103
|
def check_multiline_alignment(node, param_lines) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
|
130
104
|
longest_text_pos = param_tag_bits_positions(param_lines)[1]
|
|
131
105
|
|
|
132
|
-
comments =
|
|
106
|
+
comments = node_comments(node)
|
|
133
107
|
comments.each_with_index do |comment, index|
|
|
134
108
|
next unless comment.text.match?(/^# @param /)
|
|
135
109
|
|
|
@@ -148,26 +122,6 @@ module RuboCop
|
|
|
148
122
|
end
|
|
149
123
|
end
|
|
150
124
|
end
|
|
151
|
-
|
|
152
|
-
# Returns lines immediately following a param line that are
|
|
153
|
-
# plain comment continuations (not new tags).
|
|
154
|
-
#
|
|
155
|
-
# @param comments [Array<String>] All comment lines
|
|
156
|
-
# @param param_line [String] The @param line to find continuations for
|
|
157
|
-
#
|
|
158
|
-
# @return [Array<String>] Continuation lines
|
|
159
|
-
def following_continuation_lines(comments, param_line)
|
|
160
|
-
index = comments.index(param_line)
|
|
161
|
-
return [] if index.nil?
|
|
162
|
-
|
|
163
|
-
result = []
|
|
164
|
-
comments[(index + 1)..].each do |line|
|
|
165
|
-
break unless line.match?(/^#\s{3,}/)
|
|
166
|
-
|
|
167
|
-
result << line
|
|
168
|
-
end
|
|
169
|
-
result
|
|
170
|
-
end
|
|
171
125
|
end
|
|
172
126
|
end
|
|
173
127
|
end
|
|
@@ -21,18 +21,6 @@ module RuboCop
|
|
|
21
21
|
class ParamDescriptionCasing < Base
|
|
22
22
|
extend AutoCorrector
|
|
23
23
|
|
|
24
|
-
# Represents a comment entry (it may be a multi-line comment)
|
|
25
|
-
#
|
|
26
|
-
# @return [Struct] With :comment, :text, :tag, :line, :blank?
|
|
27
|
-
CommentEntry = Struct.new(:comment, :text, :tag, :line, :blank, keyword_init: true) do
|
|
28
|
-
# Whether the comment is empty
|
|
29
|
-
#
|
|
30
|
-
# @return [Boolean]
|
|
31
|
-
def blank?
|
|
32
|
-
blank
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
24
|
MSG = 'First letter of a @param or @return tag should be in uppercase'
|
|
37
25
|
|
|
38
26
|
# Matches a "param" tag line
|
|
@@ -46,16 +34,15 @@ module RuboCop
|
|
|
46
34
|
def on_def(node)
|
|
47
35
|
return unless documented? node
|
|
48
36
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
next unless match
|
|
37
|
+
node_comments(node).each do |line|
|
|
38
|
+
match = line.text.match(PARAM_REGEXP) || line.text.match(RETURN_REGEXP)
|
|
39
|
+
next unless match
|
|
53
40
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
41
|
+
range = offense_range(line, match[:definition])
|
|
42
|
+
add_offense(range) do |corrector|
|
|
43
|
+
corrector.replace(range, match[:desc][0].upcase)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
59
46
|
end
|
|
60
47
|
|
|
61
48
|
alias on_defs on_def
|
|
@@ -51,12 +51,10 @@ module RuboCop
|
|
|
51
51
|
next
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
add_offense(tag[:range], message: format(MSG_NO_TYPE, name: param_name))
|
|
56
|
-
end
|
|
54
|
+
add_offense(tag.tag_range, message: format(MSG_NO_TYPE, name: param_name)) if tag.types.empty?
|
|
57
55
|
|
|
58
|
-
if require_description? &&
|
|
59
|
-
add_offense(tag
|
|
56
|
+
if require_description? && tag.description_lines.empty?
|
|
57
|
+
add_offense(tag.tag_range, message: format(MSG_NO_DESCRIPTION, name: param_name))
|
|
60
58
|
end
|
|
61
59
|
end
|
|
62
60
|
|
|
@@ -27,18 +27,6 @@ module RuboCop
|
|
|
27
27
|
include RangeHelp
|
|
28
28
|
extend AutoCorrector
|
|
29
29
|
|
|
30
|
-
# Represents a comment entry (it may be a multi-line comment)
|
|
31
|
-
#
|
|
32
|
-
# @return [Struct] With :comment, :text, :tag, :line, :blank?
|
|
33
|
-
CommentEntry = Struct.new(:comment, :text, :tag, :line, :blank, keyword_init: true) do
|
|
34
|
-
# Whether the comment is empty
|
|
35
|
-
#
|
|
36
|
-
# @return [Boolean]
|
|
37
|
-
def blank?
|
|
38
|
-
blank
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
30
|
MSG = 'Add a blank comment line between different tag blocks.'
|
|
43
31
|
|
|
44
32
|
# Matches a comment line: captures the text after `#`.
|
|
@@ -54,7 +42,7 @@ module RuboCop
|
|
|
54
42
|
def on_def(node)
|
|
55
43
|
return unless documented? node
|
|
56
44
|
|
|
57
|
-
doc_comment_groups.each do |group|
|
|
45
|
+
doc_comment_groups(node).each do |group|
|
|
58
46
|
check_group(group)
|
|
59
47
|
end
|
|
60
48
|
end
|
|
@@ -65,11 +53,15 @@ module RuboCop
|
|
|
65
53
|
|
|
66
54
|
# Returns an array of "groups", where each group is an array of
|
|
67
55
|
# consecutive comment lines that form a single doc comment block.
|
|
68
|
-
|
|
56
|
+
#
|
|
57
|
+
# @param node [RuboCop::AST::Node] The AST node
|
|
58
|
+
#
|
|
59
|
+
# @return [Array<Parser::Source::Comment>]
|
|
60
|
+
def doc_comment_groups(node) # rubocop:disable Metrics/MethodLength
|
|
69
61
|
groups = []
|
|
70
62
|
current = []
|
|
71
63
|
|
|
72
|
-
|
|
64
|
+
node_comments(node).each do |comment|
|
|
73
65
|
# Only look at `#` style comments (not block =begin/=end)
|
|
74
66
|
next unless comment.text.start_with?('#')
|
|
75
67
|
|
|
@@ -90,9 +90,9 @@ module RuboCop
|
|
|
90
90
|
# @param node [RuboCop::AST::Node] The AST node to find docs for
|
|
91
91
|
# @param tag_name [String, nil] Optional tag to filter
|
|
92
92
|
def tags_and_positions(node, tag_name = nil)
|
|
93
|
-
|
|
93
|
+
comments = node_comments(node)
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
comments.filter_map do |comment|
|
|
96
96
|
text = comment.text
|
|
97
97
|
tag = text[/^# @((\w+)[\w\d]+)/, 1]
|
|
98
98
|
next if tag.nil? || (!tag_name.nil? && tag_name != tag)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Yardoc
|
|
6
|
+
# Ensures all types are separated by a space
|
|
7
|
+
#
|
|
8
|
+
# @example
|
|
9
|
+
# # bad
|
|
10
|
+
# # @param [String,nil]
|
|
11
|
+
# def greet(name); end
|
|
12
|
+
#
|
|
13
|
+
# # good
|
|
14
|
+
# # @param name [String, nil] the name to greet
|
|
15
|
+
# def greet(name); end
|
|
16
|
+
class TypesFormat < Base
|
|
17
|
+
include ParamHelp
|
|
18
|
+
include YardHelp
|
|
19
|
+
|
|
20
|
+
extend AutoCorrector
|
|
21
|
+
|
|
22
|
+
MSG = 'Types should be separated by a comma and a space'
|
|
23
|
+
|
|
24
|
+
# Executed for every method definition
|
|
25
|
+
#
|
|
26
|
+
# @param node [RuboCop::AST::Node] The AST node
|
|
27
|
+
def on_def(node)
|
|
28
|
+
return unless documented?(node)
|
|
29
|
+
|
|
30
|
+
param_tags_and_positions(node, tags: [:param, :return]).each do |param|
|
|
31
|
+
expected = param.types.join(', ')
|
|
32
|
+
|
|
33
|
+
next if param.types_s == expected
|
|
34
|
+
|
|
35
|
+
add_offense(param.tag_range, message: MSG) do |corrector|
|
|
36
|
+
corrector.replace(param.type_range, "[#{expected}]")
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
alias on_defs on_def
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Yardoc
|
|
6
|
+
# Ensures all types are separated by a space
|
|
7
|
+
#
|
|
8
|
+
# Types are parsed with YARD.
|
|
9
|
+
#
|
|
10
|
+
# @example
|
|
11
|
+
# # bad
|
|
12
|
+
# # @param name [.method, Array[String]] the name to greet
|
|
13
|
+
# def greet(name); end
|
|
14
|
+
#
|
|
15
|
+
# # good
|
|
16
|
+
# # @param [String, List(item, item2), Array<String>, Hash{String, Integer}, ClassName, #method, nil, true]
|
|
17
|
+
# def greet(name); end
|
|
18
|
+
class ValidTypes < Base
|
|
19
|
+
include ParamHelp
|
|
20
|
+
include YardHelp
|
|
21
|
+
|
|
22
|
+
extend AutoCorrector
|
|
23
|
+
|
|
24
|
+
MSG = 'Types should be parseable by YARD'
|
|
25
|
+
|
|
26
|
+
# Executed for every method definition
|
|
27
|
+
#
|
|
28
|
+
# @param node [RuboCop::AST::Node] The AST node
|
|
29
|
+
def on_def(node)
|
|
30
|
+
return unless documented?(node)
|
|
31
|
+
|
|
32
|
+
param_tags_and_positions(node, tags: [:param, :return]).each do |param|
|
|
33
|
+
param.types.each do |type|
|
|
34
|
+
YARD::Tags::TypesExplainer::Parser.parse type
|
|
35
|
+
rescue SyntaxError
|
|
36
|
+
add_offense(param.type_range || param.tag_range, message: MSG)
|
|
37
|
+
break
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
alias on_defs on_def
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -16,4 +16,6 @@ require_relative 'yardoc/param_documentation'
|
|
|
16
16
|
require_relative 'yardoc/separate_tags_blocks'
|
|
17
17
|
require_relative 'yardoc/supported_tags'
|
|
18
18
|
require_relative 'yardoc/tag_order'
|
|
19
|
+
require_relative 'yardoc/types_format'
|
|
20
|
+
require_relative 'yardoc/valid_types'
|
|
19
21
|
require_relative 'yardoc/yield_documentation'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubocop-yardoc
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Manuel Tancoigne
|
|
@@ -94,6 +94,8 @@ files:
|
|
|
94
94
|
- lib/rubocop/cop/yardoc/separate_tags_blocks.rb
|
|
95
95
|
- lib/rubocop/cop/yardoc/supported_tags.rb
|
|
96
96
|
- lib/rubocop/cop/yardoc/tag_order.rb
|
|
97
|
+
- lib/rubocop/cop/yardoc/types_format.rb
|
|
98
|
+
- lib/rubocop/cop/yardoc/valid_types.rb
|
|
97
99
|
- lib/rubocop/cop/yardoc/yield_documentation.rb
|
|
98
100
|
- lib/rubocop/cop/yardoc_cops.rb
|
|
99
101
|
- lib/rubocop/yardoc.rb
|