rubocop-sorbet 0.7.6 → 0.7.8
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 +2 -2
- data/README.md +8 -0
- data/config/default.yml +5 -0
- data/lib/rubocop/cop/sorbet/forbid_t_struct.rb +35 -3
- 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 +1 -0
- data/lib/rubocop/sorbet/version.rb +1 -1
- data/manual/cops.md +1 -0
- data/manual/cops_sorbet.md +40 -6
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 68f2d0d8c272caa3933e34350356e99c32e0ec42bec4b43a39c748ef2422d048
|
4
|
+
data.tar.gz: c0bd1e275d17d85ff1a6f63ab0bad42f47e5f3f17480ac4d06e5d70f4f52973d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8746cfe46cc7c1f7ecc6f4310c21a725b34172168de624a02485c890b5441948e26fc4617b488365a055fa3d44ee2193a5eb41ab0c4423d06d3cea8d058ccb55
|
7
|
+
data.tar.gz: e32a6b29d524cbb963c69ba8bb7bbb6b8535ac9793c0ff80db7817aa9ce751e4a6d82161f50a2942fd3a0c17e61c70954bf4406718430cb72167564963348452
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rubocop-sorbet (0.7.
|
4
|
+
rubocop-sorbet (0.7.8)
|
5
5
|
rubocop (>= 0.90.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -54,7 +54,7 @@ GEM
|
|
54
54
|
unparser (0.6.0)
|
55
55
|
diff-lcs (~> 1.3)
|
56
56
|
parser (>= 3.0.0)
|
57
|
-
yard (0.9.
|
57
|
+
yard (0.9.36)
|
58
58
|
|
59
59
|
PLATFORMS
|
60
60
|
ruby
|
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
@@ -102,7 +102,7 @@ module RuboCop
|
|
102
102
|
end
|
103
103
|
|
104
104
|
class Property
|
105
|
-
attr_reader :node, :kind, :name, :
|
105
|
+
attr_reader :node, :kind, :name, :default, :factory
|
106
106
|
|
107
107
|
def initialize(node, kind, name, type, default:, factory:)
|
108
108
|
@node = node
|
@@ -151,6 +151,11 @@ module RuboCop
|
|
151
151
|
def nilable?
|
152
152
|
type.start_with?("T.nilable(")
|
153
153
|
end
|
154
|
+
|
155
|
+
def type
|
156
|
+
copy = @type.gsub(/[[:space:]]+/, "").strip # Remove newlines and spaces
|
157
|
+
copy.gsub(",", ", ") # Add a space after each comma
|
158
|
+
end
|
154
159
|
end
|
155
160
|
|
156
161
|
# @!method t_struct?(node)
|
@@ -215,8 +220,35 @@ module RuboCop
|
|
215
220
|
sorted_props = props.sort_by { |prop| prop.default || prop.factory || prop.nilable? ? 1 : 0 }
|
216
221
|
|
217
222
|
string = +"\n"
|
218
|
-
|
219
|
-
|
223
|
+
|
224
|
+
line = "#{indent}sig { params(#{sorted_props.map(&:initialize_sig_param).join(", ")}).void }\n"
|
225
|
+
if line.length <= max_line_length
|
226
|
+
string << line
|
227
|
+
else
|
228
|
+
string << "#{indent}sig do\n"
|
229
|
+
string << "#{indent} params(\n"
|
230
|
+
sorted_props.each do |prop|
|
231
|
+
string << "#{indent} #{prop.initialize_sig_param}"
|
232
|
+
string << "," if prop != sorted_props.last
|
233
|
+
string << "\n"
|
234
|
+
end
|
235
|
+
string << "#{indent} ).void\n"
|
236
|
+
string << "#{indent}end\n"
|
237
|
+
end
|
238
|
+
|
239
|
+
line = "#{indent}def initialize(#{sorted_props.map(&:initialize_param).join(", ")})\n"
|
240
|
+
if line.length <= max_line_length
|
241
|
+
string << line
|
242
|
+
else
|
243
|
+
string << "#{indent}def initialize(\n"
|
244
|
+
sorted_props.each do |prop|
|
245
|
+
string << "#{indent} #{prop.initialize_param}"
|
246
|
+
string << "," if prop != sorted_props.last
|
247
|
+
string << "\n"
|
248
|
+
end
|
249
|
+
string << "#{indent})\n"
|
250
|
+
end
|
251
|
+
|
220
252
|
props.each do |prop|
|
221
253
|
string << "#{indent} #{prop.initialize_assign}\n"
|
222
254
|
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
|
@@ -26,6 +26,7 @@ require_relative "sorbet/rbi/single_line_rbi_class_module_definitions"
|
|
26
26
|
|
27
27
|
require_relative "sorbet/signatures/allow_incompatible_override"
|
28
28
|
require_relative "sorbet/signatures/checked_true_in_signature"
|
29
|
+
require_relative "sorbet/signatures/void_checked_tests"
|
29
30
|
require_relative "sorbet/signatures/keyword_argument_ordering"
|
30
31
|
require_relative "sorbet/signatures/signature_build_order"
|
31
32
|
require_relative "sorbet/signatures/enforce_signatures"
|
data/manual/cops.md
CHANGED
@@ -39,6 +39,7 @@ In the following section you find all available cops:
|
|
39
39
|
* [Sorbet/TrueSigil](cops_sorbet.md#sorbettruesigil)
|
40
40
|
* [Sorbet/TypeAliasName](cops_sorbet.md#sorbettypealiasname)
|
41
41
|
* [Sorbet/ValidSigil](cops_sorbet.md#sorbetvalidsigil)
|
42
|
+
* [Sorbet/VoidCheckedTests](cops_sorbet.md#sorbetvoidcheckedtests)
|
42
43
|
|
43
44
|
<!-- END_COP_LIST -->
|
44
45
|
|
data/manual/cops_sorbet.md
CHANGED
@@ -740,12 +740,6 @@ Checks for the correct order of sig builder methods:
|
|
740
740
|
- returns, or void
|
741
741
|
- soft, checked, or on_failure
|
742
742
|
|
743
|
-
# bad
|
744
|
-
sig { returns(Integer).params(x: Integer) }
|
745
|
-
|
746
|
-
# good
|
747
|
-
sig { params(x: Integer).returns(Integer) }
|
748
|
-
|
749
743
|
### Examples
|
750
744
|
|
751
745
|
```ruby
|
@@ -754,6 +748,12 @@ sig { void.abstract }
|
|
754
748
|
|
755
749
|
# good
|
756
750
|
sig { abstract.void }
|
751
|
+
|
752
|
+
# bad
|
753
|
+
sig { returns(Integer).params(x: Integer) }
|
754
|
+
|
755
|
+
# good
|
756
|
+
sig { params(x: Integer).returns(Integer) }
|
757
757
|
```
|
758
758
|
|
759
759
|
## Sorbet/SingleLineRbiClassModuleDefinitions
|
@@ -884,3 +884,37 @@ MinimumStrictness | `nil` | String
|
|
884
884
|
ExactStrictness | `nil` | String
|
885
885
|
Include | `**/*.{rb,rbi,rake,ru}` | Array
|
886
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.8
|
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-03-06 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rspec
|
@@ -122,6 +122,7 @@ files:
|
|
122
122
|
- lib/rubocop/cop/sorbet/signatures/enforce_signatures.rb
|
123
123
|
- lib/rubocop/cop/sorbet/signatures/keyword_argument_ordering.rb
|
124
124
|
- lib/rubocop/cop/sorbet/signatures/signature_build_order.rb
|
125
|
+
- lib/rubocop/cop/sorbet/signatures/void_checked_tests.rb
|
125
126
|
- lib/rubocop/cop/sorbet/type_alias_name.rb
|
126
127
|
- lib/rubocop/cop/sorbet_cops.rb
|
127
128
|
- lib/rubocop/sorbet.rb
|
@@ -155,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
155
156
|
- !ruby/object:Gem::Version
|
156
157
|
version: '0'
|
157
158
|
requirements: []
|
158
|
-
rubygems_version: 3.
|
159
|
+
rubygems_version: 3.5.6
|
159
160
|
signing_key:
|
160
161
|
specification_version: 4
|
161
162
|
summary: Automatic Sorbet code style checking tool.
|