rubocop-sorbet 0.7.6 → 0.7.8

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: 6bb19df178a322278126862ef69ee548a1480a3273b2fa7cb390efea682076d3
4
- data.tar.gz: a4808b614e42b591e1254298ae40b41327b5762f5d7e494e5dbd476034d7f5a8
3
+ metadata.gz: 68f2d0d8c272caa3933e34350356e99c32e0ec42bec4b43a39c748ef2422d048
4
+ data.tar.gz: c0bd1e275d17d85ff1a6f63ab0bad42f47e5f3f17480ac4d06e5d70f4f52973d
5
5
  SHA512:
6
- metadata.gz: 495f4c62a3e669483d4a2fb958672480e1f50519589bbef0efab007b32f56c32fad54a795a47ee8da6157d4595da0a50f845744578e0f44fab34e57fc67aa28e
7
- data.tar.gz: 3e07de7f56533ed0c86dfb510e8efa0a3d1c9eb79cd130f24235cd6919a1f05ca88afc8fa7ae114de9de3ed49beac2ddc16d0d0c3e37a0a2bf6f7404ac80dcaa
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.6)
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.25)
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
@@ -293,3 +293,8 @@ Sorbet/ValidSigil:
293
293
  - bin/**/*
294
294
  - db/**/*.rb
295
295
  - script/**/*
296
+
297
+ Sorbet/VoidCheckedTests:
298
+ Description: 'Forbid `.void.checked(:tests)`'
299
+ Enabled: true
300
+ VersionAdded: 0.7.7
@@ -102,7 +102,7 @@ module RuboCop
102
102
  end
103
103
 
104
104
  class Property
105
- attr_reader :node, :kind, :name, :type, :default, :factory
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
- string << "#{indent}sig { params(#{sorted_props.map(&:initialize_sig_param).join(", ")}).void }\n"
219
- string << "#{indent}def initialize(#{sorted_props.map(&:initialize_param).join(", ")})\n"
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
- # # 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
@@ -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"
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module Sorbet
5
- VERSION = "0.7.6"
5
+ VERSION = "0.7.8"
6
6
  end
7
7
  end
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
 
@@ -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.6
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: 2023-12-04 00:00:00.000000000 Z
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.4.22
159
+ rubygems_version: 3.5.6
159
160
  signing_key:
160
161
  specification_version: 4
161
162
  summary: Automatic Sorbet code style checking tool.