rubocop-on-rbs 1.6.0 → 1.8.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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +19 -0
  3. data/lib/rubocop/cop/rbs/layout/comment_indentation.rb +4 -1
  4. data/lib/rubocop/cop/rbs/layout/empty_line_between_declarations.rb +175 -0
  5. data/lib/rubocop/cop/rbs/layout/empty_lines.rb +0 -1
  6. data/lib/rubocop/cop/rbs/layout/empty_lines_around_access_modifier.rb +1 -0
  7. data/lib/rubocop/cop/rbs/layout/empty_lines_around_class_body.rb +1 -2
  8. data/lib/rubocop/cop/rbs/layout/empty_lines_around_interface_body.rb +2 -2
  9. data/lib/rubocop/cop/rbs/layout/empty_lines_around_module_body.rb +1 -2
  10. data/lib/rubocop/cop/rbs/layout/empty_lines_around_overloads.rb +4 -1
  11. data/lib/rubocop/cop/rbs/layout/end_alignment.rb +4 -1
  12. data/lib/rubocop/cop/rbs/layout/extra_spacing.rb +4 -1
  13. data/lib/rubocop/cop/rbs/layout/indentation_width.rb +4 -1
  14. data/lib/rubocop/cop/rbs/layout/overload_indentation.rb +4 -1
  15. data/lib/rubocop/cop/rbs/layout/space_after_comma.rb +4 -1
  16. data/lib/rubocop/cop/rbs/layout/space_around_arrow.rb +4 -1
  17. data/lib/rubocop/cop/rbs/layout/space_around_braces.rb +4 -1
  18. data/lib/rubocop/cop/rbs/layout/space_around_operators.rb +2 -1
  19. data/lib/rubocop/cop/rbs/lint/duplicate_annotation.rb +57 -0
  20. data/lib/rubocop/cop/rbs/lint/duplicate_overload.rb +15 -5
  21. data/lib/rubocop/cop/rbs/lint/implicitly_returns_nil.rb +64 -0
  22. data/lib/rubocop/cop/rbs/lint/new_returns_void.rb +1 -1
  23. data/lib/rubocop/cop/rbs/lint/rest_keyword_hash.rb +47 -0
  24. data/lib/rubocop/cop/rbs/lint/syntax.rb +1 -0
  25. data/lib/rubocop/cop/rbs/lint/unused_overload_type_params.rb +2 -1
  26. data/lib/rubocop/cop/rbs/lint/unused_type_alias_type_params.rb +2 -1
  27. data/lib/rubocop/cop/rbs/lint/useless_access_modifier.rb +3 -1
  28. data/lib/rubocop/cop/rbs/lint/will_syntax_error.rb +2 -1
  29. data/lib/rubocop/cop/rbs/style/block_return_boolish.rb +2 -1
  30. data/lib/rubocop/cop/rbs/style/classic_type.rb +2 -1
  31. data/lib/rubocop/cop/rbs/style/duplicated_type.rb +4 -1
  32. data/lib/rubocop/cop/rbs/style/empty_argument.rb +4 -1
  33. data/lib/rubocop/cop/rbs/style/initialize_return_type.rb +8 -1
  34. data/lib/rubocop/cop/rbs/style/instance_with_instance.rb +1 -1
  35. data/lib/rubocop/cop/rbs/style/optional_nil.rb +4 -1
  36. data/lib/rubocop/cop/rbs/style/redundant_parentheses.rb +4 -1
  37. data/lib/rubocop/cop/rbs/style/true_false.rb +4 -1
  38. data/lib/rubocop/cop/rbs_cops.rb +4 -0
  39. data/lib/rubocop/rbs/cop_base.rb +6 -0
  40. data/lib/rubocop/rbs/version.rb +1 -1
  41. metadata +7 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 442a7571452e14e42efbd73d0f0313f983f631a983fd5c861f5c54d333538fd6
4
- data.tar.gz: 1803e6bdf3eb67a025a3d1286966bef98eb695cf16e7edf83a717d748f995eca
3
+ metadata.gz: 0f48492da2f7f96f52584db83f1ead670446908414b91ebf0a27a7d6ccb82c1e
4
+ data.tar.gz: c5374fcc49b860034ef0852e3a4d2a86c99867e96581033884116b707844c597
5
5
  SHA512:
6
- metadata.gz: '037319b5e7725a91470530891915c93227eddf4899ad8ad1a332f23bf23c3abedfc47f34618fbaa5c9672ad37d3e0badd32c7dec13f6319622dd653726f0d76d'
7
- data.tar.gz: f2009c6f0af208cb65f96d410461c435f5a5a919253f191af1ae58f96ab54137e95c1e56d433aaac474126cbe7740a8320fd475c5d5487277ec47c0f92b46c30
6
+ metadata.gz: fceeab927591e1507529a6b55d1b30f8b8bd7b5d700846777109a0e2b84c61380b5bee05d721d5eb5a08ffee4c184875d7956327c7feea6d469742c66f5affc7
7
+ data.tar.gz: 618f0de58a7bf00f68f0df67cca9d82da6723715af26eb1740211ab16bf53be66604782ec251fcbfdb313c933f30eb535e19f932b1d029fc462c8782189599a0
data/config/default.yml CHANGED
@@ -31,6 +31,13 @@ RBS/Layout/CommentIndentation:
31
31
  Description: 'Use 2 spaces for comment indentation'
32
32
  Enabled: true
33
33
 
34
+ RBS/Layout/EmptyLineBetweenDeclarations:
35
+ Description: 'Keep 1 blank line between declarations'
36
+ Enabled: true
37
+ Class: true
38
+ Module: true
39
+ Interface: true
40
+
34
41
  RBS/Layout/EmptyLinesAroundAccessModifier:
35
42
  Description: "Keeps track of empty lines around access modifiers."
36
43
  Enabled: true
@@ -113,10 +120,18 @@ RBS/Lint/AmbiguousOperatorPrecedence:
113
120
  Description: 'Check ambiguous operator precedence'
114
121
  Enabled: true
115
122
 
123
+ RBS/Lint/DuplicateAnnotation:
124
+ Description: 'Checks that there are no repeated annotations'
125
+ Enabled: true
126
+
116
127
  RBS/Lint/DuplicateOverload:
117
128
  Description: 'Checks that there are no repeated overload bodies'
118
129
  Enabled: true
119
130
 
131
+ RBS/Lint/ImplicitlyReturnsNil:
132
+ Description: 'Check implicitly returns nil'
133
+ Enabled: true
134
+
120
135
  RBS/Lint/LiteralIntersection:
121
136
  Description: 'Check literal intersection'
122
137
  Enabled: true
@@ -125,6 +140,10 @@ RBS/Lint/NewReturnsVoid:
125
140
  Description: 'sigleton `new` method should not returns `void` type'
126
141
  Enabled: true
127
142
 
143
+ RBS/Lint/RestKeywordHash:
144
+ Description: 'Check rest keyword with `Hash` type'
145
+ Enabled: true
146
+
128
147
  RBS/Lint/Syntax:
129
148
  Severity: fatal
130
149
  Description: 'Check RBS syntax'
@@ -4,7 +4,9 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Layout
7
- # @example default
7
+ # Checks the indentation of comments in RBS.
8
+ #
9
+ # @example
8
10
  # # bad
9
11
  # # comment here
10
12
  # def foo: () -> void
@@ -12,6 +14,7 @@ module RuboCop
12
14
  # # good
13
15
  # # comment here
14
16
  # def foo: () -> void
17
+ #
15
18
  class CommentIndentation < RuboCop::RBS::CopBase
16
19
  extend AutoCorrector
17
20
 
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RBS
6
+ module Layout
7
+ # Checks for empty lines between declarations.
8
+ #
9
+ # @example Class: true (default)
10
+ # # checks for empty lines between class declarations.
11
+ #
12
+ # # bad
13
+ # class A
14
+ # end
15
+ # class B
16
+ # end
17
+ #
18
+ # # good
19
+ # class A
20
+ # end
21
+ #
22
+ # class B
23
+ # end
24
+ #
25
+ # @example Module: true (default)
26
+ # # checks for empty lines between module declarations.
27
+ #
28
+ # # bad
29
+ # module A
30
+ # end
31
+ # module B
32
+ # end
33
+ #
34
+ # # good
35
+ # module A
36
+ # end
37
+ #
38
+ # module B
39
+ # end
40
+ #
41
+ # @example Interface: true (default)
42
+ # # checks for empty lines between interface declarations.
43
+ #
44
+ # # bad
45
+ # interface _A
46
+ # end
47
+ # interface _B
48
+ # end
49
+ #
50
+ # # good
51
+ # interface _A
52
+ # end
53
+ #
54
+ # interface _B
55
+ # end
56
+ #
57
+ class EmptyLineBetweenDeclarations < RuboCop::RBS::CopBase
58
+ extend AutoCorrector
59
+
60
+ MSG = 'Expected %<expected>s between %<type>s definitions; found %<actual>d.'
61
+
62
+ def on_rbs_new_investigation
63
+ [nil, *processed_rbs_source.decls, nil].each_cons(2) do |decls|
64
+ check_decls(decls)
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def check_decls(decls)
71
+ walk_pair(decls) do |before, after|
72
+ next unless candidate?(before) && candidate?(after)
73
+
74
+ check(before, after)
75
+ end
76
+ end
77
+
78
+ def walk_pair(decls, &block)
79
+ before, after = decls
80
+
81
+ case before
82
+ when ::RBS::AST::Declarations::Class,
83
+ ::RBS::AST::Declarations::Module,
84
+ ::RBS::AST::Declarations::Interface
85
+ case after
86
+ when ::RBS::AST::Declarations::Class,
87
+ ::RBS::AST::Declarations::Module,
88
+ ::RBS::AST::Declarations::Interface
89
+ block.call(before, after)
90
+ end
91
+ [nil, *before.members, nil].each_cons(2) do |members|
92
+ walk_pair(members, &block)
93
+ end
94
+ end
95
+ end
96
+
97
+ def check(before, after)
98
+ count = blank_lines_count_between(before, after)
99
+ return if count == 1
100
+ return if multiple_blank_lines_groups?(before, after)
101
+
102
+ after_start_line = processed_source.lines[after.location.start_line - 1]
103
+ range = range_between(after.location.start_pos, after.location.start_pos + after_start_line.length)
104
+ type = decl_type(after)
105
+ add_offense(range, message: format(MSG, expected: "1 empty line", type:, actual: count)) do |corrector|
106
+ if count.zero?
107
+ range_of_first = location_to_range(location_of_first(after))
108
+ corrector.insert_before(range_by_whole_lines(range_of_first), "\n")
109
+ else
110
+ range_to_remove = range_between(before.location.end_pos + 1, location_of_first(after).start_pos)
111
+ corrector.remove(range_to_remove)
112
+ end
113
+ end
114
+ end
115
+
116
+ def decl_type(decl)
117
+ case decl
118
+ when ::RBS::AST::Declarations::Class
119
+ 'class'
120
+ when ::RBS::AST::Declarations::Module
121
+ 'module'
122
+ when ::RBS::AST::Declarations::Interface
123
+ 'interface'
124
+ end
125
+ end
126
+
127
+ def multiple_blank_lines_groups?(first_def_decl, second_def_decl)
128
+ lines = lines_between_decl(first_def_decl, second_def_decl)
129
+ blank_start = lines.each_index.select { |i| lines[i].blank? }.max
130
+ non_blank_end = lines.each_index.reject { |i| lines[i].blank? }.min
131
+ return false if blank_start.nil? || non_blank_end.nil?
132
+
133
+ blank_start > non_blank_end
134
+ end
135
+
136
+ def lines_between_decl(first_def_decl, second_def_decl)
137
+ begin_line_num = first_def_decl.location.end_line
138
+ end_line_num = location_of_first(second_def_decl).start_line - 2
139
+ return [] if end_line_num.negative?
140
+
141
+ processed_source.lines[begin_line_num..end_line_num]
142
+ end
143
+
144
+ def blank_lines_count_between(before, after)
145
+ lines_between_decl(before, after).count(&:blank?)
146
+ end
147
+
148
+ def location_of_first(decl)
149
+ [
150
+ *decl.annotations.map(&:location),
151
+ decl.comment&.location,
152
+ decl.location
153
+ ].compact.min_by(&:start_pos)
154
+ end
155
+
156
+ def candidate?(decl)
157
+ class_candidate?(decl) || module_candidate?(decl) || interface_candidate?(decl)
158
+ end
159
+
160
+ def class_candidate?(decl)
161
+ cop_config['Class'] && decl.is_a?(::RBS::AST::Declarations::Class)
162
+ end
163
+
164
+ def module_candidate?(decl)
165
+ cop_config['Module'] && decl.is_a?(::RBS::AST::Declarations::Module)
166
+ end
167
+
168
+ def interface_candidate?(decl)
169
+ cop_config['Interface'] && decl.is_a?(::RBS::AST::Declarations::Interface)
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
@@ -7,7 +7,6 @@ module RuboCop
7
7
  # Checks for two or more consecutive blank lines.
8
8
  #
9
9
  # @example
10
- #
11
10
  # # bad - It has two empty lines.
12
11
  # def foo: () -> void
13
12
  # # one empty line
@@ -6,6 +6,7 @@ module RuboCop
6
6
  module Layout
7
7
  # Access modifiers should be surrounded by blank lines.
8
8
  #
9
+ # @example
9
10
  # # bad
10
11
  # class Foo
11
12
  # def bar: () -> void
@@ -7,9 +7,8 @@ module RuboCop
7
7
  # Checks if empty lines around the bodies of classes match
8
8
  # the configuration.
9
9
  #
10
- # @example default
10
+ # @example
11
11
  # # good
12
- #
13
12
  # class Foo
14
13
  # def bar: () -> void
15
14
  # end
@@ -7,12 +7,12 @@ module RuboCop
7
7
  # Checks if empty lines around the bodies of interfaces match
8
8
  # the configuration.
9
9
  #
10
- # @example default
10
+ # @example
11
11
  # # good
12
- #
13
12
  # interface _Foo
14
13
  # def bar: () -> void
15
14
  # end
15
+ #
16
16
  class EmptyLinesAroundInterfaceBody < RuboCop::RBS::CopBase
17
17
  include EmptyLinesAroundBody
18
18
  extend AutoCorrector
@@ -7,9 +7,8 @@ module RuboCop
7
7
  # Checks if empty lines around the bodies of modules match
8
8
  # the configuration.
9
9
  #
10
- # @example default
10
+ # @example
11
11
  # # good
12
- #
13
12
  # module Foo
14
13
  # def bar: () -> void
15
14
  # end
@@ -4,7 +4,9 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Layout
7
- # @example default
7
+ # Checks empty lines around overloads.
8
+ #
9
+ # @example
8
10
  # # bad
9
11
  # def foo: () -> void
10
12
  #
@@ -13,6 +15,7 @@ module RuboCop
13
15
  # # good
14
16
  # def foo: () -> void
15
17
  # | (Integer) -> Integer
18
+ #
16
19
  class EmptyLinesAroundOverloads < RuboCop::RBS::CopBase
17
20
  extend AutoCorrector
18
21
 
@@ -4,7 +4,9 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Layout
7
- # @example default
7
+ # Checks if `end` is aligned with the start of the class, module or interface.
8
+ #
9
+ # @example
8
10
  # # bad
9
11
  # class Foo
10
12
  # def foo: () -> void
@@ -14,6 +16,7 @@ module RuboCop
14
16
  # class Foo
15
17
  # def foo: () -> void
16
18
  # end
19
+ #
17
20
  class EndAlignment < RuboCop::RBS::CopBase
18
21
  extend AutoCorrector
19
22
 
@@ -4,12 +4,15 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Layout
7
- # @example default
7
+ # Checks for unnecessary spacing between tokens.
8
+ #
9
+ # @example
8
10
  # # bad
9
11
  # def foo: () -> void
10
12
  #
11
13
  # # good
12
14
  # def foo: () -> void
15
+ #
13
16
  class ExtraSpacing < RuboCop::RBS::CopBase
14
17
  extend AutoCorrector
15
18
 
@@ -4,7 +4,9 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Layout
7
- # @example default
7
+ # Checks if the indentation width.
8
+ #
9
+ # @example
8
10
  # # bad
9
11
  # class Foo
10
12
  # def foo: () -> void
@@ -14,6 +16,7 @@ module RuboCop
14
16
  # class Foo
15
17
  # def foo: () -> void
16
18
  # end
19
+ #
17
20
  class IndentationWidth < RuboCop::RBS::CopBase
18
21
  extend AutoCorrector
19
22
 
@@ -4,7 +4,9 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Layout
7
- # @example default
7
+ # Checks the indentation of overloads.
8
+ #
9
+ # @example
8
10
  # # bad
9
11
  # def foo: () -> String | () -> (Integer)
10
12
  #
@@ -19,6 +21,7 @@ module RuboCop
19
21
  # # good
20
22
  # def foo: () -> String
21
23
  # | () -> Integer
24
+ #
22
25
  class OverloadIndentation < RuboCop::RBS::CopBase
23
26
  extend AutoCorrector
24
27
 
@@ -4,12 +4,15 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Layout
7
- # @example default
7
+ # Checks for missing spaces after commas.
8
+ #
9
+ # @example
8
10
  # # bad
9
11
  # def foo: (Integer,String) -> void
10
12
  #
11
13
  # # good
12
14
  # def foo: (Integer, String) -> void
15
+ #
13
16
  class SpaceAfterComma < RuboCop::RBS::CopBase
14
17
  extend AutoCorrector
15
18
 
@@ -4,7 +4,9 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Layout
7
- # @example default
7
+ # Checks for missing spaces around the `->` operator.
8
+ #
9
+ # @example
8
10
  # # bad
9
11
  # def foo: ()->void
10
12
  #
@@ -16,6 +18,7 @@ module RuboCop
16
18
  #
17
19
  # # good
18
20
  # def bar: () { () -> void } -> void
21
+ #
19
22
  class SpaceAroundArrow < RuboCop::RBS::CopBase
20
23
  extend AutoCorrector
21
24
 
@@ -4,12 +4,15 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Layout
7
- # @example default
7
+ # Checks for missing spaces around braces in method definitions.
8
+ #
9
+ # @example
8
10
  # # bad
9
11
  # def bar: (){() -> void}-> void
10
12
  #
11
13
  # # good
12
14
  # def bar: () { () -> void } -> void
15
+ #
13
16
  class SpaceAroundBraces < RuboCop::RBS::CopBase
14
17
  extend AutoCorrector
15
18
 
@@ -4,12 +4,13 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Layout
7
- # @example default
7
+ # @example
8
8
  # # bad
9
9
  # Integer|String
10
10
  #
11
11
  # # good
12
12
  # Integer | String
13
+ #
13
14
  class SpaceAroundOperators < RuboCop::RBS::CopBase
14
15
  extend AutoCorrector
15
16
 
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RBS
6
+ module Lint
7
+ # Checks that there are no repeated annotations.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # def %a{foo} %a{foo} def foo: () -> void
12
+ #
13
+ # # bad
14
+ # def %a{foo} foo: %a{foo} () -> void
15
+ #
16
+ # # bad
17
+ # def foo: %a{foo} %a{foo} () -> void
18
+ #
19
+ # # not bad
20
+ # def foo: %a{foo} () -> void
21
+ # | %a{foo} (Integer) -> void
22
+ #
23
+ class DuplicateAnnotation < RuboCop::RBS::CopBase
24
+ MSG = 'Duplicate annotation detected.'
25
+
26
+ def on_rbs_def(decl)
27
+ decl.annotations.each_with_index do |annotation, idx|
28
+ next_annotations = decl.annotations[(idx + 1)..] or next
29
+ check_annotations(annotation, next_annotations)
30
+
31
+ decl.overloads.each do |overload|
32
+ check_annotations(annotation, overload.annotations)
33
+ end
34
+ end
35
+
36
+ decl.overloads.each do |overload|
37
+ overload.annotations.each_with_index do |overload_annotation, idx|
38
+ next_annotations = overload.annotations[(idx + 1)..] or next
39
+ check_annotations(overload_annotation, next_annotations)
40
+ end
41
+ end
42
+ end
43
+
44
+ def check_annotations(left_annotation, right_annotations)
45
+ right_annotations.each do |right_annotation|
46
+ next unless left_annotation == right_annotation
47
+ next unless right_annotation.location
48
+
49
+ range = location_to_range(right_annotation.location)
50
+ add_offense(range)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -4,15 +4,16 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Lint
7
- # Checks that there are no repeated overload bodies
7
+ # Checks that there are no repeated overload bodies.
8
+ # This cop ignores the difference of return type.
8
9
  #
9
- # @example default
10
+ # @example
10
11
  # # bad
11
12
  # def foo: () -> void
12
- # | () -> void
13
+ # | () -> top
13
14
  #
14
15
  class DuplicateOverload < RuboCop::RBS::CopBase
15
- MSG = 'Duplicate overload body detected.'
16
+ MSG = 'Duplicate overload arguments detected.'
16
17
 
17
18
  def on_rbs_def(decl)
18
19
  overloads = decl.overloads
@@ -21,13 +22,22 @@ module RuboCop
21
22
 
22
23
  next_overloads = overloads[(idx + 1)..-1]
23
24
  next_overloads.each do |next_overload|
24
- next unless overload.method_type == next_overload.method_type
25
+ a = method_type_with_untyped_return_type(overload.method_type)
26
+ b = method_type_with_untyped_return_type(next_overload.method_type)
27
+ next unless a == b
25
28
 
26
29
  range = location_to_range(next_overload.method_type.location)
27
30
  add_offense(range)
28
31
  end
29
32
  end
30
33
  end
34
+
35
+ private
36
+
37
+ def method_type_with_untyped_return_type(method_type)
38
+ type = method_type.type.with_return_type(::RBS::Types::Bases::Any.new(location: nil))
39
+ method_type.update(type:)
40
+ end
31
41
  end
32
42
  end
33
43
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RBS
6
+ module Lint
7
+ # This cop checks for conflicts between `implicitly-returns-nil` annotations and return types.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # %a{implicitly-returns-nil}
12
+ # def foo: () -> Integer?
13
+ #
14
+ # # good
15
+ # %a{implicitly-returns-nil}
16
+ # def foo: () -> Integer
17
+ #
18
+ # # good
19
+ # def foo: () -> Integer?
20
+ #
21
+ class ImplicitlyReturnsNil < RuboCop::RBS::CopBase
22
+ extend AutoCorrector
23
+
24
+ MSG = "There is a conflict between `%<annotation>s` and return type `%<return_type>s`."
25
+
26
+ def on_rbs_def(decl)
27
+ decl.overloads.each do |overload|
28
+ annotation = find_implicitly_returns_nil(decl) || find_implicitly_returns_nil(overload)
29
+ next unless annotation
30
+ next unless overload_returns_nil?(overload)
31
+
32
+ return_type = overload.method_type.type.return_type.to_s
33
+ range = location_to_range(annotation.location)
34
+ message = format(MSG, annotation: annotation.location.source, return_type:)
35
+ add_offense(range, message:)
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def find_implicitly_returns_nil(decl)
42
+ decl.annotations.find { |a| a.string == 'implicitly-returns-nil' }
43
+ end
44
+
45
+ def overload_returns_nil?(overload)
46
+ returns_nil?(overload.method_type.type.return_type)
47
+ end
48
+
49
+ def returns_nil?(type)
50
+ case type
51
+ when ::RBS::Types::Bases::Nil,
52
+ ::RBS::Types::Optional
53
+ true
54
+ when ::RBS::Types::Union
55
+ type.types.any? { |t| returns_nil?(t) }
56
+ else
57
+ false
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -10,7 +10,7 @@ module RuboCop
10
10
  # `self.new` is a special and fundamental method, and extra care should be taken regarding its return value.
11
11
  # In most cases, assigning it `void` is an unintended mistake.
12
12
  #
13
- # @example default
13
+ # @example
14
14
  # # bad
15
15
  # def self.new: () -> void
16
16
  #
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RBS
6
+ module Lint
7
+ # Specifying the `Hash` type for `**` is a very special case and,
8
+ # in most situations, it is a mistake in type specification.
9
+ #
10
+ # @example
11
+ # # bad
12
+ # def foo: (**Hash[Symbol, String]) -> void
13
+ # # e.g.) foo(a: {x: "x"}, b: {y: "y"}, c: {z: "z"})
14
+ #
15
+ # # good
16
+ # def foo: (**String) -> void
17
+ # # e.g.) foo(a: "x", b: "y", c: "z")
18
+ #
19
+ class RestKeywordHash < RuboCop::RBS::CopBase
20
+ def on_rbs_def(decl)
21
+ decl.overloads.each do |overload|
22
+ func = overload.method_type.type
23
+ next unless func.is_a?(::RBS::Types::Function)
24
+
25
+ if !func.rest_keywords.nil?
26
+ check_type(func.rest_keywords.type)
27
+ end
28
+ end
29
+ end
30
+
31
+ def check_type(type)
32
+ case type
33
+ when ::RBS::Types::ClassInstance
34
+ if type.name.relative!.to_s == 'Hash'
35
+ did_you_mean = type.args[1] or return
36
+ range = location_to_range(type.location)
37
+ message = "The type of `**` specifies only the type of value. " \
38
+ "Did you mean `**#{did_you_mean}`?"
39
+ add_offense(range, message:)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -5,6 +5,7 @@ module RuboCop
5
5
  module RBS
6
6
  module Lint
7
7
  # Just only for syntax error
8
+ #
8
9
  class Syntax < RuboCop::RBS::CopBase
9
10
  def on_rbs_parsing_error
10
11
  e = processed_rbs_source.error or raise
@@ -6,12 +6,13 @@ module RuboCop
6
6
  module Lint
7
7
  # Notice unused overload type parameters.
8
8
  #
9
- # @example default
9
+ # @example
10
10
  # # bad
11
11
  # def foo: [T] () -> void
12
12
  #
13
13
  # # good
14
14
  # def foo: [T] (T) -> T
15
+ #
15
16
  class UnusedOverloadTypeParams < RuboCop::RBS::CopBase
16
17
  MSG = 'Unused overload type variable - `%<variable>s`.'
17
18
 
@@ -6,12 +6,13 @@ module RuboCop
6
6
  module Lint
7
7
  # Notice unused type parameters.
8
8
  #
9
- # @example default
9
+ # @example
10
10
  # # bad
11
11
  # type ary[T] = Array[Integer]
12
12
  #
13
13
  # # good
14
14
  # type ary[T] = Array[T]
15
+ #
15
16
  class UnusedTypeAliasTypeParams < RuboCop::RBS::CopBase
16
17
  MSG = 'Unused type variable - `%<variable>s`.'
17
18
 
@@ -4,7 +4,9 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Lint
7
- # @example default
7
+ # Checks for redundant access modifiers in class and module definitions.
8
+ #
9
+ # @example
8
10
  # # bad
9
11
  # class Foo
10
12
  # public # this is redundant (default access is public)
@@ -7,12 +7,13 @@ module RuboCop
7
7
  # This cop checks the WillSyntaxError in RBS.
8
8
  # RBS with this diagnostics will fail in `rbs validate` command.
9
9
  #
10
- # @example default
10
+ # @example
11
11
  # # bad
12
12
  # def foo: (void) -> void
13
13
  #
14
14
  # # bad
15
15
  # CONST: self
16
+ #
16
17
  class WillSyntaxError < RuboCop::RBS::CopBase
17
18
  # @rbs!
18
19
  # module Types = ::RBS::Types
@@ -4,12 +4,13 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Style
7
- # @example default
7
+ # @example
8
8
  # # bad
9
9
  # def foo: () { () -> bool } -> void
10
10
  #
11
11
  # # good
12
12
  # def foo: () { () -> boolish } -> void
13
+ #
13
14
  class BlockReturnBoolish < RuboCop::RBS::CopBase
14
15
  extend AutoCorrector
15
16
  MSG = 'Use `boolish` instead of `bool` in block return type.'
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Style
7
- # @example default
7
+ # @example
8
8
  # # bad
9
9
  # def foo: () -> TrueClass
10
10
  #
@@ -16,6 +16,7 @@ module RuboCop
16
16
  #
17
17
  # # good
18
18
  # def bar: () -> nil
19
+ #
19
20
  class ClassicType < RuboCop::RBS::CopBase
20
21
  extend AutoCorrector
21
22
 
@@ -4,7 +4,9 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Style
7
- # @example default
7
+ # Unions and intersections of the same type are meaningless.
8
+ #
9
+ # @example
8
10
  # # bad
9
11
  # def foo: (Integer | Integer) -> void
10
12
  #
@@ -13,6 +15,7 @@ module RuboCop
13
15
  #
14
16
  # # good
15
17
  # def foo: (Integer) -> void
18
+ #
16
19
  class DuplicatedType < RuboCop::RBS::CopBase
17
20
  extend AutoCorrector
18
21
 
@@ -4,7 +4,9 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Style
7
- # @example default
7
+ # Checks parentheses for empty arguments.
8
+ #
9
+ # @example
8
10
  # # bad
9
11
  # def foo: -> void
10
12
  #
@@ -16,6 +18,7 @@ module RuboCop
16
18
  #
17
19
  # # good
18
20
  # def foo: () { () -> void } -> ^() -> void
21
+ #
19
22
  class EmptyArgument < RuboCop::RBS::CopBase
20
23
  class MethodTypeChecker
21
24
  include RuboCop::RBS::OnTypeHelper
@@ -4,15 +4,22 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Style
7
- # @example default
7
+ # `#initialize` is a private method and is likely to be overridden.
8
+ # The return type of `#initialize` should not be specific.
9
+ #
10
+ # @example
8
11
  # # bad
9
12
  # def initialize: () -> nil
10
13
  #
14
+ # # bad
15
+ # def initialize: () -> false
16
+ #
11
17
  # # good
12
18
  # def initialize: () -> untyped
13
19
  #
14
20
  # # good
15
21
  # def initialize: () -> void
22
+ #
16
23
  class InitializeReturnType < RuboCop::RBS::CopBase
17
24
  extend AutoCorrector
18
25
  MSG = '`#initialize` method should return `void`'
@@ -7,7 +7,7 @@ module RuboCop
7
7
  module Style
8
8
  # Checks that `instance` in instance context.
9
9
  #
10
- # @example (default)
10
+ # @example
11
11
  # # bad
12
12
  # def foo: (instance) -> instance
13
13
  #
@@ -4,12 +4,15 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Style
7
- # @example default
7
+ # `nil?` is the same as `nil`.
8
+ #
9
+ # @example
8
10
  # # bad
9
11
  # def foo: (nil?) -> void
10
12
  #
11
13
  # # good
12
14
  # def foo: (nil) -> void
15
+ #
13
16
  class OptionalNil < RuboCop::RBS::CopBase
14
17
  extend AutoCorrector
15
18
 
@@ -4,7 +4,9 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Style
7
- # @example default
7
+ # Check for redundant parentheses.
8
+ #
9
+ # @example
8
10
  # # bad
9
11
  # def foo: () -> (bool)
10
12
  #
@@ -16,6 +18,7 @@ module RuboCop
16
18
  #
17
19
  # # good
18
20
  # def foo: ((true | false)) -> bool
21
+ #
19
22
  class RedundantParentheses < RuboCop::RBS::CopBase
20
23
  module BeforeTokenIfLparen
21
24
  def before_token_if_lparen(tokens, base, fun)
@@ -4,7 +4,9 @@ module RuboCop
4
4
  module Cop
5
5
  module RBS
6
6
  module Style
7
- # @example default
7
+ # `true | false` is simply the same as `bool`.
8
+ #
9
+ # @example
8
10
  # # bad
9
11
  # def foo: (true | false) -> (true | false)
10
12
  #
@@ -13,6 +15,7 @@ module RuboCop
13
15
  #
14
16
  # # good
15
17
  # def foo: (bool) -> bool
18
+ #
16
19
  class TrueFalse < RuboCop::RBS::CopBase
17
20
  extend AutoCorrector
18
21
 
@@ -3,6 +3,7 @@
3
3
  require 'rbs'
4
4
 
5
5
  require_relative 'rbs/layout/comment_indentation'
6
+ require_relative 'rbs/layout/empty_line_between_declarations'
6
7
  require_relative 'rbs/layout/empty_lines_around_access_modifier'
7
8
  require_relative 'rbs/layout/empty_lines_around_body'
8
9
  require_relative 'rbs/layout/empty_lines_around_class_body'
@@ -24,9 +25,12 @@ require_relative 'rbs/layout/trailing_whitespace'
24
25
 
25
26
  require_relative 'rbs/lint/ambiguous_keyword_argument_key'
26
27
  require_relative 'rbs/lint/ambiguous_operator_precedence'
28
+ require_relative 'rbs/lint/duplicate_annotation'
27
29
  require_relative 'rbs/lint/duplicate_overload'
30
+ require_relative 'rbs/lint/implicitly_returns_nil'
28
31
  require_relative 'rbs/lint/literal_intersection'
29
32
  require_relative 'rbs/lint/new_returns_void'
33
+ require_relative 'rbs/lint/rest_keyword_hash'
30
34
  require_relative 'rbs/lint/syntax'
31
35
  require_relative 'rbs/lint/top_level_interface'
32
36
  require_relative 'rbs/lint/top_level_type_alias'
@@ -13,6 +13,12 @@ module RuboCop
13
13
 
14
14
  exclude_from_registry
15
15
 
16
+ def self.documentation_url(_config = nil)
17
+ base = "cops_#{department.to_s.downcase.tr('/', '_')}"
18
+ fragment = cop_name.downcase.gsub(/[^a-z]/, '')
19
+ "https://github.com/ksss/rubocop-on-rbs/blob/v#{VERSION}/docs/modules/ROOT/pages/#{base}.adoc##{fragment}"
20
+ end
21
+
16
22
  def on_new_investigation
17
23
  # Called here when valid as Ruby
18
24
  investigation_rbs()
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module RBS
5
- VERSION = '1.6.0'
5
+ VERSION = '1.8.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-on-rbs
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ksss
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-04-25 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: lint_roller
@@ -85,6 +85,7 @@ files:
85
85
  - config/default.yml
86
86
  - lib/rubocop-on-rbs.rb
87
87
  - lib/rubocop/cop/rbs/layout/comment_indentation.rb
88
+ - lib/rubocop/cop/rbs/layout/empty_line_between_declarations.rb
88
89
  - lib/rubocop/cop/rbs/layout/empty_lines.rb
89
90
  - lib/rubocop/cop/rbs/layout/empty_lines_around_access_modifier.rb
90
91
  - lib/rubocop/cop/rbs/layout/empty_lines_around_body.rb
@@ -105,9 +106,12 @@ files:
105
106
  - lib/rubocop/cop/rbs/layout/trailing_whitespace.rb
106
107
  - lib/rubocop/cop/rbs/lint/ambiguous_keyword_argument_key.rb
107
108
  - lib/rubocop/cop/rbs/lint/ambiguous_operator_precedence.rb
109
+ - lib/rubocop/cop/rbs/lint/duplicate_annotation.rb
108
110
  - lib/rubocop/cop/rbs/lint/duplicate_overload.rb
111
+ - lib/rubocop/cop/rbs/lint/implicitly_returns_nil.rb
109
112
  - lib/rubocop/cop/rbs/lint/literal_intersection.rb
110
113
  - lib/rubocop/cop/rbs/lint/new_returns_void.rb
114
+ - lib/rubocop/cop/rbs/lint/rest_keyword_hash.rb
111
115
  - lib/rubocop/cop/rbs/lint/syntax.rb
112
116
  - lib/rubocop/cop/rbs/lint/top_level_interface.rb
113
117
  - lib/rubocop/cop/rbs/lint/top_level_type_alias.rb
@@ -155,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
159
  - !ruby/object:Gem::Version
156
160
  version: '0'
157
161
  requirements: []
158
- rubygems_version: 3.6.6
162
+ rubygems_version: 3.7.0.dev
159
163
  specification_version: 4
160
164
  summary: RuboCop extension for RBS file.
161
165
  test_files: []