rubocop-on-rbs 0.3.0 → 0.4.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: b70070f22849df33c71ad69c0f2a08c1a6a2d0523c19f779868dda630787de43
4
- data.tar.gz: 43789ae285bc5e4f155ba5641fed3471cf27715e58007c02e26661d853304084
3
+ metadata.gz: adb415dc438caa7d859497f2915d37fe647ba2c0a0c396a1afc79f6aec2a53ee
4
+ data.tar.gz: 621b0e9338aab521860cf7e73c7b346015f3e9e51b6af06d9159b1844083281a
5
5
  SHA512:
6
- metadata.gz: 5a3dece661499c49c0f62c9db11c5a3ee5d0e926d4aedbced0c27b09fda4425eaea161663d22cbf3edf7f37a12fd83e56350b6832f4d90eeac17d027dd5c6f3f
7
- data.tar.gz: '0662672318876ae0d61e604c3e5e9d7405000fb5632ece629ee7497ba5d45b9e9c0ebd1b11aa687472a07bf4b1fdde988f803975007841c47b21ed313ee3482c'
6
+ metadata.gz: 6e3357ceba540c5c6ee25188804ebe95965147e47970bc39c98fd8fe60eb8f52af762c1a3a90ca9e68be9d63e2263622cffc983b029232fd23f89d6f536a12b3
7
+ data.tar.gz: a9155f9687029947fb9bb4d0c47332a5bc3075e400872ebf1e58312f7d6cd47ffa0d37c4005c644adb08e88494c8c14d84a063e2550590db93c75ac7e95f0136
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.0] - 2024-06-11
4
+
5
+ * Implement RedundantOverloadTypeParams instead of UselessOverloadTypeParams by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/1
6
+ * Introduce RBS/Lint/DuplicateOverload by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/2
7
+ * Fix typo by @ydah in https://github.com/ksss/rubocop-on-rbs/pull/3
8
+ * Remove unnecessary Exclude settings in .rubocop.yml by @ydah in https://github.com/ksss/rubocop-on-rbs/pull/4
9
+ * Generate docs for cop by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/5
10
+
3
11
  ## [0.1.0] - 2024-05-15
4
12
 
5
13
  - Initial release
data/README.md CHANGED
@@ -64,6 +64,10 @@ And restart VSCode.
64
64
 
65
65
  ## Departments
66
66
 
67
+ You can see documentation for all cops.
68
+
69
+ https://github.com/ksss/rubocop-on-rbs/blob/main/docs/modules/ROOT/pages/cops.adoc
70
+
67
71
  ### RBS
68
72
 
69
73
  This gem handles many cops.
@@ -74,8 +78,6 @@ RBS:
74
78
  Enabled: true
75
79
  ```
76
80
 
77
- See `config/default.yml` for all Cop.
78
-
79
81
  ### RBS/Layout
80
82
 
81
83
  This department is a collection of relatively minor fixes has been gathered.
data/config/default.yml CHANGED
@@ -59,6 +59,10 @@ RBS/Layout/SpaceAroundBraces:
59
59
  Description: 'Use space around `{}`'
60
60
  Enabled: true
61
61
 
62
+ RBS/Layout/SpaceAroundOperators:
63
+ Description: 'Use space around `|` or `&`'
64
+ Enabled: true
65
+
62
66
  RBS/Layout/SpaceBeforeColon:
63
67
  Description: 'Use space before `:`'
64
68
  Enabled: true
@@ -81,7 +85,12 @@ RBS/Lint/DuplicateOverload:
81
85
  Description: 'Checks that there are no repeated overload bodies'
82
86
  Enabled: true
83
87
 
84
- RBS/Lint/RedundantOverloadTypeParams:
88
+ RBS/Lint/LiteralIntersection:
89
+ Severity: warning
90
+ Description: 'Check literal intersection'
91
+ Enabled: true
92
+
93
+ RBS/Lint/UselessOverloadTypeParams:
85
94
  Severity: warning
86
95
  Description: 'Check redundant overload type params'
87
96
  Enabled: true
@@ -91,53 +100,6 @@ RBS/Lint/Syntax:
91
100
  Description: 'Check RBS syntax'
92
101
  Enabled: true
93
102
 
94
- RBS/Lint/TypeParamsArity:
95
- Severity: warning
96
- Description: 'Check type params arity'
97
- Enabled: true
98
- Expects:
99
- # Default expects.
100
- # You can add expects in .rubocop.yml.
101
-
102
- ## class/module
103
- Array: 1
104
- Enumerable: 1
105
- Enumerator: 2
106
- Enumerator::Chain: 1
107
- Enumerator::Generator: 1
108
- Enumerator::Lazy: 2
109
- Enumerator::Product: 1
110
- FrozenError: 1
111
- Hash: 2
112
- KeyError: 2
113
- NameError: 1
114
- NoMatchingPatternKeyError: 2
115
- NoMethodError: 1
116
- ObjectSpace::WeakKeyMap: 2
117
- Range: 1
118
- Set: 1
119
- Struct: 1
120
-
121
- ## interface
122
- Array::_Pattern: 1
123
- Enumerable::_NotFound: 1
124
- Gem::_HashLike: 2
125
- Kernel::_RationalDiv: 1
126
- Marshal::_Proc: 1
127
- String::_MatchAgainst: 2
128
- _Each: 1
129
- _EachEntry: 1
130
- _Range: 1
131
- _ToA: 1
132
- _ToAry: 1
133
- _ToH: 2
134
- _ToHash: 2
135
-
136
- ## type alias
137
- array: 1
138
- hash: 2
139
- range: 1
140
-
141
103
  RBS/Lint/WillSyntaxError:
142
104
  Severity: warning
143
105
  Description: 'Check RBS will syntax error'
@@ -160,18 +122,22 @@ RBS/Style/DuplicatedType:
160
122
  Description: 'Check duplicated type'
161
123
  Enabled: true
162
124
 
163
- RBS/Style/InitializeReturnType:
164
- Description: 'Use `void` for initialize method'
125
+ RBS/Style/EmptyArgument:
126
+ Description: 'Use `()` for empty argument'
165
127
  Enabled: true
166
128
 
167
- RBS/Style/MergeUntyped:
168
- Description: 'Merge to `untyped`'
129
+ RBS/Style/InitializeReturnType:
130
+ Description: 'Use `void` for initialize method'
169
131
  Enabled: true
170
132
 
171
133
  RBS/Style/OptionalNil:
172
134
  Description: 'Use nil instead of nil?'
173
135
  Enabled: true
174
136
 
137
+ RBS/Style/RedundantParentheses:
138
+ Description: 'Remove redundant parentheses'
139
+ Enabled: true
140
+
175
141
  RBS/Style/TrueFalse:
176
142
  Description: 'Use bool instead of true | false'
177
143
  Enabled: true
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RBS
6
+ module Layout
7
+ # @example default
8
+ # # bad
9
+ # Integer|String
10
+ #
11
+ # # good
12
+ # Integer | String
13
+ class SpaceAroundOperators < RuboCop::RBS::CopBase
14
+ extend AutoCorrector
15
+
16
+ def on_rbs_def(decl)
17
+ decl.overloads.each do |overload|
18
+ overload.method_type.each_type do |type|
19
+ on_type(type)
20
+ end
21
+ end
22
+ end
23
+
24
+ def on_type(type)
25
+ case type
26
+ when ::RBS::Types::Union
27
+ check_operator(type, '|')
28
+ when ::RBS::Types::Intersection
29
+ check_operator(type, '&')
30
+ end
31
+ type.each_type do |t|
32
+ on_type(t)
33
+ end
34
+ end
35
+
36
+ def check_operator(type, operator)
37
+ type.types.each_cons(2) do |before, after|
38
+ next unless before.location.end_line == after.location.start_line
39
+
40
+ operator_index = type.location.source.index(
41
+ operator,
42
+ before.location.end_pos - type.location.start_pos
43
+ ) or raise
44
+ operator_index += type.location.start_pos
45
+ operator_range = range_between(operator_index, operator_index + 1)
46
+
47
+ before_char = processed_source.raw_source[operator_index - 1]
48
+ if before_char != ' '
49
+ add_offense(operator_range, message: "Use one space before `#{operator}`.") do |corrector|
50
+ corrector.insert_before(operator_range, ' ')
51
+ end
52
+ end
53
+
54
+ after_char = processed_source.raw_source[operator_index + 1]
55
+ if after_char != ' '
56
+ add_offense(operator_range, message: "Use one space after `#{operator}`.") do |corrector|
57
+ corrector.insert_after(operator_range, ' ')
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,59 @@
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 overload bodies
8
+ #
9
+ # @example default
10
+ # # bad
11
+ # 1 & 2
12
+ #
13
+ # # bad
14
+ # 1 & _Foo
15
+ #
16
+ class LiteralIntersection < RuboCop::RBS::CopBase
17
+ MSG = "Don't use literals with `&`."
18
+
19
+ def on_rbs_def(decl)
20
+ decl.overloads.each do |overload|
21
+ overload.method_type.each_type do |type|
22
+ check_type(type)
23
+ end
24
+ end
25
+ end
26
+
27
+ def check_type(type)
28
+ on_type([::RBS::Types::Intersection], type) do |intersection|
29
+ check_intersection(intersection)
30
+ end
31
+ end
32
+
33
+ def on_rbs_constant(type)
34
+ check_type(type.type)
35
+ end
36
+ alias on_rbs_global on_rbs_constant
37
+ alias on_rbs_type_alias on_rbs_constant
38
+ alias on_rbs_attribute on_rbs_constant
39
+
40
+ def check_intersection(intersection)
41
+ intersection.types.each do |type|
42
+ check_intersection_child(type)
43
+ end
44
+ end
45
+
46
+ def check_intersection_child(type)
47
+ case type
48
+ when ::RBS::Types::Literal
49
+ range = location_to_range(type.location)
50
+ add_offense(range)
51
+ when ::RBS::Types::Intersection
52
+ check_intersection(type)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -10,16 +10,10 @@ module RuboCop
10
10
  # # bad
11
11
  # def foo: [T] () -> void
12
12
  #
13
- # # bad
14
- # def bar: [T] () -> T
15
- #
16
- # # bad
17
- # def baz: [T] () { () -> T } -> void
18
- #
19
13
  # # good
20
- # def foo: [T] (Array[T]) -> T
21
- class RedundantOverloadTypeParams < RuboCop::RBS::CopBase
22
- MSG = 'Redundant overload type variable - `%<variable>s`.'
14
+ # def foo: [T] (T) -> T
15
+ class UselessOverloadTypeParams < RuboCop::RBS::CopBase
16
+ MSG = 'Useless overload type variable - `%<variable>s`.'
23
17
 
24
18
  def on_rbs_def(decl)
25
19
  decl.overloads.each do |overload|
@@ -27,16 +21,7 @@ module RuboCop
27
21
 
28
22
  type_params = overload.method_type.type_params
29
23
 
30
- types = []
31
- overload.method_type.type.each_param do |param|
32
- types << param.type
33
- end
34
- overload.method_type.block&.then do |block|
35
- block.type.each_type do |t|
36
- types << t
37
- end
38
- end
39
- types.each do |type|
24
+ overload.method_type.each_type do |type|
40
25
  used_variable_in_type(type) do |var|
41
26
  type_params.delete_if { |type_param| type_param.name == var.name }
42
27
  end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RBS
6
+ module Style
7
+ # @example default
8
+ # # bad
9
+ # def foo: -> void
10
+ #
11
+ # # bad
12
+ # def foo: () { -> void } -> void
13
+ #
14
+ # # bad
15
+ # def foo: () -> ^ -> void
16
+ #
17
+ # # good
18
+ # def foo: () { () -> void } -> ^() -> void
19
+ class EmptyArgument < RuboCop::RBS::CopBase
20
+ extend AutoCorrector
21
+
22
+ MSG = 'Insert `()` when empty argument'
23
+
24
+ def on_rbs_def(decl)
25
+ decl.overloads.each do |overload|
26
+ if !overload.method_type.location.source.start_with?('(')
27
+ range = range_between(overload.method_type.location.start_pos, overload.method_type.location.start_pos)
28
+ add_offense(range) do |corrector|
29
+ corrector.insert_before(range, '()')
30
+ end
31
+ end
32
+ if overload.method_type.block
33
+ tokens = tokenize(overload.method_type.location.source)
34
+ block_arrow_index = tokens.find_index { |t| t.type == :pARROW } or raise
35
+ if tokens[block_arrow_index - 1].type != :pRPAREN
36
+ range = range_between(
37
+ overload.method_type.location.start_pos + tokens[block_arrow_index].location.start_pos,
38
+ overload.method_type.location.start_pos + tokens[block_arrow_index].location.start_pos
39
+ )
40
+ add_offense(range) do |corrector|
41
+ corrector.insert_before(range, '()')
42
+ end
43
+ end
44
+ end
45
+
46
+ overload.method_type.each_type do |type|
47
+ check_type(type)
48
+ end
49
+ end
50
+ end
51
+
52
+ def on_rbs_constant(const)
53
+ check_type(const.type)
54
+ end
55
+ alias on_rbs_global on_rbs_constant
56
+ alias on_rbs_type_alias on_rbs_constant
57
+ alias on_rbs_attribute on_rbs_constant
58
+
59
+ def check_type(type)
60
+ case type
61
+ when ::RBS::Types::Proc
62
+ check_proc(type)
63
+ else
64
+ type.each_type do |t|
65
+ check_type(t)
66
+ end
67
+ end
68
+ end
69
+
70
+ def check_proc(type)
71
+ tokens = tokenize(type.location.source)
72
+ if tokens[1].type != :pLPAREN
73
+ range = range_between(
74
+ type.location.start_pos + tokens[0].location.end_pos,
75
+ type.location.start_pos + tokens[0].location.end_pos
76
+ )
77
+ add_offense(range) do |corrector|
78
+ corrector.insert_after(range, '()')
79
+ end
80
+ end
81
+
82
+ if type.block
83
+ block_arrow_index = tokens.find_index { |t| t.type == :pARROW } or raise
84
+ if tokens[block_arrow_index - 1].type != :pRPAREN
85
+ range = range_between(
86
+ type.location.start_pos + tokens[block_arrow_index].location.start_pos,
87
+ type.location.start_pos + tokens[block_arrow_index].location.start_pos
88
+ )
89
+ add_offense(range) do |corrector|
90
+ corrector.insert_before(range, '()')
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ def tokenize(source)
97
+ ::RBS::Parser.lex(source).value.reject { |t| t.type == :tTRIVIA }
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -6,18 +6,17 @@ module RuboCop
6
6
  module Style
7
7
  # @example default
8
8
  # # bad
9
- # def initialize: () -> untyped
10
- #
11
- # # bad
12
9
  # def initialize: () -> nil
13
10
  #
14
11
  # # good
12
+ # def initialize: () -> untyped
13
+ #
14
+ # # good
15
15
  # def initialize: () -> void
16
16
  class InitializeReturnType < RuboCop::RBS::CopBase
17
17
  extend AutoCorrector
18
18
  MSG = '`#initialize` method should return `void`'
19
19
 
20
- # @sig decl: ::RBS::AST::Members::MethodDefinition
21
20
  def on_rbs_def(decl)
22
21
  return unless decl.name == :initialize
23
22
  return unless decl.kind == :instance
@@ -25,6 +24,7 @@ module RuboCop
25
24
 
26
25
  decl.overloads.each do |overload|
27
26
  return_type = overload.method_type.type.return_type
27
+ next if return_type.is_a?(::RBS::Types::Bases::Any)
28
28
  next if return_type.is_a?(::RBS::Types::Bases::Void)
29
29
 
30
30
  range = location_to_range(return_type.location)
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RBS
6
+ module Style
7
+ # @example default
8
+ # # bad
9
+ # def foo: () -> (bool)
10
+ #
11
+ # # bad
12
+ # def foo: (((true | false))) -> void
13
+ #
14
+ # # good
15
+ # def foo: () -> bool
16
+ #
17
+ # # good
18
+ # def foo: ((true | false)) -> bool
19
+ class RedundantParentheses < RuboCop::RBS::CopBase
20
+ module BeforeTokenIfLparen
21
+ def before_token_if_lparen(tokens, base, fun)
22
+ first_param = fun.each_param.first
23
+ return unless first_param
24
+
25
+ b, _ = token_before_after(tokens, first_param.location.start_pos - base)
26
+ return unless b&.type == :pLPAREN
27
+
28
+ yield b
29
+ end
30
+
31
+ private
32
+
33
+ def token_before_after(tokens, pos)
34
+ token_index = tokens.bsearch_index do |t|
35
+ t.location.start_pos >= pos
36
+ end
37
+ return unless token_index
38
+
39
+ [
40
+ tokens[token_index - 1],
41
+ tokens[token_index + 1]
42
+ ]
43
+ end
44
+ end
45
+
46
+ class ParenChecker
47
+ include BeforeTokenIfLparen
48
+ include RangeHelp
49
+ attr_reader :processed_source
50
+
51
+ def initialize(processed_source:, base:, tokens:, type:, skip:, cop:)
52
+ @processed_source = processed_source
53
+ @base = base
54
+ @tokens = tokens
55
+ @type = type
56
+ @skip = skip
57
+ @cop = cop
58
+ end
59
+
60
+ def check
61
+ @cop.on_type([::RBS::Types::Proc], @type) do |proc_type|
62
+ before_token_if_lparen(@tokens, @base, proc_type.type) do |b|
63
+ @skip << (b.location.start_pos + @base)
64
+ end
65
+ if proc_type.block
66
+ before_token_if_lparen(@tokens, @base, proc_type.block.type) do |b|
67
+ @skip << (b.location.start_pos + @base)
68
+ end
69
+ end
70
+ end
71
+
72
+ excludes = [
73
+ ::RBS::Types::Union,
74
+ ::RBS::Types::Intersection,
75
+ ::RBS::Types::Proc
76
+ ]
77
+ @cop.on_not_type(excludes, @type) do |type|
78
+ check_parentheses(type)
79
+ end
80
+ end
81
+
82
+ def check_parentheses(type)
83
+ type_token_start_index = @tokens.bsearch_index do |token|
84
+ (token.location.start_pos + @base) >= type.location.start_pos
85
+ end or raise
86
+ before_token = @tokens[type_token_start_index - 1]
87
+ return if @skip.include?(before_token.location.start_pos + @base)
88
+ return if before_token&.type != :pLPAREN
89
+
90
+ type_token_end_index = @tokens.bsearch_index do |token|
91
+ (token.location.start_pos + @base) >= type.location.end_pos
92
+ end or raise
93
+ after_token = @tokens[type_token_end_index]
94
+ return if after_token&.type != :pRPAREN
95
+
96
+ range = range_between(before_token.location.start_pos + @base, after_token.location.end_pos + @base)
97
+ @cop.add_offense(range, message: "Don't use parentheses around simple type.") do |corrector|
98
+ corrector.remove(range_between(before_token.location.start_pos + @base,
99
+ before_token.location.end_pos + @base))
100
+ corrector.remove(range_between(after_token.location.start_pos + @base,
101
+ after_token.location.end_pos + @base))
102
+ end
103
+ end
104
+ end
105
+
106
+ include BeforeTokenIfLparen
107
+ extend AutoCorrector
108
+
109
+ def on_rbs_def(decl)
110
+ base = decl.location.start_pos
111
+ tokens = tokenize(decl.location.source)
112
+ skip = Set.new
113
+ decl.overloads.each do |overload|
114
+ before_token_if_lparen(tokens, base, overload.method_type.type) do |b|
115
+ skip << (b.location.start_pos + base)
116
+ end
117
+ if overload.method_type.block
118
+ before_token_if_lparen(tokens, base, overload.method_type.block.type) do |b|
119
+ skip << (b.location.start_pos + base)
120
+ end
121
+ end
122
+ overload.method_type.each_type do |type|
123
+ check_type(tokens:, type:, base:, skip:)
124
+ end
125
+ end
126
+ end
127
+
128
+ def check_type(tokens:, type:, base:, skip: Set.new)
129
+ ParenChecker.new(
130
+ processed_source:,
131
+ base:,
132
+ tokens:,
133
+ type:,
134
+ skip:,
135
+ cop: self
136
+ ).check
137
+ end
138
+
139
+ def on_rbs_constant(const)
140
+ tokens = tokenize(const.location.source)
141
+ type = const.type
142
+ base = const.location.start_pos
143
+ check_type(tokens:, type:, base:)
144
+ end
145
+ alias on_rbs_global on_rbs_constant
146
+ alias on_rbs_type_alias on_rbs_constant
147
+ alias on_rbs_attribute on_rbs_constant
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
@@ -10,20 +10,22 @@ require_relative 'rbs/layout/indentation_width'
10
10
  require_relative 'rbs/layout/overload_indentation'
11
11
  require_relative 'rbs/layout/space_around_arrow'
12
12
  require_relative 'rbs/layout/space_around_braces'
13
+ require_relative 'rbs/layout/space_around_operators'
13
14
  require_relative 'rbs/layout/space_before_colon'
14
15
  require_relative 'rbs/layout/space_before_overload'
15
16
  require_relative 'rbs/layout/trailing_whitespace'
16
17
 
17
18
  require_relative 'rbs/lint/duplicate_overload'
18
- require_relative 'rbs/lint/redundant_overload_type_params'
19
+ require_relative 'rbs/lint/literal_intersection'
20
+ require_relative 'rbs/lint/useless_overload_type_params'
19
21
  require_relative 'rbs/lint/syntax'
20
- require_relative 'rbs/lint/type_params_arity'
21
22
  require_relative 'rbs/lint/will_syntax_error'
22
23
 
23
24
  require_relative 'rbs/style/block_return_boolish'
24
- require_relative 'rbs/style/true_false'
25
25
  require_relative 'rbs/style/classic_type'
26
- require_relative 'rbs/style/optional_nil'
27
26
  require_relative 'rbs/style/duplicated_type'
27
+ require_relative 'rbs/style/empty_argument'
28
28
  require_relative 'rbs/style/initialize_return_type'
29
- require_relative 'rbs/style/merge_untyped'
29
+ require_relative 'rbs/style/optional_nil'
30
+ require_relative 'rbs/style/redundant_parentheses'
31
+ require_relative 'rbs/style/true_false'
@@ -86,6 +86,32 @@ module RuboCop
86
86
  def location_to_range(location)
87
87
  range_between(location.start_pos, location.end_pos)
88
88
  end
89
+
90
+ def tokenize(source)
91
+ ::RBS::Parser.lex(source).value.reject { |t| t.type == :tTRIVIA }
92
+ end
93
+
94
+ def on_type(types, type, &block)
95
+ case type
96
+ when *types
97
+ yield type
98
+ end
99
+ type.each_type do |t|
100
+ on_type(types, t, &block)
101
+ end
102
+ end
103
+
104
+ def on_not_type(types, type, &block)
105
+ case type
106
+ when *types
107
+ # not
108
+ else
109
+ yield type
110
+ end
111
+ type.each_type do |t|
112
+ on_not_type(types, t, &block)
113
+ end
114
+ end
89
115
  end
90
116
  end
91
117
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module RBS
5
- VERSION = '0.3.0'
5
+ VERSION = '0.4.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-on-rbs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ksss
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-06-11 00:00:00.000000000 Z
11
+ date: 2024-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbs
@@ -59,20 +59,22 @@ files:
59
59
  - lib/rubocop/cop/rbs/layout/overload_indentation.rb
60
60
  - lib/rubocop/cop/rbs/layout/space_around_arrow.rb
61
61
  - lib/rubocop/cop/rbs/layout/space_around_braces.rb
62
+ - lib/rubocop/cop/rbs/layout/space_around_operators.rb
62
63
  - lib/rubocop/cop/rbs/layout/space_before_colon.rb
63
64
  - lib/rubocop/cop/rbs/layout/space_before_overload.rb
64
65
  - lib/rubocop/cop/rbs/layout/trailing_whitespace.rb
65
66
  - lib/rubocop/cop/rbs/lint/duplicate_overload.rb
66
- - lib/rubocop/cop/rbs/lint/redundant_overload_type_params.rb
67
+ - lib/rubocop/cop/rbs/lint/literal_intersection.rb
67
68
  - lib/rubocop/cop/rbs/lint/syntax.rb
68
- - lib/rubocop/cop/rbs/lint/type_params_arity.rb
69
+ - lib/rubocop/cop/rbs/lint/useless_overload_type_params.rb
69
70
  - lib/rubocop/cop/rbs/lint/will_syntax_error.rb
70
71
  - lib/rubocop/cop/rbs/style/block_return_boolish.rb
71
72
  - lib/rubocop/cop/rbs/style/classic_type.rb
72
73
  - lib/rubocop/cop/rbs/style/duplicated_type.rb
74
+ - lib/rubocop/cop/rbs/style/empty_argument.rb
73
75
  - lib/rubocop/cop/rbs/style/initialize_return_type.rb
74
- - lib/rubocop/cop/rbs/style/merge_untyped.rb
75
76
  - lib/rubocop/cop/rbs/style/optional_nil.rb
77
+ - lib/rubocop/cop/rbs/style/redundant_parentheses.rb
76
78
  - lib/rubocop/cop/rbs/style/true_false.rb
77
79
  - lib/rubocop/cop/rbs_cops.rb
78
80
  - lib/rubocop/rbs.rb
@@ -1,170 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module RBS
6
- module Lint
7
- # This cop checks the arity of type parameters arity.
8
- # You can add expect settings in your .rubocop.yml.
9
- #
10
- # @example Expects settings
11
- # RBS/Lint/TypeParamsArity:
12
- # Expects:
13
- # Your::Class: 1
14
- #
15
- # @example default
16
- # # bad
17
- # type a = Array[Integer, String, Symbol]
18
- #
19
- # # bad
20
- # class Foo
21
- # include Enumerable
22
- # end
23
- class TypeParamsArity < RuboCop::RBS::CopBase
24
- Types = ::RBS::Types
25
-
26
- def on_rbs_module(decl)
27
- check_type_params(decl)
28
- decl.self_types.each do |self_type|
29
- check(
30
- name: self_type.name,
31
- args: self_type.args,
32
- location: self_type.location
33
- )
34
- end
35
- check_each_mixin(decl)
36
- end
37
-
38
- def on_rbs_class(decl)
39
- check_type_params(decl)
40
- if decl.super_class
41
- check(
42
- name: decl.super_class.name,
43
- args: decl.super_class.args,
44
- location: decl.super_class.location
45
- )
46
- end
47
- check_each_mixin(decl)
48
- end
49
-
50
- def on_rbs_interface(decl)
51
- check_type_params(decl)
52
- check_each_mixin(decl)
53
- end
54
-
55
- def on_rbs_constant(const)
56
- check_type(const.type)
57
- end
58
-
59
- def on_rbs_global(global)
60
- check_type(global.type)
61
- end
62
-
63
- def on_rbs_type_alias(decl)
64
- check_type_params(decl)
65
- check_type(decl.type)
66
- decl.type.each_type do |type|
67
- check_type(type)
68
- end
69
- end
70
-
71
- def on_rbs_def(member)
72
- member.overloads.each do |overload|
73
- overload.method_type.each_type do |type|
74
- check_type(type)
75
- end
76
- end
77
- end
78
-
79
- def on_rbs_attribute(attr)
80
- check_type(attr.type)
81
- end
82
-
83
- def check_each_mixin(decl)
84
- decl.each_mixin do |mixin|
85
- check(
86
- name: mixin.name,
87
- args: mixin.args,
88
- location: mixin.location
89
- )
90
- end
91
- end
92
-
93
- def check_type_params(decl)
94
- decl.type_params.each do |type_param|
95
- if type_param.upper_bound
96
- check(
97
- name: type_param.upper_bound.name,
98
- args: type_param.upper_bound.args,
99
- location: type_param.upper_bound.location
100
- )
101
- end
102
- end
103
- end
104
-
105
- def check_type(type)
106
- case type
107
- when Types::Record,
108
- Types::Tuple,
109
- Types::Union,
110
- Types::Intersection,
111
- Types::Optional,
112
- Types::Proc
113
- type.each_type.each do |t|
114
- check_type(t)
115
- end
116
- when Types::Interface,
117
- Types::Alias,
118
- Types::ClassInstance
119
- check(
120
- name: type.name,
121
- args: type.args,
122
- location: type.location,
123
- )
124
- end
125
- end
126
-
127
- def check(name:, args:, location:)
128
- return unless name.absolute?
129
- return unless location
130
-
131
- expect_size = expects[name.to_s]
132
- return unless expect_size
133
- return unless expect_size != args.size
134
-
135
- message = if args.size == 0
136
- "Type `#{name}` is generic but used as a non generic type."
137
- else
138
- "Type `#{name}` expects #{expect_size} arguments, but #{args.size} arguments are given."
139
- end
140
- add_offense(
141
- location_to_range(location),
142
- message: message,
143
- severity: :error
144
- )
145
- end
146
-
147
- def expects
148
- @expects ||= begin
149
- expects = cop_config['Expects']
150
- raise "Expects must be a hash" unless expects.is_a?(Hash)
151
-
152
- unless expects.all? { |k, _| k.is_a?(String) }
153
- raise "[RBS/Lint/TypeParamsArity] Keys of Expects must be strings"
154
- end
155
- unless expects.all? { |_, v| v.is_a?(Integer) }
156
- raise "[RBS/Lint/TypeParamsArity] Values of Expects must be integers"
157
- end
158
-
159
- expects.transform_keys! do |k|
160
- k.start_with?('::') ? k : "::#{k}"
161
- end
162
-
163
- expects
164
- end
165
- end
166
- end
167
- end
168
- end
169
- end
170
- end
@@ -1,91 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module RBS
6
- module Style
7
- # @example default
8
- # # bad
9
- # def foo: (untyped?) -> untyped?
10
- #
11
- # # bad
12
- # def foo: (Integer | untyped) -> (Integer | untyped)
13
- #
14
- # # bad
15
- # def foo: (Integer & untyped) -> (Integer & untyped)
16
- #
17
- # # good
18
- # def foo: (untyped) -> untyped
19
- class MergeUntyped < RuboCop::RBS::CopBase
20
- extend AutoCorrector
21
-
22
- # @sig decl: ::RBS::AST::Members::MethodDefinition
23
- def on_rbs_def(decl)
24
- decl.overloads.each do |overload|
25
- overload.method_type.type.tap do |fun|
26
- fun.each_param do |param|
27
- check_type(param.type)
28
- end
29
- check_type(fun.return_type)
30
- end
31
- end
32
- end
33
-
34
- def check_type(type)
35
- find_replacement(type) do |method, t, replaced|
36
- case method
37
- when :replace
38
- range = location_to_range(t.location)
39
- add_offense(range, message: "Use `#{replaced}` instead of `#{t}`") do |corrector|
40
- corrector.replace(range, replaced.to_s)
41
- end
42
- when :remove
43
- range = t
44
- add_offense(range, message: "Remove `?` in Optional") do |corrector|
45
- corrector.remove(range)
46
- end
47
- end
48
- end
49
- end
50
-
51
- def find_replacement(type, &block)
52
- case type
53
- when ::RBS::Types::Optional
54
- case type.type
55
- when ::RBS::Types::Bases::Any,
56
- ::RBS::Types::Bases::Nil,
57
- ::RBS::Types::Bases::Void,
58
- ::RBS::Types::Bases::Top,
59
- ::RBS::Types::Bases::Bottom
60
- # untyped? => untyped
61
- block.call([:replace, type, type.type])
62
- when ::RBS::Types::Optional
63
- # (Integer?)? => Integer?
64
- range = Parser::Source::Range.new(processed_source.buffer, type.type.location.end_pos - 1,
65
- type.type.location.end_pos)
66
- block.call([:remove, range])
67
- find_replacement(type.type, &block)
68
- when ::RBS::Types::Union, ::RBS::Types::Intersection
69
- find_replacement(type.type, &block)
70
- end
71
- when ::RBS::Types::Union, ::RBS::Types::Intersection
72
- # (untyped | Integer) => untyped
73
- # (untyped & Integer) => untyped
74
- if type.types.any? { |t| t.is_a?(::RBS::Types::Bases::Any) }
75
- block.call([:replace, type, 'untyped'])
76
- end
77
-
78
- uniqed = type.types.uniq
79
- if uniqed.size < type.types.size
80
- block.call([:replace, type, type.class.new(types: uniqed, location: nil)])
81
- end
82
- type.types.each do |t|
83
- find_replacement(t, &block)
84
- end
85
- end
86
- end
87
- end
88
- end
89
- end
90
- end
91
- end