rubocop-sorbet 0.8.1 → 0.8.2

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: d0993b56c619f271efe5948d6a3b090695290b91d55db8948b95cf690c610cbf
4
- data.tar.gz: 0f69733c05f1391747711ee316152b6541800a35682b71482d50903c8981bfdc
3
+ metadata.gz: 1cf8cfdff3aedba93731774d5f47fd8c4f10ef8d615ea2cb9f4cdfd2f20d1522
4
+ data.tar.gz: 69b6974d9a6de86eeed4b29dcfcae25648a3880036b49ceb57a426821da4535c
5
5
  SHA512:
6
- metadata.gz: aa9413ff649b22b1afab51d3e6f8c48cfb1387ff52a0d3e8547db70c42824d9d2e0da53e093b79fb57f916d07100b655368831bf23abe12c69371281185faab9
7
- data.tar.gz: 8cffb6fdef999a34b5f0c92ec7c2712b993f7851b8d7cb7c9ae7c9e764bd132f4d25b3bb733bb31facfb38cc17e62cbe042ac77aee92e74df093a20e56f5c7d4
6
+ metadata.gz: 98a957ed012dcfefb642d54ee332d1435c0931bafe6fa07e2d36d280b7a1c4391bab2f05d2b77b1f44da850196a7edb322886b0d50bbe154e0e6d9d80a9f8f62
7
+ data.tar.gz: 25634e48e2daf8db8b41211d64f49560f9ddcd7236cc181364e7ab6ecc67cbdcd5d169454825a92ffebb2e6337ed81c1847d54483f0a073447034333c2b4b150
data/Gemfile CHANGED
@@ -5,7 +5,7 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in rubocop-sorbet.gemspec
6
6
  gemspec
7
7
 
8
- gem "byebug"
8
+ gem "debug"
9
9
  gem "rake", ">= 12.3.3"
10
10
  gem "rspec", "~> 3.13"
11
11
  gem "rubocop-shopify", require: false
data/Gemfile.lock CHANGED
@@ -1,25 +1,37 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rubocop-sorbet (0.8.1)
4
+ rubocop-sorbet (0.8.2)
5
5
  rubocop (>= 0.90.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
10
  ast (2.4.2)
11
- byebug (11.1.3)
11
+ debug (1.9.2)
12
+ irb (~> 1.10)
13
+ reline (>= 0.3.8)
12
14
  diff-lcs (1.5.1)
13
- json (2.7.1)
15
+ io-console (0.7.2)
16
+ irb (1.12.0)
17
+ rdoc
18
+ reline (>= 0.4.2)
19
+ json (2.7.2)
14
20
  language_server-protocol (3.17.0.3)
15
21
  parallel (1.24.0)
16
22
  parser (3.3.0.5)
17
23
  ast (~> 2.4.1)
18
24
  racc
25
+ psych (5.1.2)
26
+ stringio
19
27
  racc (1.7.3)
20
28
  rainbow (3.1.1)
21
29
  rake (13.2.1)
30
+ rdoc (6.6.3.1)
31
+ psych (>= 4.0.0)
22
32
  regexp_parser (2.9.0)
33
+ reline (0.5.1)
34
+ io-console (~> 0.5)
23
35
  rexml (3.2.6)
24
36
  rspec (3.13.0)
25
37
  rspec-core (~> 3.13.0)
@@ -34,7 +46,7 @@ GEM
34
46
  diff-lcs (>= 1.2.0, < 2.0)
35
47
  rspec-support (~> 3.13.0)
36
48
  rspec-support (3.13.1)
37
- rubocop (1.62.1)
49
+ rubocop (1.63.2)
38
50
  json (~> 2.3)
39
51
  language_server-protocol (>= 3.17.0)
40
52
  parallel (~> 1.10)
@@ -47,9 +59,10 @@ GEM
47
59
  unicode-display_width (>= 2.4.0, < 3.0)
48
60
  rubocop-ast (1.31.2)
49
61
  parser (>= 3.3.0.4)
50
- rubocop-shopify (2.14.0)
62
+ rubocop-shopify (2.15.1)
51
63
  rubocop (~> 1.51)
52
64
  ruby-progressbar (1.13.0)
65
+ stringio (3.1.0)
53
66
  unicode-display_width (2.5.0)
54
67
  yard (0.9.36)
55
68
 
@@ -57,7 +70,7 @@ PLATFORMS
57
70
  ruby
58
71
 
59
72
  DEPENDENCIES
60
- byebug
73
+ debug
61
74
  rake (>= 12.3.3)
62
75
  rspec (~> 3.13)
63
76
  rubocop-shopify
data/config/default.yml CHANGED
@@ -200,11 +200,6 @@ Sorbet/BuggyObsoleteStrictMemoization:
200
200
  Safe: true
201
201
  SafeAutoCorrect: false
202
202
 
203
- Sorbet/OneAncestorPerLine:
204
- Description: 'Enforces one ancestor per call to requires_ancestor'
205
- Enabled: false
206
- VersionAdded: '0.6.0'
207
-
208
203
  Sorbet/RedundantExtendTSig:
209
204
  Description: >-
210
205
  Forbid the usage of redundant `extend T::Sig`.
@@ -312,3 +307,13 @@ Sorbet/VoidCheckedTests:
312
307
  Description: 'Forbid `.void.checked(:tests)`'
313
308
  Enabled: true
314
309
  VersionAdded: 0.7.7
310
+
311
+ Sorbet/MultipleTEnumValues:
312
+ Description: 'Ensures that all `T::Enum`s have multiple values.'
313
+ Enabled: true
314
+ VersionAdded: 0.8.2
315
+
316
+ Sorbet/ForbidComparableTEnum:
317
+ Description: 'Disallows including the `Comparable` module in a `T::Enum`.'
318
+ Enabled: true
319
+ VersionAdded: 0.8.2
@@ -3,4 +3,6 @@
3
3
  #
4
4
  # See: https://docs.rubocop.org/rubocop/extensions.html#config-obsoletions
5
5
  #
6
- {}
6
+ removed:
7
+ Sorbet/OneAncestorPerLine:
8
+ reason: '`require_ancestor` now takes a block instead of arguments'
@@ -48,8 +48,8 @@ module RuboCop
48
48
 
49
49
  include TargetSorbetVersion
50
50
 
51
- MSG = "This might be a mistaken variant of the two-stage workaround that used to be needed for memoization in "\
52
- "`#typed: strict` files. See https://sorbet.org/docs/type-assertions#put-type-assertions-behind-memoization."
51
+ MSG = "This might be a mistaken variant of the two-stage workaround that used to be needed for memoization " \
52
+ "in `#typed: strict` files. See https://sorbet.org/docs/type-assertions#put-type-assertions-behind-memoization."
53
53
 
54
54
  # @!method buggy_legacy_memoization_pattern?(node)
55
55
  def_node_matcher :buggy_legacy_memoization_pattern?, <<~PATTERN
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Sorbet
6
+ # Mixing for writing cops that deal with `T::Enum`s
7
+ module TEnum
8
+ extend RuboCop::NodePattern::Macros
9
+ def initialize(*)
10
+ @scopes = []
11
+ super
12
+ end
13
+
14
+ # @!method t_enum?(node)
15
+ def_node_matcher :t_enum?, <<~PATTERN
16
+ (class (const...) (const (const nil? :T) :Enum) ...)
17
+ PATTERN
18
+
19
+ def on_class(node)
20
+ @scopes.push(node)
21
+ end
22
+
23
+ def after_class(node)
24
+ @scopes.pop
25
+ end
26
+
27
+ private
28
+
29
+ def in_t_enum_class?
30
+ t_enum?(@scopes&.last)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Sorbet
6
+ # Disallow including the `Comparable` module in `T::Enum`.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # class Priority < T::Enum
12
+ # include Comparable
13
+ #
14
+ # enums do
15
+ # High = new(3)
16
+ # Medium = new(2)
17
+ # Low = new(1)
18
+ # end
19
+ #
20
+ # def <=>(other)
21
+ # serialize <=> other.serialize
22
+ # end
23
+ # end
24
+ class ForbidComparableTEnum < Base
25
+ include TEnum
26
+
27
+ MSG = "Do not use `T::Enum` as a comparable object because of significant performance overhead."
28
+
29
+ RESTRICT_ON_SEND = [:include, :prepend].freeze
30
+
31
+ # @!method mix_in_comparable?(node)
32
+ def_node_matcher :mix_in_comparable?, <<~PATTERN
33
+ (send nil? {:include | :prepend} (const nil? :Comparable))
34
+ PATTERN
35
+
36
+ def on_send(node)
37
+ return unless in_t_enum_class? && mix_in_comparable?(node)
38
+
39
+ add_offense(node)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Sorbet
6
+ # Disallow creating a `T::Enum` with less than two values.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # class ErrorMessages < T::Enum
12
+ # enums do
13
+ # ServerError = new("There was a server error.")
14
+ # end
15
+ # end
16
+ #
17
+ # # good
18
+ # class ErrorMessages < T::Enum
19
+ # enums do
20
+ # ServerError = new("There was a server error.")
21
+ # NotFound = new("The resource was not found.")
22
+ # end
23
+ # end
24
+ class MultipleTEnumValues < Base
25
+ include TEnum
26
+
27
+ MSG = "`T::Enum` should have at least two values."
28
+
29
+ # @!method enums_block?(node)
30
+ def_node_matcher :enums_block?, <<~PATTERN
31
+ (block (send nil? :enums) ...)
32
+ PATTERN
33
+
34
+ def on_class(node)
35
+ super
36
+
37
+ add_offense(node) if t_enum?(node) && node.body.nil?
38
+ end
39
+
40
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
41
+ return unless in_t_enum_class?
42
+ return unless enums_block?(node)
43
+
44
+ scope = @scopes.last
45
+
46
+ if node.body.nil?
47
+ add_offense(scope)
48
+ return
49
+ end
50
+
51
+ begin_node = node.children.find(&:begin_type?)
52
+
53
+ num_casgn_nodes = (begin_node || node).children.count(&:casgn_type?)
54
+ add_offense(scope) if num_casgn_nodes < 2
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "sorbet/mixin/target_sorbet_version.rb"
4
- require_relative "sorbet/mixin/signature_help.rb"
3
+ require_relative "sorbet/mixin/target_sorbet_version"
4
+ require_relative "sorbet/mixin/t_enum"
5
+ require_relative "sorbet/mixin/signature_help"
5
6
 
6
7
  require_relative "sorbet/binding_constant_without_type_alias"
7
8
  require_relative "sorbet/constants_from_strings"
@@ -10,7 +11,6 @@ require_relative "sorbet/forbid_include_const_literal"
10
11
  require_relative "sorbet/forbid_type_aliased_shapes"
11
12
  require_relative "sorbet/forbid_untyped_struct_props"
12
13
  require_relative "sorbet/implicit_conversion_method"
13
- require_relative "sorbet/one_ancestor_per_line"
14
14
  require_relative "sorbet/callback_conditionals_binding"
15
15
  require_relative "sorbet/forbid_t_struct"
16
16
  require_relative "sorbet/forbid_t_unsafe"
@@ -42,4 +42,7 @@ require_relative "sorbet/sigils/strong_sigil"
42
42
  require_relative "sorbet/sigils/enforce_sigil_order"
43
43
  require_relative "sorbet/sigils/enforce_single_sigil"
44
44
 
45
+ require_relative "sorbet/t_enum/forbid_comparable_t_enum"
46
+ require_relative "sorbet/t_enum/multiple_t_enum_values"
47
+
45
48
  require_relative "sorbet/mutable_constant_sorbet_aware_behaviour"
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module Sorbet
5
- VERSION = "0.8.1"
5
+ VERSION = "0.8.2"
6
6
  end
7
7
  end
data/manual/cops.md CHANGED
@@ -16,6 +16,7 @@ In the following section you find all available cops:
16
16
  * [Sorbet/EnforceSignatures](cops_sorbet.md#sorbetenforcesignatures)
17
17
  * [Sorbet/EnforceSingleSigil](cops_sorbet.md#sorbetenforcesinglesigil)
18
18
  * [Sorbet/FalseSigil](cops_sorbet.md#sorbetfalsesigil)
19
+ * [Sorbet/ForbidComparableTEnum](cops_sorbet.md#sorbetforbidcomparabletenum)
19
20
  * [Sorbet/ForbidExtendTSigHelpersInShims](cops_sorbet.md#sorbetforbidextendtsighelpersinshims)
20
21
  * [Sorbet/ForbidIncludeConstLiteral](cops_sorbet.md#sorbetforbidincludeconstliteral)
21
22
  * [Sorbet/ForbidRBIOutsideOfAllowedPaths](cops_sorbet.md#sorbetforbidrbioutsideofallowedpaths)
@@ -29,8 +30,8 @@ In the following section you find all available cops:
29
30
  * [Sorbet/IgnoreSigil](cops_sorbet.md#sorbetignoresigil)
30
31
  * [Sorbet/ImplicitConversionMethod](cops_sorbet.md#sorbetimplicitconversionmethod)
31
32
  * [Sorbet/KeywordArgumentOrdering](cops_sorbet.md#sorbetkeywordargumentordering)
33
+ * [Sorbet/MultipleTEnumValues](cops_sorbet.md#sorbetmultipletenumvalues)
32
34
  * [Sorbet/ObsoleteStrictMemoization](cops_sorbet.md#sorbetobsoletestrictmemoization)
33
- * [Sorbet/OneAncestorPerLine](cops_sorbet.md#sorbetoneancestorperline)
34
35
  * [Sorbet/RedundantExtendTSig](cops_sorbet.md#sorbetredundantextendtsig)
35
36
  * [Sorbet/SignatureBuildOrder](cops_sorbet.md#sorbetsignaturebuildorder)
36
37
  * [Sorbet/SingleLineRbiClassModuleDefinitions](cops_sorbet.md#sorbetsinglelinerbiclassmoduledefinitions)
@@ -295,6 +295,33 @@ SuggestedStrictness | `false` | String
295
295
  Include | `**/*.{rb,rbi,rake,ru}` | Array
296
296
  Exclude | `bin/**/*`, `db/**/*.rb`, `script/**/*` | Array
297
297
 
298
+ ## Sorbet/ForbidComparableTEnum
299
+
300
+ Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
301
+ --- | --- | --- | --- | ---
302
+ Enabled | Yes | No | 0.8.2 | -
303
+
304
+ Disallow including the `Comparable` module in `T::Enum`.
305
+
306
+ ### Examples
307
+
308
+ ```ruby
309
+ # bad
310
+ class Priority < T::Enum
311
+ include Comparable
312
+
313
+ enums do
314
+ High = new(3)
315
+ Medium = new(2)
316
+ Low = new(1)
317
+ end
318
+
319
+ def <=>(other)
320
+ serialize <=> other.serialize
321
+ end
322
+ end
323
+ ```
324
+
298
325
  ## Sorbet/ForbidExtendTSigHelpersInShims
299
326
 
300
327
  Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
@@ -639,6 +666,33 @@ sig { params(b: String, a: Integer).void }
639
666
  def foo(b:, a: 1); end
640
667
  ```
641
668
 
669
+ ## Sorbet/MultipleTEnumValues
670
+
671
+ Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
672
+ --- | --- | --- | --- | ---
673
+ Enabled | Yes | No | 0.8.2 | -
674
+
675
+ Disallow creating a `T::Enum` with less than two values.
676
+
677
+ ### Examples
678
+
679
+ ```ruby
680
+ # bad
681
+ class ErrorMessages < T::Enum
682
+ enums do
683
+ ServerError = new("There was a server error.")
684
+ end
685
+ end
686
+
687
+ # good
688
+ class ErrorMessages < T::Enum
689
+ enums do
690
+ ServerError = new("There was a server error.")
691
+ NotFound = new("The resource was not found.")
692
+ end
693
+ end
694
+ ```
695
+
642
696
  ## Sorbet/ObsoleteStrictMemoization
643
697
 
644
698
  Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
@@ -676,30 +730,6 @@ def foo
676
730
  end
677
731
  ```
678
732
 
679
- ## Sorbet/OneAncestorPerLine
680
-
681
- Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
682
- --- | --- | --- | --- | ---
683
- Disabled | Yes | Yes | 0.6.0 | -
684
-
685
- Ensures one ancestor per requires_ancestor line
686
- rather than chaining them as a comma-separated list.
687
-
688
- ### Examples
689
-
690
- ```ruby
691
- # bad
692
- module SomeModule
693
- requires_ancestor Kernel, Minitest::Assertions
694
- end
695
-
696
- # good
697
- module SomeModule
698
- requires_ancestor Kernel
699
- requires_ancestor Minitest::Assertions
700
- end
701
- ```
702
-
703
733
  ## Sorbet/RedundantExtendTSig
704
734
 
705
735
  Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-sorbet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ufuk Kayserilioglu
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2024-04-09 00:00:00.000000000 Z
14
+ date: 2024-04-23 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rubocop
@@ -74,10 +74,10 @@ files:
74
74
  - lib/rubocop/cop/sorbet/forbid_untyped_struct_props.rb
75
75
  - lib/rubocop/cop/sorbet/implicit_conversion_method.rb
76
76
  - lib/rubocop/cop/sorbet/mixin/signature_help.rb
77
+ - lib/rubocop/cop/sorbet/mixin/t_enum.rb
77
78
  - lib/rubocop/cop/sorbet/mixin/target_sorbet_version.rb
78
79
  - lib/rubocop/cop/sorbet/mutable_constant_sorbet_aware_behaviour.rb
79
80
  - lib/rubocop/cop/sorbet/obsolete_strict_memoization.rb
80
- - lib/rubocop/cop/sorbet/one_ancestor_per_line.rb
81
81
  - lib/rubocop/cop/sorbet/rbi/forbid_extend_t_sig_helpers_in_shims.rb
82
82
  - lib/rubocop/cop/sorbet/rbi/forbid_rbi_outside_of_allowed_paths.rb
83
83
  - lib/rubocop/cop/sorbet/rbi/single_line_rbi_class_module_definitions.rb
@@ -98,6 +98,8 @@ files:
98
98
  - lib/rubocop/cop/sorbet/signatures/keyword_argument_ordering.rb
99
99
  - lib/rubocop/cop/sorbet/signatures/signature_build_order.rb
100
100
  - lib/rubocop/cop/sorbet/signatures/void_checked_tests.rb
101
+ - lib/rubocop/cop/sorbet/t_enum/forbid_comparable_t_enum.rb
102
+ - lib/rubocop/cop/sorbet/t_enum/multiple_t_enum_values.rb
101
103
  - lib/rubocop/cop/sorbet/type_alias_name.rb
102
104
  - lib/rubocop/cop/sorbet_cops.rb
103
105
  - lib/rubocop/sorbet.rb
@@ -131,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
133
  - !ruby/object:Gem::Version
132
134
  version: '0'
133
135
  requirements: []
134
- rubygems_version: 3.5.7
136
+ rubygems_version: 3.5.9
135
137
  signing_key:
136
138
  specification_version: 4
137
139
  summary: Automatic Sorbet code style checking tool.
@@ -1,80 +0,0 @@
1
- # encoding: utf-8
2
- # frozen_string_literal: true
3
-
4
- require "rubocop"
5
-
6
- module RuboCop
7
- module Cop
8
- module Sorbet
9
- # Ensures one ancestor per requires_ancestor line
10
- # rather than chaining them as a comma-separated list.
11
- #
12
- # @example
13
- #
14
- # # bad
15
- # module SomeModule
16
- # requires_ancestor Kernel, Minitest::Assertions
17
- # end
18
- #
19
- # # good
20
- # module SomeModule
21
- # requires_ancestor Kernel
22
- # requires_ancestor Minitest::Assertions
23
- # end
24
- class OneAncestorPerLine < RuboCop::Cop::Cop # rubocop:todo InternalAffairs/InheritDeprecatedCopClass
25
- MSG = "Cannot require more than one ancestor per line"
26
-
27
- # @!method requires_ancestors(node)
28
- def_node_search :requires_ancestors, <<~PATTERN
29
- (send nil? :requires_ancestor ...)
30
- PATTERN
31
-
32
- # @!method more_than_one_ancestor(node)
33
- def_node_matcher :more_than_one_ancestor, <<~PATTERN
34
- (send nil? :requires_ancestor const const+)
35
- PATTERN
36
-
37
- # @!method abstract?(node)
38
- def_node_search :abstract?, <<~PATTERN
39
- (send nil? :abstract!)
40
- PATTERN
41
-
42
- def on_module(node)
43
- return unless node.body
44
- return unless requires_ancestors(node)
45
-
46
- process_node(node)
47
- end
48
-
49
- def on_class(node)
50
- return unless abstract?(node)
51
- return unless requires_ancestors(node)
52
-
53
- process_node(node)
54
- end
55
-
56
- def autocorrect(node)
57
- ->(corrector) do
58
- ra_call = node.parent
59
- split_ra_calls = ra_call.source.gsub(/,\s+/, new_ra_line(ra_call.loc.column))
60
- corrector.replace(ra_call, split_ra_calls)
61
- end
62
- end
63
-
64
- private
65
-
66
- def process_node(node)
67
- requires_ancestors(node).each do |ra|
68
- add_offense(ra.child_nodes[1]) if more_than_one_ancestor(ra)
69
- end
70
- end
71
-
72
- def new_ra_line(indent_count)
73
- indents = " " * indent_count
74
- indented_ra_call = "#{indents}requires_ancestor "
75
- "\n#{indented_ra_call}"
76
- end
77
- end
78
- end
79
- end
80
- end