rubocop-sorbet 0.15.0 → 0.16.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c39dd9a109166794a04d1de593be112325fa55f600df1d6fc1d481c400360a2a
4
- data.tar.gz: '079324e7c60ee05df867f0906e7793834f617c52976dae43eb1abc73a64e1abb'
3
+ metadata.gz: 470327d8286422c40aae8ee749d18b5eb41dc672e1a7a9840ad5127c5b9b908d
4
+ data.tar.gz: 74920f83bc657a9bf96be7f917479d945e3ff26f8a0ee084c34bb82e2b89da31
5
5
  SHA512:
6
- metadata.gz: 9437cce4926a57337187fc4b2a493f06d2689e84dff0dc4fe812bbf24fe5dab0d85aa3a677f3d114a8f258fa90a84fcea6dd2eae57200675853800c1df4028a0
7
- data.tar.gz: 35305c1ad2adaf35bafd5cc05dfda479e24098ef20ee6512dcb39709b8fe1a6525e85aa436cb35e23e5aa089146c2ffd74182f6edf7e9706e3bea7173220cb8c
6
+ metadata.gz: 30ff526689054a6f85efa7db803f707f1409e7490b930b497c5c352a5b729701090100a2143228bca9e8b6023240d162541e974bf0e7e5e58c7a1dbe8b16dbd6
7
+ data.tar.gz: 589c8d1fda81972ae50ab72138e952c9d17d4dc7275dee9ef58473af9a013f671f5f8c71a8e423fbd977d247e1fa41a7bf266a517a532ab32826f60ad406a5ba
@@ -29,7 +29,7 @@ jobs:
29
29
  bundler-cache: true
30
30
 
31
31
  - name: Release gem on RubyGems.org
32
- uses: rubygems/release-gem@052cc82692552de3ef2b81fd670e41d13cba8092 # v1.4.0
32
+ uses: rubygems/release-gem@7f9650160c1a4e7989fdc9855807bdbd421d8b6b # v1.4.1
33
33
 
34
34
  release_github:
35
35
  name: Create GitHub release
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rubocop-sorbet (0.15.0)
4
+ rubocop-sorbet (0.16.0)
5
5
  lint_roller
6
6
  rbi (~> 0.4)
7
7
  rubocop (>= 1.75.2)
@@ -110,6 +110,7 @@ GEM
110
110
 
111
111
  PLATFORMS
112
112
  arm64-darwin-23
113
+ arm64-darwin-24
113
114
  arm64-darwin-25
114
115
  x86_64-linux
115
116
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.15.0
1
+ 0.16.0
data/config/default.yml CHANGED
@@ -5,6 +5,9 @@
5
5
  Layout/LeadingCommentSpace:
6
6
  AllowRBSInlineAnnotation: true
7
7
 
8
+ Lint/SelfAssignment:
9
+ AllowRBSInlineAnnotation: true
10
+
8
11
  Sorbet/ForbidTHelpers:
9
12
  Description: 'Forbid usage of T::Helpers via `extend` or `include`.'
10
13
  Enabled: false
@@ -246,7 +249,7 @@ Sorbet/ForbidTCast:
246
249
  AutocorrectToRBS: false
247
250
  SafeAutoCorrect: false
248
251
  VersionAdded: 0.10.4
249
- VersionChanged: '0.15.0'
252
+ VersionChanged: '0.16.0'
250
253
 
251
254
  Sorbet/ForbidTLet:
252
255
  Description: 'Forbid usage of T.let.'
@@ -254,7 +257,7 @@ Sorbet/ForbidTLet:
254
257
  AutocorrectToRBS: false
255
258
  SafeAutoCorrect: false
256
259
  VersionAdded: 0.10.4
257
- VersionChanged: '0.15.0'
260
+ VersionChanged: '0.16.0'
258
261
 
259
262
  Sorbet/ForbidTMust:
260
263
  Description: 'Forbid usage of T.must.'
@@ -282,7 +285,7 @@ Sorbet/ForbidTUnsafe:
282
285
  AutocorrectToRBS: false
283
286
  SafeAutoCorrect: false
284
287
  VersionAdded: 0.7.0
285
- VersionChanged: '0.15.0'
288
+ VersionChanged: '0.16.0'
286
289
 
287
290
  Sorbet/ForbidTUntyped:
288
291
  Description: 'Forbid usage of T.untyped'
@@ -37,10 +37,11 @@ module RuboCop
37
37
 
38
38
  def autocorrect_t_cast_to_rbs(corrector, node)
39
39
  return if t_cast?(node.first_argument)
40
- return unless rbs_assertion_autocorrectable?(node, allow_assignment: true)
41
40
 
42
- type = ::RBI::Type.parse_string(node.last_argument.source).rbs_string
43
- corrector.replace(node, "#{node.first_argument.source} #: as #{type}")
41
+ autocorrect_rbs_assertion(corrector, node, allow_assignment: true) do
42
+ type = ::RBI::Type.parse_string(node.last_argument.source).rbs_string
43
+ [node.first_argument.source, "as #{type}"]
44
+ end
44
45
  rescue ::RBI::Type::Error
45
46
  nil
46
47
  end
@@ -37,10 +37,11 @@ module RuboCop
37
37
 
38
38
  def autocorrect_t_let_to_rbs(corrector, node)
39
39
  return if t_let?(node.first_argument)
40
- return unless rbs_assertion_autocorrectable?(node, allow_assignment: true)
41
40
 
42
- type = ::RBI::Type.parse_string(node.last_argument.source).rbs_string
43
- corrector.replace(node, "#{node.first_argument.source} #: #{type}")
41
+ autocorrect_rbs_assertion(corrector, node, allow_assignment: true) do
42
+ type = ::RBI::Type.parse_string(node.last_argument.source).rbs_string
43
+ [node.first_argument.source, type]
44
+ end
44
45
  rescue ::RBI::Type::Error
45
46
  nil
46
47
  end
@@ -35,9 +35,9 @@ module RuboCop
35
35
  private
36
36
 
37
37
  def autocorrect_t_unsafe_to_rbs(corrector, node)
38
- return unless rbs_assertion_autocorrectable?(node, allow_assignment: true)
39
-
40
- corrector.replace(node, "#{node.first_argument.source} #: as untyped")
38
+ autocorrect_rbs_assertion(corrector, node, allow_assignment: true) do
39
+ [node.first_argument.source, "as untyped"]
40
+ end
41
41
  end
42
42
  end
43
43
  end
@@ -3,16 +3,133 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Sorbet
6
- # Shared guards for replacing Sorbet runtime assertions with RBS inline
7
- # comments without changing the surrounding Ruby syntax.
6
+ # Shared guards and rewrites for replacing Sorbet runtime assertions
7
+ # with equivalent RBS inline comments.
8
8
  module RBSAssertionCorrection
9
9
  include RangeHelp
10
+ include Alignment
10
11
 
11
12
  COMMENT_START = "#"
12
13
  NEWLINES = ["\n", "\r"].freeze
13
14
 
14
15
  private
15
16
 
17
+ def autocorrect_rbs_assertion(corrector, node, allow_assignment: false)
18
+ context = rbs_assertion_correction_context(node, allow_assignment: allow_assignment)
19
+ return unless context
20
+
21
+ expression, annotation = yield
22
+ case context.first
23
+ when :direct
24
+ corrector.replace(node, "#{expression} #: #{annotation}")
25
+ when :arguments
26
+ autocorrect_argument_list(corrector, node, expression, annotation, context)
27
+ end
28
+ end
29
+
30
+ def rbs_assertion_correction_context(node, allow_assignment:)
31
+ return [:direct] if rbs_assertion_autocorrectable?(node, allow_assignment: allow_assignment)
32
+ return unless nested_rbs_assertion_autocorrectable?(node)
33
+
34
+ call_argument_context(node)
35
+ end
36
+
37
+ def call_argument_context(node)
38
+ parent = node.parent
39
+ if parent&.type?(:call) && parent.arguments.include?(node)
40
+ call = parent
41
+ target = node
42
+ elsif parent&.splat_type?
43
+ call = parent.parent
44
+ return unless call&.type?(:call) && call.arguments.include?(parent)
45
+
46
+ target = parent
47
+ elsif parent&.kwsplat_type?
48
+ argument = node.first_argument
49
+ return if argument.hash_type? && !argument.loc.begin
50
+
51
+ hash = parent.parent
52
+ return unless hash&.hash_type? && !hash.loc.begin
53
+
54
+ call = hash.parent
55
+ return unless call&.type?(:call) && call.arguments.include?(hash)
56
+
57
+ target = parent
58
+ elsif parent&.pair_type? && parent.value.equal?(node)
59
+ hash = parent.parent
60
+ return unless hash&.hash_type? && !hash.loc.begin
61
+
62
+ call = hash.parent
63
+ return unless call&.type?(:call) && call.arguments.include?(hash)
64
+
65
+ target = parent
66
+ else
67
+ return
68
+ end
69
+
70
+ return unless call.single_line? && call.loc.begin && call.loc.end
71
+ return if comments_within?(call)
72
+ return unless one_matching_assertion?(call, node)
73
+
74
+ items = call.arguments.flat_map do |argument|
75
+ argument.hash_type? && !argument.loc.begin ? argument.children : argument
76
+ end
77
+ return unless items.include?(target)
78
+
79
+ [:arguments, call, items, target]
80
+ end
81
+
82
+ def autocorrect_argument_list(corrector, node, expression, annotation, context)
83
+ _, container, items, target = context
84
+ indentation = container.source_range.source_line[/\A[ \t]*/]
85
+ item_indentation = indentation + (" " * configured_indentation_width)
86
+ splat = target.type?(:splat, :kwsplat)
87
+ target_index = items.index(target)
88
+ replacement = "#{expression} #: #{annotation}"
89
+ if splat
90
+ nested_indentation = item_indentation + (" " * configured_indentation_width)
91
+ replacement = "(\n#{nested_indentation}#{replacement}\n#{item_indentation})"
92
+ elsif target_index < items.length - 1
93
+ replacement = "#{expression}, #: #{annotation}"
94
+ end
95
+ corrector.replace(node, replacement)
96
+
97
+ corrector.replace(container.loc.begin.end.join(items.first.source_range.begin), "\n#{item_indentation}")
98
+ items.each_cons(2) do |item, next_item|
99
+ separator = item.equal?(target) && !splat ? "" : ","
100
+ corrector.replace(item.source_range.end.join(next_item.source_range.begin), "#{separator}\n#{item_indentation}")
101
+ end
102
+ corrector.replace(items.last.source_range.end.join(container.loc.end.begin), "\n#{indentation}")
103
+ end
104
+
105
+ def comments_within?(node)
106
+ range = node.source_range
107
+ processed_source.comments.any? do |comment|
108
+ comment.source_range.begin_pos >= range.begin_pos && comment.source_range.end_pos <= range.end_pos
109
+ end
110
+ end
111
+
112
+ def one_matching_assertion?(container, node)
113
+ container.each_node(:send).count do |candidate|
114
+ candidate.method?(node.method_name) &&
115
+ candidate.receiver&.const_type? &&
116
+ candidate.receiver.const_name == "T"
117
+ end == 1
118
+ end
119
+
120
+ def nested_rbs_assertion_autocorrectable?(node)
121
+ return false unless cop_config["AutocorrectToRBS"]
122
+ return false unless node.single_line?
123
+ return false if inside_single_line_block?(node)
124
+ return false if ::RuboCop::Sorbet::RBSParser.rbs_annotation_after(processed_source, node)
125
+
126
+ true
127
+ end
128
+
129
+ def inside_single_line_block?(node)
130
+ node.each_ancestor.any? { |ancestor| ancestor.type?(:block, :numblock) && ancestor.single_line? }
131
+ end
132
+
16
133
  def rbs_assertion_autocorrectable?(node, allow_assignment: false)
17
134
  return false unless cop_config["AutocorrectToRBS"]
18
135
  return false unless assertion_ends_line?(node)
@@ -733,7 +733,7 @@ foo = T.cast(self, Integer)
733
733
 
734
734
  Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
735
735
  --- | --- | --- | --- | ---
736
- Disabled | Yes | Yes (Unsafe) | 0.10.4 | 0.15.0
736
+ Disabled | Yes | Yes (Unsafe) | 0.10.4 | 0.16.0
737
737
 
738
738
  Disallows using `T.cast` anywhere.
739
739
  Set `AutocorrectToRBS: true` to replace supported calls with RBS inline comments.
@@ -814,7 +814,7 @@ end
814
814
 
815
815
  Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
816
816
  --- | --- | --- | --- | ---
817
- Disabled | Yes | Yes (Unsafe) | 0.10.4 | 0.15.0
817
+ Disabled | Yes | Yes (Unsafe) | 0.10.4 | 0.16.0
818
818
 
819
819
  Disallows using `T.let` anywhere.
820
820
  Set `AutocorrectToRBS: true` to replace supported calls with RBS inline comments.
@@ -980,7 +980,7 @@ STRING_OR_INTEGER = T.type_alias { T.any(Integer, String) }
980
980
 
981
981
  Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
982
982
  --- | --- | --- | --- | ---
983
- Disabled | Yes | Yes (Unsafe) | 0.7.0 | 0.15.0
983
+ Disabled | Yes | Yes (Unsafe) | 0.7.0 | 0.16.0
984
984
 
985
985
  Disallows using `T.unsafe` anywhere.
986
986
  Set `AutocorrectToRBS: true` to replace supported calls with RBS inline comments.
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.15.0
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ufuk Kayserilioglu