rubocop-on-rbs 1.7.0 → 1.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1758c7e798195a042bd2b9266255dda2699470450e839f6ba330da6ff6470919
4
- data.tar.gz: 15fe04c864306c9c17ffa1e1eb7ed58d9974ca33905e2b6ed337647ee05b7d21
3
+ metadata.gz: af5e7c84d5044bb2a7d6e95b4de88a076e9624c96011d0eb41dae6f2de20fec6
4
+ data.tar.gz: 6270af5147ea7981766721a24b70e6cb5adcf82c82c82ba91c5dbe8f0409de43
5
5
  SHA512:
6
- metadata.gz: fca111db62f0ea2f501a08251f3f11829564db8ba842f512b4b11fa8d95b153d2db260f611690b453d7f660d9be07ca59eb0467a69bc041d0c2b1446ca22ba7b
7
- data.tar.gz: 2cbab8660a43d57094f10cac7c3c39c992cf96e404108b7429b10cbaca918159b0c077d3480a907c36dc9292bd145863882d575e692e3fa50f37edc698b5fee5
6
+ metadata.gz: 7b66215eae031a7c9f9cf95498b57998d0942da9a96920684d34227230ab250868e5a3d75cb5bbbf15a90ce8b43dcf0e8a9dd532b4fb41edf486eecdd2df411f
7
+ data.tar.gz: 477c78f1eacc84844b52bf1e2626597d3304a97ed47f4a7641a0be9fff7ddd6f00789aa0953c54cc9dc802419919997206531dffa0ef42f615ea49001a3fb40b
data/config/default.yml CHANGED
@@ -26,8 +26,10 @@ RBS:
26
26
 
27
27
  RBS/Layout:
28
28
  Enabled: true
29
- DocumentationBaseURL: 'https://github.com/ksss/rubocop-on-rbs/blob/main/docs/modules/ROOT/pages'
30
- DocumentationExtension: '.adoc'
29
+
30
+ RBS/Layout/AnnotationIndentation:
31
+ Description: 'Use 2 spaces for annotation indentation'
32
+ Enabled: true
31
33
 
32
34
  RBS/Layout/CommentIndentation:
33
35
  Description: 'Use 2 spaces for comment indentation'
@@ -113,8 +115,6 @@ RBS/Layout/TrailingWhitespace:
113
115
  RBS/Lint:
114
116
  Severity: warning
115
117
  Enabled: true
116
- DocumentationBaseURL: 'https://github.com/ksss/rubocop-on-rbs/blob/main/docs/modules/ROOT/pages'
117
- DocumentationExtension: '.adoc'
118
118
 
119
119
  RBS/Lint/AmbiguousKeywordArgumentKey:
120
120
  Description: 'Check ambiguous keyword argument key'
@@ -124,10 +124,18 @@ RBS/Lint/AmbiguousOperatorPrecedence:
124
124
  Description: 'Check ambiguous operator precedence'
125
125
  Enabled: true
126
126
 
127
+ RBS/Lint/DuplicateAnnotation:
128
+ Description: 'Checks that there are no repeated annotations'
129
+ Enabled: true
130
+
127
131
  RBS/Lint/DuplicateOverload:
128
132
  Description: 'Checks that there are no repeated overload bodies'
129
133
  Enabled: true
130
134
 
135
+ RBS/Lint/ImplicitlyReturnsNil:
136
+ Description: 'Check implicitly returns nil'
137
+ Enabled: true
138
+
131
139
  RBS/Lint/LiteralIntersection:
132
140
  Description: 'Check literal intersection'
133
141
  Enabled: true
@@ -176,8 +184,6 @@ RBS/Lint/WillSyntaxError:
176
184
 
177
185
  RBS/Style:
178
186
  Enabled: true
179
- DocumentationBaseURL: 'https://github.com/ksss/rubocop-on-rbs/blob/main/docs/modules/ROOT/pages'
180
- DocumentationExtension: '.adoc'
181
187
 
182
188
  RBS/Style/BlockReturnBoolish:
183
189
  Description: 'Use `bool` for block return type'
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RBS
6
+ module Layout
7
+ # Checks the indentation of annotations in RBS.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # # comment
12
+ # %a{pure}
13
+ # def foo: () -> void
14
+ #
15
+ # # good
16
+ # # comment
17
+ # %a{pure}
18
+ # def foo: () -> void
19
+ #
20
+ class AnnotationIndentation < RuboCop::RBS::CopBase
21
+ extend AutoCorrector
22
+
23
+ MSG = "Incorrect indentation detected (column %<expect>s instead of %<actual>s)."
24
+
25
+ def on_rbs_new_investigation
26
+ indent_start_lines = Set.new
27
+ indent_end_lines = Set.new
28
+ ignore_poses = Set.new
29
+ processed_rbs_source.decls.each do |decl|
30
+ walk_decl(decl) do |d|
31
+ indent_start_lines << d.location.start_line
32
+ indent_end_lines << d.location.end_line
33
+ d.members.each do |member|
34
+ case member
35
+ when ::RBS::AST::Members::MethodDefinition
36
+ member.overloads.each do |overload|
37
+ overload.annotations.each do |annotation|
38
+ ignore_poses << annotation.location.start_pos
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ expected_width = 0
47
+ last_annotation_line = -1
48
+ processed_rbs_source.tokens.each do |token|
49
+ case token.type
50
+ when :kMODULE, :kCLASS, :kINTERFACE
51
+ next unless indent_start_lines.include?(token.location.start_line)
52
+
53
+ expected_width += 2
54
+ when :kEND
55
+ next unless indent_end_lines.include?(token.location.start_line)
56
+
57
+ expected_width -= 2
58
+ when :tANNOTATION
59
+ next if ignore_poses.include?(token.location.start_pos)
60
+
61
+ if token.location.start_column == expected_width
62
+ last_annotation_line = token.location.start_line
63
+ next
64
+ end
65
+ next if last_annotation_line == token.location.start_line
66
+
67
+ token_range = location_to_range(token.location)
68
+ message = format(MSG, expect: expected_width, actual: token.location.start_column)
69
+ last_annotation_line = token.location.start_line
70
+ add_offense(token_range, message: message) do |corrector|
71
+ line_start_pos = processed_source.buffer.line_range(token.location.start_line).begin_pos
72
+ indent = range_between(line_start_pos, token.location.start_pos)
73
+ corrector.replace(indent, ' ' * expected_width)
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ def walk_decl(decl, &block)
80
+ if decl.respond_to?(:members)
81
+ yield decl
82
+ decl.members.each { |member| walk_decl(member, &block) }
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -21,45 +21,47 @@ module RuboCop
21
21
  MSG = "Incorrect indentation detected (column %<expect>s instead of %<actual>s)."
22
22
 
23
23
  def on_rbs_new_investigation
24
- indent_start_lines = Set.new
25
- indent_end_lines = Set.new
26
- processed_rbs_source.decls.each do |decl|
27
- walk_decl(decl) do |d|
28
- indent_start_lines << d.location.start_line
29
- indent_end_lines << d.location.end_line
30
- end
24
+ comments = processed_rbs_source.tokens.select { |token| token.type == :tLINECOMMENT }
25
+ comments.each_with_index do |token, comment_index|
26
+ check(token, comment_index)
31
27
  end
28
+ end
32
29
 
33
- expected_width = 0
34
- processed_rbs_source.tokens.each do |token|
35
- case token.type
36
- when :kMODULE, :kCLASS, :kINTERFACE
37
- next unless indent_start_lines.include?(token.location.start_line)
30
+ def check(comment_token, _comment_index)
31
+ next_line = line_after_comment(comment_token)
32
+ correct_comment_indentation = correct_indentation(next_line)
33
+ column = comment_token.location.start_column
38
34
 
39
- expected_width += 2
40
- when :kEND
41
- next unless indent_end_lines.include?(token.location.start_line)
35
+ column_delta = correct_comment_indentation - column
36
+ return if column_delta.zero?
42
37
 
43
- expected_width -= 2
44
- when :tLINECOMMENT
45
- if token.location.start_column != expected_width
46
- token_range = location_to_range(token.location)
47
- message = format(MSG, expect: expected_width, actual: token.location.start_column)
48
- add_offense(token_range, message: message) do |corrector|
49
- line_start_pos = processed_source.buffer.line_range(token.location.start_line).begin_pos
50
- indent = range_between(line_start_pos, token.location.start_pos)
51
- corrector.replace(indent, ' ' * expected_width)
52
- end
53
- end
54
- end
38
+ token_range = location_to_range(comment_token.location)
39
+ message = format(MSG, expect: correct_comment_indentation, actual: column)
40
+ add_offense(token_range, message: message) do |corrector|
41
+ line_start_pos = processed_source.buffer.line_range(comment_token.location.start_line).begin_pos
42
+ indent = range_between(line_start_pos, comment_token.location.start_pos)
43
+ corrector.replace(indent, ' ' * correct_comment_indentation)
55
44
  end
56
45
  end
57
46
 
58
- def walk_decl(decl, &block)
59
- if decl.respond_to?(:members)
60
- yield decl
61
- decl.members.each { |member| walk_decl(member, &block) }
62
- end
47
+ def line_after_comment(comment)
48
+ lines = processed_source.lines
49
+ lines[comment.location.start_line..].find { |line| !line.blank? }
50
+ end
51
+
52
+ def correct_indentation(next_line)
53
+ return 0 unless next_line
54
+
55
+ indentation_of_next_line = next_line =~ /\S/
56
+ indentation_of_next_line + if less_indented?(next_line)
57
+ 2
58
+ else
59
+ 0
60
+ end
61
+ end
62
+
63
+ def less_indented?(line)
64
+ /\A\s*end\b/.match?(line)
63
65
  end
64
66
  end
65
67
  end
@@ -68,7 +68,7 @@ module RuboCop
68
68
  end
69
69
 
70
70
  def previous_line_ignoring_comments(processed_source, send_line)
71
- processed_source[0..send_line - 2].reverse.find { |line| !comment_line?(line) }
71
+ processed_source[0..(send_line - 2)].reverse.find { |line| !comment_line?(line) }
72
72
  end
73
73
 
74
74
  def previous_line_empty?(send_line)
@@ -14,8 +14,15 @@ module RuboCop
14
14
  class SpaceAroundOperators < RuboCop::RBS::CopBase
15
15
  extend AutoCorrector
16
16
 
17
+ def on_rbs_class(decl)
18
+ check_type_params(decl)
19
+ end
20
+ alias on_rbs_module on_rbs_class
21
+ alias on_rbs_interface on_rbs_class
22
+
17
23
  def on_rbs_def(decl)
18
24
  decl.overloads.each do |overload|
25
+ check_type_params(overload.method_type)
19
26
  overload.method_type.each_type do |type|
20
27
  check_type(type)
21
28
  end
@@ -26,10 +33,14 @@ module RuboCop
26
33
  check_type(decl.type)
27
34
  end
28
35
  alias on_rbs_global on_rbs_constant
29
- alias on_rbs_type_alias on_rbs_constant
30
36
  alias on_rbs_attribute on_rbs_constant
31
37
  alias on_rbs_var on_rbs_constant
32
38
 
39
+ def on_rbs_type_alias(decl)
40
+ check_type_params(decl)
41
+ check_type(decl.type)
42
+ end
43
+
33
44
  def check_type(type)
34
45
  case type
35
46
  when ::RBS::Types::Union
@@ -42,6 +53,13 @@ module RuboCop
42
53
  end
43
54
  end
44
55
 
56
+ def check_type_params(decl)
57
+ decl.type_params.each do |type_param|
58
+ check_type(type_param.default_type) if type_param.default_type
59
+ check_type(type_param.upper_bound_type) if type_param.upper_bound_type
60
+ end
61
+ end
62
+
45
63
  def check_operator(type, operator)
46
64
  type.types.each_cons(2) do |before, after|
47
65
  next unless before.location.end_line == after.location.start_line
@@ -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
@@ -13,6 +13,7 @@ module RuboCop
13
13
  #
14
14
  class BlockReturnBoolish < RuboCop::RBS::CopBase
15
15
  extend AutoCorrector
16
+
16
17
  MSG = 'Use `boolish` instead of `bool` in block return type.'
17
18
 
18
19
  # @sig decl: ::RBS::AST::Members::MethodDefinition
@@ -16,6 +16,7 @@ module RuboCop
16
16
  #
17
17
  class ClassWithSingleton < RuboCop::RBS::CopBase
18
18
  extend AutoCorrector
19
+
19
20
  MSG = 'Use `self` instead of `class`.'
20
21
 
21
22
  # @rbs decl: RBS::AST::Members::MethodDefinition
@@ -22,6 +22,7 @@ module RuboCop
22
22
  #
23
23
  class InitializeReturnType < RuboCop::RBS::CopBase
24
24
  extend AutoCorrector
25
+
25
26
  MSG = '`#initialize` method should return `void`'
26
27
 
27
28
  def on_rbs_def(decl)
@@ -16,6 +16,7 @@ module RuboCop
16
16
  #
17
17
  class InstanceWithInstance < RuboCop::RBS::CopBase
18
18
  extend AutoCorrector
19
+
19
20
  MSG = 'Use `self` instead of `instance`.'
20
21
 
21
22
  # @rbs decl: RBS::AST::Declarations::Class
@@ -49,6 +49,7 @@ module RuboCop
49
49
  class ParenChecker
50
50
  include BeforeTokenIfLparen
51
51
  include RangeHelp
52
+
52
53
  attr_reader :processed_source
53
54
 
54
55
  def initialize(processed_source:, base:, tokens:, type:, skip:, cop:)
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'rbs'
4
4
 
5
+ require_relative 'rbs/layout/annotation_indentation'
5
6
  require_relative 'rbs/layout/comment_indentation'
6
7
  require_relative 'rbs/layout/empty_line_between_declarations'
7
8
  require_relative 'rbs/layout/empty_lines_around_access_modifier'
@@ -25,7 +26,9 @@ require_relative 'rbs/layout/trailing_whitespace'
25
26
 
26
27
  require_relative 'rbs/lint/ambiguous_keyword_argument_key'
27
28
  require_relative 'rbs/lint/ambiguous_operator_precedence'
29
+ require_relative 'rbs/lint/duplicate_annotation'
28
30
  require_relative 'rbs/lint/duplicate_overload'
31
+ require_relative 'rbs/lint/implicitly_returns_nil'
29
32
  require_relative 'rbs/lint/literal_intersection'
30
33
  require_relative 'rbs/lint/new_returns_void'
31
34
  require_relative 'rbs/lint/rest_keyword_hash'
@@ -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.7.0'
5
+ VERSION = '1.9.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.7.0
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ksss
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-05-18 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
@@ -84,6 +84,7 @@ files:
84
84
  - README.md
85
85
  - config/default.yml
86
86
  - lib/rubocop-on-rbs.rb
87
+ - lib/rubocop/cop/rbs/layout/annotation_indentation.rb
87
88
  - lib/rubocop/cop/rbs/layout/comment_indentation.rb
88
89
  - lib/rubocop/cop/rbs/layout/empty_line_between_declarations.rb
89
90
  - lib/rubocop/cop/rbs/layout/empty_lines.rb
@@ -106,7 +107,9 @@ files:
106
107
  - lib/rubocop/cop/rbs/layout/trailing_whitespace.rb
107
108
  - lib/rubocop/cop/rbs/lint/ambiguous_keyword_argument_key.rb
108
109
  - lib/rubocop/cop/rbs/lint/ambiguous_operator_precedence.rb
110
+ - lib/rubocop/cop/rbs/lint/duplicate_annotation.rb
109
111
  - lib/rubocop/cop/rbs/lint/duplicate_overload.rb
112
+ - lib/rubocop/cop/rbs/lint/implicitly_returns_nil.rb
110
113
  - lib/rubocop/cop/rbs/lint/literal_intersection.rb
111
114
  - lib/rubocop/cop/rbs/lint/new_returns_void.rb
112
115
  - lib/rubocop/cop/rbs/lint/rest_keyword_hash.rb
@@ -157,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
160
  - !ruby/object:Gem::Version
158
161
  version: '0'
159
162
  requirements: []
160
- rubygems_version: 3.6.6
163
+ rubygems_version: 4.0.3
161
164
  specification_version: 4
162
165
  summary: RuboCop extension for RBS file.
163
166
  test_files: []