rubocop-sorbet 0.7.5 → 0.7.7

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: 9b2451806224baad5c72fb848ae38e6510037b2e26415afc236c3639f8504655
4
- data.tar.gz: e55c4a39d87a4fe345a6257e14483de155738ea5d39c25ef1e7822a2174321cb
3
+ metadata.gz: 8a1efe9f67422bb3173e5d5f91b3ccfd9f3862218af34495ca45e37be474ce6d
4
+ data.tar.gz: aeef803f94dd5084efa7d95cb1e899dd1e901b0a992acdb1e1bfe5b3613b78d7
5
5
  SHA512:
6
- metadata.gz: d05d0627ce52223c931f3461e221f6cb105838c21eeae6d68a7270934e6e292fcd2a7390453583c95d721bc1544125cb74f2d65ef6161c4d8fe823c3ee8217e6
7
- data.tar.gz: adf840bad5a49581286937604e83b3ee864f45031efb115db9faed9032da04d4178d7022b3d2040e08e8b10dc5f7a95bc8bf8a0ee1ac06ba74780b135d947b26
6
+ metadata.gz: 607f488db395a271ab0fe3997f710f1f275d04c62b0fdd00bfb3bf4b3ffbd0274315d65d284440078fe92415b3ba7b66f364de415af004ab45f745238081de31
7
+ data.tar.gz: d55d280a2c2404fe754bcb59445369b3c67c03329b4055700984e99effef6b6c53b7c44560925ee029f1a963649cbc65d30f49d30cb406fca7d92eafc83a6859
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rubocop-sorbet (0.7.5)
4
+ rubocop-sorbet (0.7.7)
5
5
  rubocop (>= 0.90.0)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -69,6 +69,14 @@ inherit_gem:
69
69
 
70
70
  This will turn off default cops for `**/*.rbi` files and enable the RBI specific cops.
71
71
 
72
+ You'll also need to add an entry to the main `.rubocop.yml` so that RBI files are included, e.g.:
73
+
74
+ ```yaml
75
+ AllCops:
76
+ Include:
77
+ - "sorbet/rbi/shims/**/*.rbi"
78
+ ```
79
+
72
80
  ## The Cops
73
81
  All cops are located under [`lib/rubocop/cop/sorbet`](lib/rubocop/cop/sorbet), and contain examples/documentation.
74
82
 
data/config/default.yml CHANGED
@@ -89,6 +89,11 @@ Sorbet/ForbidIncludeConstLiteral:
89
89
  VersionAdded: 0.2.0
90
90
  VersionChanged: 0.5.0
91
91
 
92
+ Sorbet/ForbidTypeAliasedShapes:
93
+ Description: 'Forbids defining type aliases that contain shapes'
94
+ Enabled: false
95
+ VersionAdded: 0.7.6
96
+
92
97
  Sorbet/ForbidSuperclassConstLiteral:
93
98
  Description: 'Forbid superclasses which are non-literal constants.'
94
99
  Enabled: false
@@ -288,3 +293,8 @@ Sorbet/ValidSigil:
288
293
  - bin/**/*
289
294
  - db/**/*.rb
290
295
  - script/**/*
296
+
297
+ Sorbet/VoidCheckedTests:
298
+ Description: 'Forbid `.void.checked(:tests)`'
299
+ Enabled: true
300
+ VersionAdded: 0.7.7
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+
5
+ module RuboCop
6
+ module Cop
7
+ module Sorbet
8
+ # Disallows defining type aliases that contain shapes
9
+ #
10
+ # @example
11
+ #
12
+ # # bad
13
+ # Foo = T.type_alias { { foo: Integer } }
14
+ #
15
+ # # good
16
+ # class Foo
17
+ # extend T::Sig
18
+ #
19
+ # sig { params(foo: Integer).void }
20
+ # def initialize(foo)
21
+ # @foo = foo
22
+ # end
23
+ # end
24
+ class ForbidTypeAliasedShapes < RuboCop::Cop::Base
25
+ MSG = "Type aliases shouldn't contain shapes because of significant performance overhead"
26
+
27
+ # @!method shape_type_alias?(node)
28
+ def_node_matcher(:shape_type_alias?, <<-PATTERN)
29
+ (block
30
+ (send (const {nil? cbase} :T) :type_alias)
31
+ (args)
32
+ `hash
33
+ )
34
+ PATTERN
35
+
36
+ def on_block(node)
37
+ add_offense(node) if shape_type_alias?(node)
38
+ end
39
+
40
+ alias_method :on_numblock, :on_block
41
+ end
42
+ end
43
+ end
44
+ end
@@ -23,11 +23,11 @@ module RuboCop
23
23
  # # good
24
24
  # sig { abstract.void }
25
25
  #
26
- # # bad
27
- # sig { returns(Integer).params(x: Integer) }
26
+ # # bad
27
+ # sig { returns(Integer).params(x: Integer) }
28
28
  #
29
- # # good
30
- # sig { params(x: Integer).returns(Integer) }
29
+ # # good
30
+ # sig { params(x: Integer).returns(Integer) }
31
31
  class SignatureBuildOrder < ::RuboCop::Cop::Cop # rubocop:todo InternalAffairs/InheritDeprecatedCopClass
32
32
  include SignatureHelp
33
33
 
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Sorbet
6
+ # Disallows the usage of `.void.checked(:tests)`.
7
+ #
8
+ # Using `.void` changes the value returned from the method, but only if
9
+ # runtime type checking is enabled for the method. Methods marked `.void`
10
+ # will return different values in tests compared with non-test
11
+ # environments. This is particularly troublesome if branching on the
12
+ # result of a `.void` method, because the returned value in test code
13
+ # will be the truthy `VOID` value, while the non-test return value may be
14
+ # falsy depending on the method's implementation.
15
+ #
16
+ # - Use `.returns(T.anything).checked(:tests)` to keep the runtime type
17
+ # checking for the rest of the parameters.
18
+ # - Use `.void.checked(:never)` if you are on an older version of Sorbet
19
+ # which does not have `T.anything` (meaning versions 0.5.10781 or
20
+ # earlier. Versions released after 2023-04-14 include `T.anything`.)
21
+ #
22
+ # @example
23
+ #
24
+ # # bad
25
+ # sig { void.checked(:tests) }
26
+ #
27
+ # # good
28
+ # sig { void }
29
+ # sig { returns(T.anything).checked(:tests) }
30
+ # sig { void.checked(:never) }
31
+ class VoidCheckedTests < ::RuboCop::Cop::Base
32
+ include(RuboCop::Cop::RangeHelp)
33
+ include(RuboCop::Cop::Sorbet::SignatureHelp)
34
+ extend AutoCorrector
35
+
36
+ # @!method checked_tests(node)
37
+ def_node_search(:checked_tests, <<~PATTERN)
38
+ ({csend send} _ :checked (sym :tests))
39
+ PATTERN
40
+
41
+ MESSAGE =
42
+ "Returning `.void` from a sig marked `.checked(:tests)` means that the " \
43
+ "method will return a different value in non-test environments (possibly " \
44
+ "with different truthiness). Either use `.returns(T.anything).checked(:tests)` " \
45
+ "to keep checking in tests, or `.void.checked(:never)` to leave it untouched."
46
+ private_constant(:MESSAGE)
47
+
48
+ private def top_level_void(node)
49
+ return unless node.is_a?(RuboCop::AST::SendNode)
50
+
51
+ if node.method?(:void)
52
+ node
53
+ elsif (recv = node.receiver)
54
+ top_level_void(recv)
55
+ end
56
+ end
57
+
58
+ def on_signature(node)
59
+ checked_send = checked_tests(node).first
60
+ return unless checked_send
61
+
62
+ if (parent = node.parent) && (sibling_index = node.sibling_index)
63
+ later_siblings = parent.children[(sibling_index + 1)..]
64
+ if (def_node = later_siblings.find { |sibling| sibling.is_a?(RuboCop::AST::DefNode) })
65
+ # Sorbet requires that `initialize` methods return `.void`
66
+ # (A stylistic convention which happens to be enforced by Sorbet)
67
+ return if def_node.method?(:initialize)
68
+ end
69
+ end
70
+
71
+ void_send = top_level_void(node.body)
72
+
73
+ return unless void_send
74
+
75
+ add_offense(
76
+ void_send.selector,
77
+ message: MESSAGE,
78
+ ) do |corrector|
79
+ corrector.replace(void_send.selector, "returns(T.anything)")
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -7,6 +7,7 @@ require_relative "sorbet/binding_constant_without_type_alias"
7
7
  require_relative "sorbet/constants_from_strings"
8
8
  require_relative "sorbet/forbid_superclass_const_literal"
9
9
  require_relative "sorbet/forbid_include_const_literal"
10
+ require_relative "sorbet/forbid_type_aliased_shapes"
10
11
  require_relative "sorbet/forbid_untyped_struct_props"
11
12
  require_relative "sorbet/implicit_conversion_method"
12
13
  require_relative "sorbet/one_ancestor_per_line"
@@ -25,6 +26,7 @@ require_relative "sorbet/rbi/single_line_rbi_class_module_definitions"
25
26
 
26
27
  require_relative "sorbet/signatures/allow_incompatible_override"
27
28
  require_relative "sorbet/signatures/checked_true_in_signature"
29
+ require_relative "sorbet/signatures/void_checked_tests"
28
30
  require_relative "sorbet/signatures/keyword_argument_ordering"
29
31
  require_relative "sorbet/signatures/signature_build_order"
30
32
  require_relative "sorbet/signatures/enforce_signatures"
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module Sorbet
5
- VERSION = "0.7.5"
5
+ VERSION = "0.7.7"
6
6
  end
7
7
  end
data/manual/cops.md CHANGED
@@ -23,6 +23,7 @@ In the following section you find all available cops:
23
23
  * [Sorbet/ForbidTStruct](cops_sorbet.md#sorbetforbidtstruct)
24
24
  * [Sorbet/ForbidTUnsafe](cops_sorbet.md#sorbetforbidtunsafe)
25
25
  * [Sorbet/ForbidTUntyped](cops_sorbet.md#sorbetforbidtuntyped)
26
+ * [Sorbet/ForbidTypeAliasedShapes](cops_sorbet.md#sorbetforbidtypealiasedshapes)
26
27
  * [Sorbet/ForbidUntypedStructProps](cops_sorbet.md#sorbetforbiduntypedstructprops)
27
28
  * [Sorbet/HasSigil](cops_sorbet.md#sorbethassigil)
28
29
  * [Sorbet/IgnoreSigil](cops_sorbet.md#sorbetignoresigil)
@@ -38,6 +39,7 @@ In the following section you find all available cops:
38
39
  * [Sorbet/TrueSigil](cops_sorbet.md#sorbettruesigil)
39
40
  * [Sorbet/TypeAliasName](cops_sorbet.md#sorbettypealiasname)
40
41
  * [Sorbet/ValidSigil](cops_sorbet.md#sorbetvalidsigil)
42
+ * [Sorbet/VoidCheckedTests](cops_sorbet.md#sorbetvoidcheckedtests)
41
43
 
42
44
  <!-- END_COP_LIST -->
43
45
 
@@ -496,6 +496,31 @@ sig { params(my_argument: String).void }
496
496
  def foo(my_argument); end
497
497
  ```
498
498
 
499
+ ## Sorbet/ForbidTypeAliasedShapes
500
+
501
+ Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
502
+ --- | --- | --- | --- | ---
503
+ Disabled | Yes | No | 0.7.6 | -
504
+
505
+ Disallows defining type aliases that contain shapes
506
+
507
+ ### Examples
508
+
509
+ ```ruby
510
+ # bad
511
+ Foo = T.type_alias { { foo: Integer } }
512
+
513
+ # good
514
+ class Foo
515
+ extend T::Sig
516
+
517
+ sig { params(foo: Integer).void }
518
+ def initialize(foo)
519
+ @foo = foo
520
+ end
521
+ end
522
+ ```
523
+
499
524
  ## Sorbet/ForbidUntypedStructProps
500
525
 
501
526
  Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
@@ -715,12 +740,6 @@ Checks for the correct order of sig builder methods:
715
740
  - returns, or void
716
741
  - soft, checked, or on_failure
717
742
 
718
- # bad
719
- sig { returns(Integer).params(x: Integer) }
720
-
721
- # good
722
- sig { params(x: Integer).returns(Integer) }
723
-
724
743
  ### Examples
725
744
 
726
745
  ```ruby
@@ -729,6 +748,12 @@ sig { void.abstract }
729
748
 
730
749
  # good
731
750
  sig { abstract.void }
751
+
752
+ # bad
753
+ sig { returns(Integer).params(x: Integer) }
754
+
755
+ # good
756
+ sig { params(x: Integer).returns(Integer) }
732
757
  ```
733
758
 
734
759
  ## Sorbet/SingleLineRbiClassModuleDefinitions
@@ -859,3 +884,37 @@ MinimumStrictness | `nil` | String
859
884
  ExactStrictness | `nil` | String
860
885
  Include | `**/*.{rb,rbi,rake,ru}` | Array
861
886
  Exclude | `bin/**/*`, `db/**/*.rb`, `script/**/*` | Array
887
+
888
+ ## Sorbet/VoidCheckedTests
889
+
890
+ Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
891
+ --- | --- | --- | --- | ---
892
+ Enabled | Yes | Yes | 0.7.7 | -
893
+
894
+ Disallows the usage of `.void.checked(:tests)`.
895
+
896
+ Using `.void` changes the value returned from the method, but only if
897
+ runtime type checking is enabled for the method. Methods marked `.void`
898
+ will return different values in tests compared with non-test
899
+ environments. This is particularly troublesome if branching on the
900
+ result of a `.void` method, because the returned value in test code
901
+ will be the truthy `VOID` value, while the non-test return value may be
902
+ falsy depending on the method's implementation.
903
+
904
+ - Use `.returns(T.anything).checked(:tests)` to keep the runtime type
905
+ checking for the rest of the parameters.
906
+ - Use `.void.checked(:never)` if you are on an older version of Sorbet
907
+ which does not have `T.anything` (meaning versions 0.5.10781 or
908
+ earlier. Versions released after 2023-04-14 include `T.anything`.)
909
+
910
+ ### Examples
911
+
912
+ ```ruby
913
+ # bad
914
+ sig { void.checked(:tests) }
915
+
916
+ # good
917
+ sig { void }
918
+ sig { returns(T.anything).checked(:tests) }
919
+ sig { void.checked(:never) }
920
+ ```
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.7.5
4
+ version: 0.7.7
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: 2023-10-31 00:00:00.000000000 Z
14
+ date: 2024-02-09 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rspec
@@ -95,6 +95,7 @@ files:
95
95
  - lib/rubocop/cop/sorbet/forbid_t_struct.rb
96
96
  - lib/rubocop/cop/sorbet/forbid_t_unsafe.rb
97
97
  - lib/rubocop/cop/sorbet/forbid_t_untyped.rb
98
+ - lib/rubocop/cop/sorbet/forbid_type_aliased_shapes.rb
98
99
  - lib/rubocop/cop/sorbet/forbid_untyped_struct_props.rb
99
100
  - lib/rubocop/cop/sorbet/implicit_conversion_method.rb
100
101
  - lib/rubocop/cop/sorbet/mixin/signature_help.rb
@@ -121,6 +122,7 @@ files:
121
122
  - lib/rubocop/cop/sorbet/signatures/enforce_signatures.rb
122
123
  - lib/rubocop/cop/sorbet/signatures/keyword_argument_ordering.rb
123
124
  - lib/rubocop/cop/sorbet/signatures/signature_build_order.rb
125
+ - lib/rubocop/cop/sorbet/signatures/void_checked_tests.rb
124
126
  - lib/rubocop/cop/sorbet/type_alias_name.rb
125
127
  - lib/rubocop/cop/sorbet_cops.rb
126
128
  - lib/rubocop/sorbet.rb
@@ -154,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
154
156
  - !ruby/object:Gem::Version
155
157
  version: '0'
156
158
  requirements: []
157
- rubygems_version: 3.4.21
159
+ rubygems_version: 3.5.6
158
160
  signing_key:
159
161
  specification_version: 4
160
162
  summary: Automatic Sorbet code style checking tool.