rubocop-sorbet 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +1 -1
  3. data/.rubocop.yml +12 -1
  4. data/.yardopts +1 -0
  5. data/Gemfile +1 -0
  6. data/Gemfile.lock +23 -17
  7. data/README.md +1 -1
  8. data/Rakefile +1 -1
  9. data/bin/rspec +4 -2
  10. data/bin/rubocop +4 -2
  11. data/config/default.yml +23 -2
  12. data/lib/rubocop/cop/sorbet/binding_constant_without_type_alias.rb +105 -0
  13. data/lib/rubocop/cop/sorbet/callback_conditionals_binding.rb +39 -11
  14. data/lib/rubocop/cop/sorbet/constants_from_strings.rb +5 -3
  15. data/lib/rubocop/cop/sorbet/forbid_include_const_literal.rb +27 -23
  16. data/lib/rubocop/cop/sorbet/forbid_superclass_const_literal.rb +26 -27
  17. data/lib/rubocop/cop/sorbet/forbid_t_unsafe.rb +7 -3
  18. data/lib/rubocop/cop/sorbet/forbid_t_untyped.rb +7 -3
  19. data/lib/rubocop/cop/sorbet/forbid_untyped_struct_props.rb +13 -11
  20. data/lib/rubocop/cop/sorbet/implicit_conversion_method.rb +56 -0
  21. data/lib/rubocop/cop/sorbet/mixin/target_sorbet_version.rb +49 -0
  22. data/lib/rubocop/cop/sorbet/mutable_constant_sorbet_aware_behaviour.rb +8 -5
  23. data/lib/rubocop/cop/sorbet/obsolete_strict_memoization.rb +92 -0
  24. data/lib/rubocop/cop/sorbet/one_ancestor_per_line.rb +8 -3
  25. data/lib/rubocop/cop/sorbet/rbi/forbid_extend_t_sig_helpers_in_shims.rb +12 -18
  26. data/lib/rubocop/cop/sorbet/rbi/forbid_rbi_outside_of_allowed_paths.rb +8 -7
  27. data/lib/rubocop/cop/sorbet/rbi/single_line_rbi_class_module_definitions.rb +12 -18
  28. data/lib/rubocop/cop/sorbet/redundant_extend_t_sig.rb +5 -6
  29. data/lib/rubocop/cop/sorbet/sigils/enforce_sigil_order.rb +3 -2
  30. data/lib/rubocop/cop/sorbet/sigils/enforce_single_sigil.rb +6 -5
  31. data/lib/rubocop/cop/sorbet/sigils/false_sigil.rb +1 -1
  32. data/lib/rubocop/cop/sorbet/sigils/has_sigil.rb +1 -1
  33. data/lib/rubocop/cop/sorbet/sigils/ignore_sigil.rb +1 -1
  34. data/lib/rubocop/cop/sorbet/sigils/strict_sigil.rb +1 -1
  35. data/lib/rubocop/cop/sorbet/sigils/strong_sigil.rb +1 -1
  36. data/lib/rubocop/cop/sorbet/sigils/true_sigil.rb +1 -1
  37. data/lib/rubocop/cop/sorbet/sigils/valid_sigil.rb +50 -25
  38. data/lib/rubocop/cop/sorbet/signatures/allow_incompatible_override.rb +19 -30
  39. data/lib/rubocop/cop/sorbet/signatures/checked_true_in_signature.rb +3 -2
  40. data/lib/rubocop/cop/sorbet/signatures/empty_line_after_sig.rb +3 -3
  41. data/lib/rubocop/cop/sorbet/signatures/enforce_signatures.rb +8 -4
  42. data/lib/rubocop/cop/sorbet/signatures/keyword_argument_ordering.rb +5 -4
  43. data/lib/rubocop/cop/sorbet/signatures/signature_build_order.rb +8 -3
  44. data/lib/rubocop/cop/sorbet/signatures/signature_cop.rb +6 -1
  45. data/lib/rubocop/cop/sorbet/type_alias_name.rb +10 -17
  46. data/lib/rubocop/cop/sorbet_cops.rb +6 -1
  47. data/lib/rubocop/sorbet/inject.rb +9 -7
  48. data/lib/rubocop/sorbet/version.rb +2 -1
  49. data/lib/rubocop/sorbet.rb +1 -0
  50. data/manual/cops.md +2 -0
  51. data/manual/cops_sorbet.md +137 -31
  52. data/rubocop-sorbet.gemspec +1 -0
  53. data/tasks/cops_documentation.rake +16 -5
  54. metadata +8 -4
  55. 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: 87c7e5f3cd38dc5528234c83895115c4f0fe10010c041c0c914f73cf92f289f4
4
- data.tar.gz: f991837c8cce7938ae4f0043b2c10a98b9130bd01f0d2b95f62a967e03337fab
3
+ metadata.gz: c0d4456bcb92b2f40f1208842fce6a102f6ce2ba88ff491840d77a3001784677
4
+ data.tar.gz: 5e389a2c6c772f68aaf95555da670732ac70a9c5262be18c0418e0d787feb5de
5
5
  SHA512:
6
- metadata.gz: 71581073a6caba33b050d643815d98fdeae36d17eedbbcab985b9b467c9ccde100f153c58970ac3fb06f03c7834170fab65276f499bcf5e398b8dfdcde0ae5f7
7
- data.tar.gz: 66ab517902652d5921967544c7c81d89b758886d9c893b2ed60d0e32a4826fc8391c6e91c6c0701e17c916a0a6535390fead92f740cc367e34530865cc4e4122
6
+ metadata.gz: c2cb4129f91d6c52aa3affe2728a9c049635ce9ccefdcaa86520bbf0a1d25b7160a3d253597329008661f4207bf953ec36058c3908874b6f9077da0742a9f15f
7
+ data.tar.gz: c4736a927b8f377f81bf7982e9a6d6fa4669b6ebc7dea5c60bba7a8e54adc843f096c8bfe6a0eea7fc47e34cc4374c4675495936d5c9b1289a17b2d226c44375
@@ -11,7 +11,7 @@ jobs:
11
11
  strategy:
12
12
  fail-fast: false
13
13
  matrix:
14
- ruby: [ '2.5', '2.6', '2.7', '3.0', '3.1', '3.2' ]
14
+ ruby: [ '2.7', '3.0', '3.1', '3.2' ]
15
15
  name: Test Ruby ${{ matrix.ruby }}
16
16
  steps:
17
17
  - uses: actions/checkout@v2
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.5
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
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  source "https://rubygems.org"
3
4
 
4
5
  # Specify your gem's dependencies in rubocop-sorbet.gemspec
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rubocop-sorbet (0.7.0)
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
- parallel (1.21.0)
14
- parser (3.0.1.1)
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.2.0)
19
- rexml (3.2.5)
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.24.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.0.0.0)
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.15.1, < 2.0)
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 (>= 1.4.0, < 3.0)
42
- rubocop-ast (1.15.1)
43
- parser (>= 3.0.1.1)
44
- rubocop-shopify (2.1.0)
45
- rubocop (~> 1.13)
46
- ruby-progressbar (1.11.0)
47
- unicode-display_width (2.1.0)
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.2.16
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
@@ -18,7 +18,7 @@ task :new_cop, [:cop] do |_task, args|
18
18
  require "rubocop"
19
19
 
20
20
  cop_name = args.fetch(:cop) do
21
- warn("usage: bundle exec rake new_cop[Department/Name]")
21
+ warn('usage: bundle exec rake "new_cop[Department/Name]"')
22
22
  exit!
23
23
  end
24
24
 
data/bin/rspec CHANGED
@@ -9,8 +9,10 @@
9
9
  #
10
10
 
11
11
  require "pathname"
12
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
- Pathname.new(__FILE__).realpath)
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("../../Gemfile",
13
- Pathname.new(__FILE__).realpath)
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: "false"
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: "false"
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
- # This cop ensures that callback conditionals are bound to the right type
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, :validates, :validates_with, :before_validation, :around_validation, :before_create,
38
- :before_save, :before_destroy, :before_update, :after_create, :after_save, :after_destroy,
39
- :after_update, :after_touch, :after_initialize, :after_find, :around_create, :around_save,
40
- :around_destroy, :around_update, :before_commit, :after_commit, :after_create_commit,
41
- :after_destroy_commit, :after_rollback, :after_save_commit, :after_update_commit,
42
- :before_action, :prepend_before_action, :append_before_action, :around_action,
43
- :prepend_around_action, :append_around_action, :after_action, :prepend_after_action,
44
- :append_after_action
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
- # This cop disallows the calls that are used to get constants fom Strings
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
- class ForbidIncludeConstLiteral < RuboCop::Cop::Cop
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.source_range,
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
- class ForbidSuperclassConstLiteral < RuboCop::Cop::Cop
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
- def_node_matcher :not_lit_const_superclass?, <<-PATTERN
31
- (class
32
- (const ...)
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
- return unless not_lit_const_superclass?(node)
40
- add_offense(node.child_nodes[1])
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
- # This cop disallows using `T.unsafe` anywhere.
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::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, message: "Do not use `T.unsafe`.") if t_unsafe?(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
- # This cop disallows using `T.untyped` anywhere.
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::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, message: "Do not use `T.untyped`.") if t_untyped?(node)
28
+ add_offense(node) if t_untyped?(node)
25
29
  end
26
30
  end
27
31
  end