rubocop-sorbet 0.7.5 → 0.7.7
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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +8 -0
- data/config/default.yml +10 -0
- data/lib/rubocop/cop/sorbet/forbid_type_aliased_shapes.rb +44 -0
- data/lib/rubocop/cop/sorbet/signatures/signature_build_order.rb +4 -4
- data/lib/rubocop/cop/sorbet/signatures/void_checked_tests.rb +85 -0
- data/lib/rubocop/cop/sorbet_cops.rb +2 -0
- data/lib/rubocop/sorbet/version.rb +1 -1
- data/manual/cops.md +2 -0
- data/manual/cops_sorbet.md +65 -6
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a1efe9f67422bb3173e5d5f91b3ccfd9f3862218af34495ca45e37be474ce6d
|
4
|
+
data.tar.gz: aeef803f94dd5084efa7d95cb1e899dd1e901b0a992acdb1e1bfe5b3613b78d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 607f488db395a271ab0fe3997f710f1f275d04c62b0fdd00bfb3bf4b3ffbd0274315d65d284440078fe92415b3ba7b66f364de415af004ab45f745238081de31
|
7
|
+
data.tar.gz: d55d280a2c2404fe754bcb59445369b3c67c03329b4055700984e99effef6b6c53b7c44560925ee029f1a963649cbc65d30f49d30cb406fca7d92eafc83a6859
|
data/Gemfile.lock
CHANGED
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
|
-
#
|
27
|
-
#
|
26
|
+
# # bad
|
27
|
+
# sig { returns(Integer).params(x: Integer) }
|
28
28
|
#
|
29
|
-
#
|
30
|
-
#
|
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"
|
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
|
|
data/manual/cops_sorbet.md
CHANGED
@@ -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.
|
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:
|
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.
|
159
|
+
rubygems_version: 3.5.6
|
158
160
|
signing_key:
|
159
161
|
specification_version: 4
|
160
162
|
summary: Automatic Sorbet code style checking tool.
|