rubocop-on-rbs 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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