rubocop-sorbet 0.7.0 → 0.7.1
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/.github/workflows/ci.yml +1 -1
- data/.rubocop.yml +12 -1
- data/.yardopts +1 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +23 -17
- data/README.md +1 -1
- data/Rakefile +1 -1
- data/bin/rspec +4 -2
- data/bin/rubocop +4 -2
- data/config/default.yml +23 -2
- data/lib/rubocop/cop/sorbet/binding_constant_without_type_alias.rb +105 -0
- data/lib/rubocop/cop/sorbet/callback_conditionals_binding.rb +39 -11
- data/lib/rubocop/cop/sorbet/constants_from_strings.rb +5 -3
- data/lib/rubocop/cop/sorbet/forbid_include_const_literal.rb +27 -23
- data/lib/rubocop/cop/sorbet/forbid_superclass_const_literal.rb +26 -27
- data/lib/rubocop/cop/sorbet/forbid_t_unsafe.rb +7 -3
- data/lib/rubocop/cop/sorbet/forbid_t_untyped.rb +7 -3
- data/lib/rubocop/cop/sorbet/forbid_untyped_struct_props.rb +13 -11
- data/lib/rubocop/cop/sorbet/implicit_conversion_method.rb +56 -0
- data/lib/rubocop/cop/sorbet/mixin/target_sorbet_version.rb +49 -0
- data/lib/rubocop/cop/sorbet/mutable_constant_sorbet_aware_behaviour.rb +8 -5
- data/lib/rubocop/cop/sorbet/obsolete_strict_memoization.rb +92 -0
- data/lib/rubocop/cop/sorbet/one_ancestor_per_line.rb +8 -3
- data/lib/rubocop/cop/sorbet/rbi/forbid_extend_t_sig_helpers_in_shims.rb +12 -18
- data/lib/rubocop/cop/sorbet/rbi/forbid_rbi_outside_of_allowed_paths.rb +8 -7
- data/lib/rubocop/cop/sorbet/rbi/single_line_rbi_class_module_definitions.rb +12 -18
- data/lib/rubocop/cop/sorbet/redundant_extend_t_sig.rb +5 -6
- data/lib/rubocop/cop/sorbet/sigils/enforce_sigil_order.rb +3 -2
- data/lib/rubocop/cop/sorbet/sigils/enforce_single_sigil.rb +6 -5
- data/lib/rubocop/cop/sorbet/sigils/false_sigil.rb +1 -1
- data/lib/rubocop/cop/sorbet/sigils/has_sigil.rb +1 -1
- data/lib/rubocop/cop/sorbet/sigils/ignore_sigil.rb +1 -1
- data/lib/rubocop/cop/sorbet/sigils/strict_sigil.rb +1 -1
- data/lib/rubocop/cop/sorbet/sigils/strong_sigil.rb +1 -1
- data/lib/rubocop/cop/sorbet/sigils/true_sigil.rb +1 -1
- data/lib/rubocop/cop/sorbet/sigils/valid_sigil.rb +50 -25
- data/lib/rubocop/cop/sorbet/signatures/allow_incompatible_override.rb +19 -30
- data/lib/rubocop/cop/sorbet/signatures/checked_true_in_signature.rb +3 -2
- data/lib/rubocop/cop/sorbet/signatures/empty_line_after_sig.rb +3 -3
- data/lib/rubocop/cop/sorbet/signatures/enforce_signatures.rb +8 -4
- data/lib/rubocop/cop/sorbet/signatures/keyword_argument_ordering.rb +5 -4
- data/lib/rubocop/cop/sorbet/signatures/signature_build_order.rb +8 -3
- data/lib/rubocop/cop/sorbet/signatures/signature_cop.rb +6 -1
- data/lib/rubocop/cop/sorbet/type_alias_name.rb +10 -17
- data/lib/rubocop/cop/sorbet_cops.rb +6 -1
- data/lib/rubocop/sorbet/inject.rb +9 -7
- data/lib/rubocop/sorbet/version.rb +2 -1
- data/lib/rubocop/sorbet.rb +1 -0
- data/manual/cops.md +2 -0
- data/manual/cops_sorbet.md +137 -31
- data/rubocop-sorbet.gemspec +1 -0
- data/tasks/cops_documentation.rake +16 -5
- metadata +8 -4
- data/lib/rubocop/cop/sorbet/binding_constants_without_type_alias.rb +0 -127
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0d4456bcb92b2f40f1208842fce6a102f6ce2ba88ff491840d77a3001784677
|
4
|
+
data.tar.gz: 5e389a2c6c772f68aaf95555da670732ac70a9c5262be18c0418e0d787feb5de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c2cb4129f91d6c52aa3affe2728a9c049635ce9ccefdcaa86520bbf0a1d25b7160a3d253597329008661f4207bf953ec36058c3908874b6f9077da0742a9f15f
|
7
|
+
data.tar.gz: c4736a927b8f377f81bf7982e9a6d6fa4669b6ebc7dea5c60bba7a8e54adc843f096c8bfe6a0eea7fc47e34cc4374c4675495936d5c9b1289a17b2d226c44375
|
data/.github/workflows/ci.yml
CHANGED
data/.rubocop.yml
CHANGED
@@ -3,11 +3,22 @@
|
|
3
3
|
inherit_gem:
|
4
4
|
rubocop-shopify: rubocop.yml
|
5
5
|
|
6
|
+
require:
|
7
|
+
- rubocop/cop/internal_affairs
|
8
|
+
|
6
9
|
AllCops:
|
7
|
-
TargetRubyVersion: 2.
|
10
|
+
TargetRubyVersion: 2.7
|
8
11
|
Exclude:
|
9
12
|
- vendor/**/*
|
13
|
+
NewCops: disable
|
14
|
+
SuggestExtensions: false
|
15
|
+
|
16
|
+
InternalAffairs:
|
17
|
+
Enabled: true
|
10
18
|
|
11
19
|
Naming/FileName:
|
12
20
|
Exclude:
|
13
21
|
- lib/rubocop-sorbet.rb
|
22
|
+
|
23
|
+
Layout/LineLength:
|
24
|
+
IgnoreCopDirectives: true
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--tag safety:"Cop Safety Information"
|
data/Gemfile
CHANGED
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.1)
|
5
5
|
rubocop (>= 0.90.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -10,13 +10,17 @@ GEM
|
|
10
10
|
ast (2.4.2)
|
11
11
|
byebug (11.1.3)
|
12
12
|
diff-lcs (1.3)
|
13
|
-
|
14
|
-
|
13
|
+
json (2.6.3)
|
14
|
+
language_server-protocol (3.17.0.3)
|
15
|
+
parallel (1.23.0)
|
16
|
+
parser (3.2.2.3)
|
15
17
|
ast (~> 2.4.1)
|
18
|
+
racc
|
19
|
+
racc (1.7.1)
|
16
20
|
rainbow (3.1.1)
|
17
21
|
rake (13.0.1)
|
18
|
-
regexp_parser (2.
|
19
|
-
rexml (3.2.
|
22
|
+
regexp_parser (2.8.1)
|
23
|
+
rexml (3.2.6)
|
20
24
|
rspec (3.8.0)
|
21
25
|
rspec-core (~> 3.8.0)
|
22
26
|
rspec-expectations (~> 3.8.0)
|
@@ -30,21 +34,23 @@ GEM
|
|
30
34
|
diff-lcs (>= 1.2.0, < 2.0)
|
31
35
|
rspec-support (~> 3.8.0)
|
32
36
|
rspec-support (3.8.2)
|
33
|
-
rubocop (1.
|
37
|
+
rubocop (1.55.1)
|
38
|
+
json (~> 2.3)
|
39
|
+
language_server-protocol (>= 3.17.0)
|
34
40
|
parallel (~> 1.10)
|
35
|
-
parser (>= 3.
|
41
|
+
parser (>= 3.2.2.3)
|
36
42
|
rainbow (>= 2.2.2, < 4.0)
|
37
43
|
regexp_parser (>= 1.8, < 3.0)
|
38
|
-
rexml
|
39
|
-
rubocop-ast (>= 1.
|
44
|
+
rexml (>= 3.2.5, < 4.0)
|
45
|
+
rubocop-ast (>= 1.28.1, < 2.0)
|
40
46
|
ruby-progressbar (~> 1.7)
|
41
|
-
unicode-display_width (>=
|
42
|
-
rubocop-ast (1.
|
43
|
-
parser (>= 3.
|
44
|
-
rubocop-shopify (2.
|
45
|
-
rubocop (~> 1.
|
46
|
-
ruby-progressbar (1.
|
47
|
-
unicode-display_width (2.
|
47
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
48
|
+
rubocop-ast (1.29.0)
|
49
|
+
parser (>= 3.2.1.0)
|
50
|
+
rubocop-shopify (2.14.0)
|
51
|
+
rubocop (~> 1.51)
|
52
|
+
ruby-progressbar (1.13.0)
|
53
|
+
unicode-display_width (2.4.2)
|
48
54
|
unparser (0.6.0)
|
49
55
|
diff-lcs (~> 1.3)
|
50
56
|
parser (>= 3.0.0)
|
@@ -63,4 +69,4 @@ DEPENDENCIES
|
|
63
69
|
yard (~> 0.9)
|
64
70
|
|
65
71
|
BUNDLED WITH
|
66
|
-
2.
|
72
|
+
2.4.18
|
data/README.md
CHANGED
@@ -98,7 +98,7 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/Shopif
|
|
98
98
|
To contribute a new cop, please use the supplied generator like this:
|
99
99
|
|
100
100
|
```sh
|
101
|
-
bundle exec rake new_cop[Sorbet/NewCopName]
|
101
|
+
bundle exec rake "new_cop[Sorbet/NewCopName]"
|
102
102
|
```
|
103
103
|
|
104
104
|
which will create a skeleton cop, a skeleton spec, an entry in the default config file and will require the new cop so that it is properly exported from the gem.
|
data/Rakefile
CHANGED
data/bin/rspec
CHANGED
@@ -9,8 +9,10 @@
|
|
9
9
|
#
|
10
10
|
|
11
11
|
require "pathname"
|
12
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(
|
13
|
-
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(
|
13
|
+
"../../Gemfile",
|
14
|
+
Pathname.new(__FILE__).realpath,
|
15
|
+
)
|
14
16
|
|
15
17
|
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
18
|
|
data/bin/rubocop
CHANGED
@@ -9,8 +9,10 @@
|
|
9
9
|
#
|
10
10
|
|
11
11
|
require "pathname"
|
12
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(
|
13
|
-
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(
|
13
|
+
"../../Gemfile",
|
14
|
+
Pathname.new(__FILE__).realpath,
|
15
|
+
)
|
14
16
|
|
15
17
|
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
18
|
|
data/config/default.yml
CHANGED
@@ -120,7 +120,8 @@ Sorbet/HasSigil:
|
|
120
120
|
Description: 'Makes the Sorbet typed sigil mandatory in all files.'
|
121
121
|
Enabled: false
|
122
122
|
SuggestedStrictness: "false"
|
123
|
-
MinimumStrictness:
|
123
|
+
MinimumStrictness: nil
|
124
|
+
ExactStrictness: nil
|
124
125
|
VersionAdded: 0.3.3
|
125
126
|
Include:
|
126
127
|
- "**/*.{rb,rbi,rake,ru}"
|
@@ -141,6 +142,13 @@ Sorbet/IgnoreSigil:
|
|
141
142
|
- db/**/*.rb
|
142
143
|
- script/**/*
|
143
144
|
|
145
|
+
Sorbet/ImplicitConversionMethod:
|
146
|
+
Description: >-
|
147
|
+
This cop disallows declaring implicit conversion methods, as sorbet does
|
148
|
+
not support implicit conversion.
|
149
|
+
Enabled: false
|
150
|
+
VersionAdded: '<<next>>'
|
151
|
+
|
144
152
|
Sorbet/KeywordArgumentOrdering:
|
145
153
|
Description: >-
|
146
154
|
Enforces a compatible keyword arguments with Sorbet.
|
@@ -151,6 +159,18 @@ Sorbet/KeywordArgumentOrdering:
|
|
151
159
|
Enabled: true
|
152
160
|
VersionAdded: 0.2.0
|
153
161
|
|
162
|
+
Sorbet/ObsoleteStrictMemoization:
|
163
|
+
Description: >-
|
164
|
+
This cop checks for the obsolete pattern for initializing instance variables that was required for older Sorbet
|
165
|
+
versions in `#typed: strict` files.
|
166
|
+
|
167
|
+
It's no longer required, as of Sorbet 0.5.10210
|
168
|
+
See https://sorbet.org/docs/type-assertions#put-type-assertions-behind-memoization
|
169
|
+
Enabled: true
|
170
|
+
VersionAdded: '0.7.1'
|
171
|
+
Safe: true
|
172
|
+
SafeAutoCorrect: true
|
173
|
+
|
154
174
|
Sorbet/OneAncestorPerLine:
|
155
175
|
Description: 'Enforces one ancestor per call to requires_ancestor'
|
156
176
|
Enabled: false
|
@@ -235,7 +255,8 @@ Sorbet/ValidSigil:
|
|
235
255
|
Enabled: true
|
236
256
|
RequireSigilOnAllFiles: false
|
237
257
|
SuggestedStrictness: "false"
|
238
|
-
MinimumStrictness:
|
258
|
+
MinimumStrictness: nil
|
259
|
+
ExactStrictness: nil
|
239
260
|
VersionAdded: 0.3.3
|
240
261
|
Include:
|
241
262
|
- "**/*.{rb,rbi,rake,ru}"
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rubocop"
|
4
|
+
|
5
|
+
module RuboCop
|
6
|
+
module Cop
|
7
|
+
module Sorbet
|
8
|
+
# Disallows binding the return value of `T.any`, `T.all`, `T.enum`
|
9
|
+
# to a constant directly. To bind the value, one must use `T.type_alias`.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
#
|
13
|
+
# # bad
|
14
|
+
# FooOrBar = T.any(Foo, Bar)
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# FooOrBar = T.type_alias { T.any(Foo, Bar) }
|
18
|
+
class BindingConstantWithoutTypeAlias < RuboCop::Cop::Base
|
19
|
+
extend AutoCorrector
|
20
|
+
|
21
|
+
MSG = "It looks like you're trying to bind a type to a constant. " \
|
22
|
+
"To do this, you must alias the type using `T.type_alias`."
|
23
|
+
WITHOUT_BLOCK_MSG = "It looks like you're using the old `T.type_alias` syntax. " \
|
24
|
+
"`T.type_alias` now expects a block." \
|
25
|
+
'Run Sorbet with the options "--autocorrect --error-white-list=5043" ' \
|
26
|
+
"to automatically upgrade to the new syntax."
|
27
|
+
|
28
|
+
# @!method type_alias_without_block(node)
|
29
|
+
def_node_matcher :type_alias_without_block, <<~PATTERN
|
30
|
+
(send
|
31
|
+
(const {nil? cbase} :T)
|
32
|
+
:type_alias
|
33
|
+
$_
|
34
|
+
)
|
35
|
+
PATTERN
|
36
|
+
|
37
|
+
# @!method type_alias_with_block?(node)
|
38
|
+
def_node_matcher :type_alias_with_block?, <<~PATTERN
|
39
|
+
(block
|
40
|
+
(send
|
41
|
+
(const {nil? cbase} :T)
|
42
|
+
:type_alias)
|
43
|
+
...
|
44
|
+
)
|
45
|
+
PATTERN
|
46
|
+
|
47
|
+
# @!method requires_type_alias?(node)
|
48
|
+
def_node_matcher :requires_type_alias?, <<~PATTERN
|
49
|
+
(send
|
50
|
+
(const {nil? cbase} :T)
|
51
|
+
{
|
52
|
+
:all
|
53
|
+
:any
|
54
|
+
:class_of
|
55
|
+
:nilable
|
56
|
+
:noreturn
|
57
|
+
:proc
|
58
|
+
:self_type
|
59
|
+
:untyped
|
60
|
+
}
|
61
|
+
...
|
62
|
+
)
|
63
|
+
PATTERN
|
64
|
+
|
65
|
+
def on_casgn(node)
|
66
|
+
expression = node.expression
|
67
|
+
return if expression.nil? # multiple assignment
|
68
|
+
|
69
|
+
type_alias_without_block(expression) do |type|
|
70
|
+
return add_offense(expression, message: WITHOUT_BLOCK_MSG) do |corrector|
|
71
|
+
corrector.replace(expression, "T.type_alias { #{type.source} }")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
return if type_alias_with_block?(expression)
|
76
|
+
|
77
|
+
requires_type_alias?(send_leaf(expression)) do
|
78
|
+
return add_offense(expression) do |corrector|
|
79
|
+
corrector.replace(expression, "T.type_alias { #{expression.source} }")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
# Given nested send nodes, returns the leaf with explicit receiver.
|
87
|
+
#
|
88
|
+
# i.e. in Ruby
|
89
|
+
#
|
90
|
+
# a.b.c.d.e.f
|
91
|
+
# ^^^
|
92
|
+
#
|
93
|
+
# i.e. in AST
|
94
|
+
#
|
95
|
+
# (send (send (send (send (send (send nil :a) :b) :c) :d) :e) :f)
|
96
|
+
# ^^^^^^^^^^^^^^^^^^^^^^^
|
97
|
+
#
|
98
|
+
def send_leaf(node)
|
99
|
+
node = node.receiver while node&.receiver&.send_type?
|
100
|
+
node
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Sorbet
|
6
|
-
#
|
6
|
+
# Ensures that callback conditionals are bound to the right type
|
7
7
|
# so that they are type checked properly.
|
8
8
|
#
|
9
9
|
# Auto-correction is unsafe because other libraries define similar style callbacks as Rails, but don't always need
|
@@ -32,16 +32,44 @@ module RuboCop
|
|
32
32
|
# true
|
33
33
|
# end
|
34
34
|
# end
|
35
|
-
class CallbackConditionalsBinding < RuboCop::Cop::Cop
|
35
|
+
class CallbackConditionalsBinding < RuboCop::Cop::Cop # rubocop:todo InternalAffairs/InheritDeprecatedCopClass
|
36
36
|
CALLBACKS = [
|
37
|
-
:validate,
|
38
|
-
:
|
39
|
-
:
|
40
|
-
:
|
41
|
-
:
|
42
|
-
:
|
43
|
-
:
|
44
|
-
:
|
37
|
+
:validate,
|
38
|
+
:validates,
|
39
|
+
:validates_with,
|
40
|
+
:before_validation,
|
41
|
+
:around_validation,
|
42
|
+
:before_create,
|
43
|
+
:before_save,
|
44
|
+
:before_destroy,
|
45
|
+
:before_update,
|
46
|
+
:after_create,
|
47
|
+
:after_save,
|
48
|
+
:after_destroy,
|
49
|
+
:after_update,
|
50
|
+
:after_touch,
|
51
|
+
:after_initialize,
|
52
|
+
:after_find,
|
53
|
+
:around_create,
|
54
|
+
:around_save,
|
55
|
+
:around_destroy,
|
56
|
+
:around_update,
|
57
|
+
:before_commit,
|
58
|
+
:after_commit,
|
59
|
+
:after_create_commit,
|
60
|
+
:after_destroy_commit,
|
61
|
+
:after_rollback,
|
62
|
+
:after_save_commit,
|
63
|
+
:after_update_commit,
|
64
|
+
:before_action,
|
65
|
+
:prepend_before_action,
|
66
|
+
:append_before_action,
|
67
|
+
:around_action,
|
68
|
+
:prepend_around_action,
|
69
|
+
:append_around_action,
|
70
|
+
:after_action,
|
71
|
+
:prepend_after_action,
|
72
|
+
:append_after_action,
|
45
73
|
].freeze
|
46
74
|
|
47
75
|
def autocorrect(node)
|
@@ -132,7 +160,7 @@ module RuboCop
|
|
132
160
|
unless block.source.include?("T.bind(self")
|
133
161
|
add_offense(
|
134
162
|
node,
|
135
|
-
message: "Callback conditionals should be bound to the right type. Use T.bind(self, #{expected_class})"
|
163
|
+
message: "Callback conditionals should be bound to the right type. Use T.bind(self, #{expected_class})",
|
136
164
|
)
|
137
165
|
end
|
138
166
|
end
|
@@ -5,7 +5,7 @@ require "rubocop"
|
|
5
5
|
module RuboCop
|
6
6
|
module Cop
|
7
7
|
module Sorbet
|
8
|
-
#
|
8
|
+
# Disallows the calls that are used to get constants fom Strings
|
9
9
|
# such as +constantize+, +const_get+, and +constants+.
|
10
10
|
#
|
11
11
|
# The goal of this cop is to make the code easier to statically analyze,
|
@@ -33,18 +33,20 @@ module RuboCop
|
|
33
33
|
#
|
34
34
|
# # good
|
35
35
|
# { "User" => User }.fetch(class_name)
|
36
|
-
class ConstantsFromStrings < ::RuboCop::Cop::Cop
|
36
|
+
class ConstantsFromStrings < ::RuboCop::Cop::Cop # rubocop:todo InternalAffairs/InheritDeprecatedCopClass
|
37
|
+
# @!method constant_from_string?(node)
|
37
38
|
def_node_matcher(:constant_from_string?, <<-PATTERN)
|
38
39
|
(send _ {:constantize :constants :const_get} ...)
|
39
40
|
PATTERN
|
40
41
|
|
41
42
|
def on_send(node)
|
42
43
|
return unless constant_from_string?(node)
|
44
|
+
|
43
45
|
add_offense(
|
44
46
|
node,
|
45
47
|
location: :selector,
|
46
48
|
message: "Don't use `#{node.method_name}`, it makes the code harder to understand, less editor-friendly, " \
|
47
|
-
"and impossible to analyze. Replace `#{node.method_name}` with a case/when or a hash."
|
49
|
+
"and impossible to analyze. Replace `#{node.method_name}` with a case/when or a hash.",
|
48
50
|
)
|
49
51
|
end
|
50
52
|
end
|
@@ -3,34 +3,35 @@
|
|
3
3
|
|
4
4
|
require "rubocop"
|
5
5
|
|
6
|
-
# Correct `send` expressions in include statements by constant literals.
|
7
|
-
#
|
8
|
-
# Sorbet, the static checker, is not (yet) able to support constructs on the
|
9
|
-
# following form:
|
10
|
-
#
|
11
|
-
# ```ruby
|
12
|
-
# class MyClass
|
13
|
-
# include send_expr
|
14
|
-
# end
|
15
|
-
# ```
|
16
|
-
#
|
17
|
-
# Multiple occurences of this can be found in Shopify's code base like:
|
18
|
-
#
|
19
|
-
# ```ruby
|
20
|
-
# include Rails.application.routes.url_helpers
|
21
|
-
# ```
|
22
|
-
# or
|
23
|
-
# ```ruby
|
24
|
-
# include Polaris::Engine.helpers
|
25
|
-
# ```
|
26
6
|
module RuboCop
|
27
7
|
module Cop
|
28
8
|
module Sorbet
|
29
|
-
|
9
|
+
# Correct `send` expressions in include statements by constant literals.
|
10
|
+
#
|
11
|
+
# Sorbet, the static checker, is not (yet) able to support constructs on the
|
12
|
+
# following form:
|
13
|
+
#
|
14
|
+
# ```ruby
|
15
|
+
# class MyClass
|
16
|
+
# include send_expr
|
17
|
+
# end
|
18
|
+
# ```
|
19
|
+
#
|
20
|
+
# Multiple occurences of this can be found in Shopify's code base like:
|
21
|
+
#
|
22
|
+
# ```ruby
|
23
|
+
# include Rails.application.routes.url_helpers
|
24
|
+
# ```
|
25
|
+
# or
|
26
|
+
# ```ruby
|
27
|
+
# include Polaris::Engine.helpers
|
28
|
+
# ```
|
29
|
+
class ForbidIncludeConstLiteral < RuboCop::Cop::Cop # rubocop:todo InternalAffairs/InheritDeprecatedCopClass
|
30
30
|
MSG = "Includes must only contain constant literals"
|
31
31
|
|
32
32
|
attr_accessor :used_names
|
33
33
|
|
34
|
+
# @!method not_lit_const_include?(node)
|
34
35
|
def_node_matcher :not_lit_const_include?, <<-PATTERN
|
35
36
|
(send nil? {:include :extend :prepend}
|
36
37
|
$_
|
@@ -46,18 +47,21 @@ module RuboCop
|
|
46
47
|
return unless not_lit_const_include?(node) do |send_argument|
|
47
48
|
![:const, :self].include?(send_argument.type)
|
48
49
|
end
|
50
|
+
|
49
51
|
parent = node.parent
|
50
52
|
return unless parent
|
53
|
+
|
51
54
|
parent = parent.parent if [:begin, :block].include?(parent.type)
|
52
55
|
return unless [:module, :class, :sclass].include?(parent.type)
|
56
|
+
|
53
57
|
add_offense(node)
|
54
58
|
end
|
55
59
|
|
56
60
|
def autocorrect(node)
|
57
61
|
lambda do |corrector|
|
58
62
|
corrector.replace(
|
59
|
-
node
|
60
|
-
"T.unsafe(self).#{node.source}"
|
63
|
+
node,
|
64
|
+
"T.unsafe(self).#{node.source}",
|
61
65
|
)
|
62
66
|
end
|
63
67
|
end
|
@@ -3,41 +3,40 @@
|
|
3
3
|
|
4
4
|
require "rubocop"
|
5
5
|
|
6
|
-
# Correct superclass `send` expressions by constant literals.
|
7
|
-
#
|
8
|
-
# Sorbet, the static checker, is not (yet) able to support constructs on the
|
9
|
-
# following form:
|
10
|
-
#
|
11
|
-
# ```ruby
|
12
|
-
# class Foo < send_expr; end
|
13
|
-
# ```
|
14
|
-
#
|
15
|
-
# Multiple occurences of this can be found in Shopify's code base like:
|
16
|
-
#
|
17
|
-
# ```ruby
|
18
|
-
# class ShopScope < Component::TrustedIdScope[ShopIdentity::ShopId]
|
19
|
-
# ```
|
20
|
-
# or
|
21
|
-
# ```ruby
|
22
|
-
# class ApiClientEligibility < Struct.new(:api_client, :match_results, :shop)
|
23
|
-
# ```
|
24
6
|
module RuboCop
|
25
7
|
module Cop
|
26
8
|
module Sorbet
|
27
|
-
|
9
|
+
# Correct superclass `send` expressions by constant literals.
|
10
|
+
#
|
11
|
+
# Sorbet, the static checker, is not (yet) able to support constructs on the
|
12
|
+
# following form:
|
13
|
+
#
|
14
|
+
# ```ruby
|
15
|
+
# class Foo < send_expr; end
|
16
|
+
# ```
|
17
|
+
#
|
18
|
+
# Multiple occurences of this can be found in Shopify's code base like:
|
19
|
+
#
|
20
|
+
# ```ruby
|
21
|
+
# class ShopScope < Component::TrustedIdScope[ShopIdentity::ShopId]
|
22
|
+
# ```
|
23
|
+
# or
|
24
|
+
# ```ruby
|
25
|
+
# class ApiClientEligibility < Struct.new(:api_client, :match_results, :shop)
|
26
|
+
# ```
|
27
|
+
|
28
|
+
class ForbidSuperclassConstLiteral < RuboCop::Cop::Base
|
28
29
|
MSG = "Superclasses must only contain constant literals"
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
(send ...)
|
34
|
-
...
|
35
|
-
)
|
31
|
+
# @!method dynamic_superclass?(node)
|
32
|
+
def_node_matcher :dynamic_superclass?, <<-PATTERN
|
33
|
+
(class (const ...) $(send ...) ...)
|
36
34
|
PATTERN
|
37
35
|
|
38
36
|
def on_class(node)
|
39
|
-
|
40
|
-
|
37
|
+
dynamic_superclass?(node) do |superclass|
|
38
|
+
add_offense(superclass)
|
39
|
+
end
|
41
40
|
end
|
42
41
|
end
|
43
42
|
end
|
@@ -5,7 +5,7 @@ require "rubocop"
|
|
5
5
|
module RuboCop
|
6
6
|
module Cop
|
7
7
|
module Sorbet
|
8
|
-
#
|
8
|
+
# Disallows using `T.unsafe` anywhere.
|
9
9
|
#
|
10
10
|
# @example
|
11
11
|
#
|
@@ -14,11 +14,15 @@ module RuboCop
|
|
14
14
|
#
|
15
15
|
# # good
|
16
16
|
# foo
|
17
|
-
class ForbidTUnsafe < RuboCop::Cop::
|
17
|
+
class ForbidTUnsafe < RuboCop::Cop::Base
|
18
|
+
MSG = "Do not use `T.unsafe`."
|
19
|
+
RESTRICT_ON_SEND = [:unsafe].freeze
|
20
|
+
|
21
|
+
# @!method t_unsafe?(node)
|
18
22
|
def_node_matcher(:t_unsafe?, "(send (const nil? :T) :unsafe _)")
|
19
23
|
|
20
24
|
def on_send(node)
|
21
|
-
add_offense(node
|
25
|
+
add_offense(node) if t_unsafe?(node)
|
22
26
|
end
|
23
27
|
end
|
24
28
|
end
|
@@ -5,7 +5,7 @@ require "rubocop"
|
|
5
5
|
module RuboCop
|
6
6
|
module Cop
|
7
7
|
module Sorbet
|
8
|
-
#
|
8
|
+
# Disallows using `T.untyped` anywhere.
|
9
9
|
#
|
10
10
|
# @example
|
11
11
|
#
|
@@ -17,11 +17,15 @@ module RuboCop
|
|
17
17
|
# sig { params(my_argument: String).void }
|
18
18
|
# def foo(my_argument); end
|
19
19
|
#
|
20
|
-
class ForbidTUntyped < RuboCop::Cop::
|
20
|
+
class ForbidTUntyped < RuboCop::Cop::Base
|
21
|
+
MSG = "Do not use `T.untyped`."
|
22
|
+
RESTRICT_ON_SEND = [:untyped].freeze
|
23
|
+
|
24
|
+
# @!method t_untyped?(node)
|
21
25
|
def_node_matcher(:t_untyped?, "(send (const nil? :T) :untyped)")
|
22
26
|
|
23
27
|
def on_send(node)
|
24
|
-
add_offense(node
|
28
|
+
add_offense(node) if t_untyped?(node)
|
25
29
|
end
|
26
30
|
end
|
27
31
|
end
|