rubocop-on-rbs 0.2.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.
Files changed (36) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/CODE_OF_CONDUCT.md +84 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +186 -0
  6. data/config/default.yml +165 -0
  7. data/lib/rubocop/cop/rbs/layout/comment_indentation.rb +69 -0
  8. data/lib/rubocop/cop/rbs/layout/empty_lines_around_overloads.rb +49 -0
  9. data/lib/rubocop/cop/rbs/layout/end_alignment.rb +55 -0
  10. data/lib/rubocop/cop/rbs/layout/extra_spacing.rb +55 -0
  11. data/lib/rubocop/cop/rbs/layout/indentation_width.rb +64 -0
  12. data/lib/rubocop/cop/rbs/layout/overload_indentation.rb +69 -0
  13. data/lib/rubocop/cop/rbs/layout/space_around_arrow.rb +56 -0
  14. data/lib/rubocop/cop/rbs/layout/space_around_braces.rb +77 -0
  15. data/lib/rubocop/cop/rbs/layout/space_before_colon.rb +43 -0
  16. data/lib/rubocop/cop/rbs/layout/space_before_overload.rb +46 -0
  17. data/lib/rubocop/cop/rbs/layout/trailing_whitespace.rb +42 -0
  18. data/lib/rubocop/cop/rbs/lint/syntax.rb +18 -0
  19. data/lib/rubocop/cop/rbs/lint/type_params_arity.rb +170 -0
  20. data/lib/rubocop/cop/rbs/lint/useless_overload_type_params.rb +57 -0
  21. data/lib/rubocop/cop/rbs/lint/will_syntax_error.rb +205 -0
  22. data/lib/rubocop/cop/rbs/style/block_return_boolish.rb +35 -0
  23. data/lib/rubocop/cop/rbs/style/classic_type.rb +73 -0
  24. data/lib/rubocop/cop/rbs/style/duplicated_type.rb +61 -0
  25. data/lib/rubocop/cop/rbs/style/initialize_return_type.rb +40 -0
  26. data/lib/rubocop/cop/rbs/style/merge_untyped.rb +91 -0
  27. data/lib/rubocop/cop/rbs/style/optional_nil.rb +50 -0
  28. data/lib/rubocop/cop/rbs/style/true_false.rb +84 -0
  29. data/lib/rubocop/cop/rbs_cops.rb +28 -0
  30. data/lib/rubocop/rbs/cop_base.rb +91 -0
  31. data/lib/rubocop/rbs/inject.rb +20 -0
  32. data/lib/rubocop/rbs/processed_rbs_source.rb +29 -0
  33. data/lib/rubocop/rbs/version.rb +7 -0
  34. data/lib/rubocop/rbs.rb +15 -0
  35. data/lib/rubocop-on-rbs.rb +13 -0
  36. metadata +106 -0
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RBS
6
+ module Lint
7
+ # Notice useless overload type parameters.
8
+ #
9
+ # @example default
10
+ # # bad
11
+ # def foo: [T] () -> void
12
+ #
13
+ # # bad
14
+ # def bar: [T, U] (T) -> void
15
+ #
16
+ # # good
17
+ # def foo: [T] (Array[T]) -> T
18
+ class UselessOverloadTypeParams < RuboCop::RBS::CopBase
19
+ MSG = 'Useless overload type variable - `%<variable>s`.'
20
+
21
+ def on_rbs_def(decl)
22
+ decl.overloads.each do |overload|
23
+ next if overload.method_type.type_params.empty?
24
+
25
+ type_params = overload.method_type.type_params
26
+
27
+ overload.method_type.each_type do |type|
28
+ used_variable_in_type(type) do |var|
29
+ type_params.delete_if { |type_param| type_param.name == var.name }
30
+ end
31
+ end
32
+ next if type_params.empty?
33
+
34
+ type_params.each do |type_param|
35
+ next unless type_param.location
36
+
37
+ t = location_to_range(type_param.location[:name])
38
+ add_offense(t, message: format(MSG, variable: type_param.name), severity: :warning)
39
+ end
40
+ end
41
+ end
42
+
43
+ def used_variable_in_type(type, &block)
44
+ case type
45
+ when ::RBS::Types::Variable
46
+ yield type
47
+ else
48
+ type.each_type do |t|
49
+ used_variable_in_type(t, &block)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,205 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RBS
6
+ module Lint
7
+ # This cop checks the WillSyntaxError in RBS.
8
+ # RBS with this diagnostics will fail in `rbs validate` command.
9
+ #
10
+ # @example default
11
+ # # bad
12
+ # def foo: (void) -> void
13
+ #
14
+ # # bad
15
+ # CONST: self
16
+ class WillSyntaxError < RuboCop::RBS::CopBase
17
+ # @rbs!
18
+ # module Types = ::RBS::Types
19
+ # module AST = ::RBS::AST
20
+
21
+ # @rbs skip
22
+ AST = ::RBS::AST
23
+ # @rbs skip
24
+ Types = ::RBS::Types
25
+
26
+ def on_rbs_class(decl)
27
+ if super_class = decl.super_class
28
+ super_class.args.each do |arg|
29
+ void_type_context_validator(arg, true)
30
+ no_self_type_validator(arg)
31
+ no_classish_type_validator(arg)
32
+ end
33
+ end
34
+ check_module_or_class(decl)
35
+ end
36
+
37
+ def on_rbs_module(decl)
38
+ decl.self_types.each do |self_type|
39
+ self_type.args.each do |arg|
40
+ void_type_context_validator(arg, true)
41
+ no_self_type_validator(arg)
42
+ no_classish_type_validator(arg)
43
+ end
44
+ end
45
+ check_module_or_class(decl)
46
+ end
47
+
48
+ def check_module_or_class(decl)
49
+ decl.type_params.each do |param|
50
+ if ub = param.upper_bound
51
+ void_type_context_validator(ub)
52
+ no_self_type_validator(ub)
53
+ no_classish_type_validator(ub)
54
+ end
55
+ end
56
+
57
+ decl.each_member do |member|
58
+ case member
59
+ when AST::Members::MethodDefinition
60
+ member.overloads.each do |ov|
61
+ void_type_context_validator(ov.method_type)
62
+ end
63
+ when AST::Members::Attribute
64
+ void_type_context_validator(member.type)
65
+ when AST::Members::Mixin
66
+ member.args.each do |arg|
67
+ no_self_type_validator(arg)
68
+ unless arg.is_a?(Types::Bases::Void)
69
+ void_type_context_validator(arg, true)
70
+ end
71
+ end
72
+ when AST::Members::Var
73
+ void_type_context_validator(member.type)
74
+ if member.is_a?(AST::Members::ClassVariable)
75
+ no_self_type_validator(member.type)
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ def on_rbs_interface(decl)
82
+ decl.members.each do |member|
83
+ case member
84
+ when AST::Members::MethodDefinition
85
+ member.overloads.each do |ov|
86
+ void_type_context_validator(ov.method_type)
87
+ no_classish_type_validator(ov.method_type)
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ def on_rbs_constant(decl)
94
+ no_self_type_validator(decl.type)
95
+ no_classish_type_validator(decl.type)
96
+ void_type_context_validator(decl.type)
97
+ end
98
+ alias on_rbs_global on_rbs_constant
99
+ alias on_rbs_type_alias on_rbs_constant
100
+
101
+ private
102
+
103
+ # @rbs type: ::RBS::Types::t
104
+ def no_self_type_validator(type)
105
+ case type
106
+ when ::RBS::MethodType,
107
+ Types::Record,
108
+ Types::Tuple,
109
+ Types::Union,
110
+ Types::Intersection,
111
+ Types::Optional,
112
+ Types::ClassInstance,
113
+ Types::Proc
114
+ type.each_type do |t|
115
+ no_self_type_validator(t)
116
+ end
117
+ else
118
+ if type.has_self_type?
119
+ offence(type, "`self` type is not allowed in this context")
120
+ end
121
+ end
122
+ end
123
+
124
+ # @rbs type: ::RBS::MethodType | ::RBS::Types::t
125
+ def no_classish_type_validator(type)
126
+ case type
127
+ when ::RBS::MethodType,
128
+ Types::Record,
129
+ Types::Tuple,
130
+ Types::Union,
131
+ Types::Intersection,
132
+ Types::Optional,
133
+ Types::ClassInstance,
134
+ Types::Proc
135
+ type.each_type do |t|
136
+ no_classish_type_validator(t)
137
+ end
138
+ when Types::Bases::Instance
139
+ offence(type, "`instance` type is not allowed in this context")
140
+ when Types::Bases::Class
141
+ offence(type, "`class` type is not allowed in this context")
142
+ else
143
+ if type.has_classish_type?
144
+ offence(type, "`instance` or `class` type is not allowed in this context")
145
+ end
146
+ end
147
+ end
148
+
149
+ # @rbs type: ::RBS::MethodType | ::RBS::Types::Function | ::RBS::Types::t
150
+ # @rbs allowed_here: bool
151
+ def void_type_context_validator(type, allowed_here = false)
152
+ return if type.is_a?(Types::UntypedFunction)
153
+
154
+ case type
155
+ when ::RBS::MethodType
156
+ void_type_context_validator(type.type)
157
+ when Types::Function
158
+ type.each_param do |param|
159
+ void_type_context_validator(param.type)
160
+ end
161
+ case type.return_type
162
+ when Types::Bases::Void
163
+ # `() -> void` is allowed
164
+ else
165
+ void_type_context_validator(type.return_type, true)
166
+ end
167
+ when Types::Proc
168
+ void_type_context_validator(type.type)
169
+ if type.block
170
+ void_type_context_validator(type.block.type)
171
+ void_type_context_validator(type.block.self_type) if type.block.self_type
172
+ end
173
+ when Types::ClassInstance
174
+ type.args.each do |arg|
175
+ next if arg.is_a?(Types::Bases::Void)
176
+
177
+ void_type_context_validator(arg)
178
+ end
179
+ when Types::Record,
180
+ Types::Tuple,
181
+ Types::Union,
182
+ Types::Intersection,
183
+ Types::Optional
184
+ type.each_type do |t|
185
+ void_type_context_validator(t)
186
+ end
187
+ else
188
+ if allowed_here
189
+ return if type.is_a?(Types::Bases::Void)
190
+ end
191
+ if type.with_nonreturn_void?
192
+ offence(type, "`void` type is only allowed in return type or generics parameter")
193
+ end
194
+ end
195
+ end
196
+
197
+ def offence(decl, message)
198
+ range = location_to_range(decl.location)
199
+ add_offense(range, message: message)
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RBS
6
+ module Style
7
+ # @example default
8
+ # # bad
9
+ # def foo: () { () -> bool } -> void
10
+ #
11
+ # # good
12
+ # def foo: () { () -> boolish } -> void
13
+ class BlockReturnBoolish < RuboCop::RBS::CopBase
14
+ extend AutoCorrector
15
+ MSG = 'Use `boolish` instead of `bool` in block return type.'
16
+
17
+ # @sig decl: ::RBS::AST::Members::MethodDefinition
18
+ def on_rbs_def(decl)
19
+ decl.overloads.each do |overload|
20
+ next unless overload.method_type.block
21
+
22
+ return_type = overload.method_type.block.type.return_type
23
+ next unless return_type.is_a?(::RBS::Types::Bases::Bool)
24
+
25
+ range = location_to_range(return_type.location)
26
+ add_offense(range) do |corrector|
27
+ corrector.replace(range, 'boolish')
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RBS
6
+ module Style
7
+ # @example default
8
+ # # bad
9
+ # def foo: () -> TrueClass
10
+ #
11
+ # # bad
12
+ # def bar: () -> NilClass
13
+ #
14
+ # # good
15
+ # def foo: () -> true
16
+ #
17
+ # # good
18
+ # def bar: () -> nil
19
+ class ClassicType < RuboCop::RBS::CopBase
20
+ extend AutoCorrector
21
+
22
+ Types = ::RBS::Types
23
+
24
+ def on_rbs_def(decl)
25
+ decl.overloads.each do |overload|
26
+ overload.method_type.each_type do |type|
27
+ check_type(type)
28
+ end
29
+ end
30
+ end
31
+
32
+ # @rbs type: ::RBS::Types::t
33
+ def check_type(type)
34
+ find_replacement(type) do |t, replaced|
35
+ range = location_to_range(t.location)
36
+ add_offense(range, message: "Use `#{replaced}` instead of `#{t}`") do |corrector|
37
+ corrector.replace(range, replaced)
38
+ end
39
+ end
40
+ end
41
+
42
+ def find_replacement(type, &block)
43
+ case type
44
+ when Types::Record,
45
+ Types::Tuple,
46
+ Types::Union,
47
+ Types::Intersection,
48
+ Types::Optional,
49
+ Types::Proc,
50
+ Types::Alias,
51
+ Types::Interface
52
+ type.each_type do |t|
53
+ find_replacement(t, &block)
54
+ end
55
+ when Types::ClassInstance
56
+ case type.name.to_s
57
+ when 'TrueClass', '::TrueClass'
58
+ block.call([type, 'true'])
59
+ when 'FalseClass', '::FalseClass'
60
+ block.call([type, 'false'])
61
+ when 'NilClass', '::NilClass'
62
+ block.call([type, 'nil'])
63
+ end
64
+ type.each_type do |arg|
65
+ find_replacement(arg, &block)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RBS
6
+ module Style
7
+ # @example default
8
+ # # bad
9
+ # def foo: (Integer | Integer) -> void
10
+ #
11
+ # # bad
12
+ # def foo: (Integer & Integer) -> void
13
+ #
14
+ # # good
15
+ # def foo: (Integer) -> void
16
+ class DuplicatedType < RuboCop::RBS::CopBase
17
+ extend AutoCorrector
18
+
19
+ # @sig decl: ::RBS::AST::Members::MethodDefinition
20
+ def on_rbs_def(decl)
21
+ decl.overloads.each do |overload|
22
+ overload.method_type.each_type do |type|
23
+ check_type(type)
24
+ end
25
+ end
26
+ end
27
+
28
+ # @rbs type: ::RBS::Types::t
29
+ def check_type(type)
30
+ case type
31
+ when ::RBS::Types::Record,
32
+ ::RBS::Types::Tuple,
33
+ ::RBS::Types::Optional,
34
+ ::RBS::Types::ClassInstance,
35
+ ::RBS::Types::Proc
36
+ type.each_type do |t|
37
+ check_type(t)
38
+ end
39
+ when ::RBS::Types::Union,
40
+ ::RBS::Types::Intersection
41
+ set = Set.new
42
+ type.types.each do |t|
43
+ if set.include?(t)
44
+ if t.location
45
+ range = location_to_range(t.location)
46
+ add_offense(range, message: "Duplicated type `#{t}`.")
47
+ end
48
+ else
49
+ set.add(t)
50
+ end
51
+ end
52
+ type.each_type do |t|
53
+ check_type(t)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RBS
6
+ module Style
7
+ # @example default
8
+ # # bad
9
+ # def initialize: () -> untyped
10
+ #
11
+ # # bad
12
+ # def initialize: () -> nil
13
+ #
14
+ # # good
15
+ # def initialize: () -> void
16
+ class InitializeReturnType < RuboCop::RBS::CopBase
17
+ extend AutoCorrector
18
+ MSG = '`#initialize` method should return `void`'
19
+
20
+ # @sig decl: ::RBS::AST::Members::MethodDefinition
21
+ def on_rbs_def(decl)
22
+ return unless decl.name == :initialize
23
+ return unless decl.kind == :instance
24
+ return unless decl.overloading == false
25
+
26
+ decl.overloads.each do |overload|
27
+ return_type = overload.method_type.type.return_type
28
+ next if return_type.is_a?(::RBS::Types::Bases::Void)
29
+
30
+ range = location_to_range(return_type.location)
31
+ add_offense(range) do |corrector|
32
+ corrector.replace(range, 'void')
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RBS
6
+ module Style
7
+ # @example default
8
+ # # bad
9
+ # def foo: (untyped?) -> untyped?
10
+ #
11
+ # # bad
12
+ # def foo: (Integer | untyped) -> (Integer | untyped)
13
+ #
14
+ # # bad
15
+ # def foo: (Integer & untyped) -> (Integer & untyped)
16
+ #
17
+ # # good
18
+ # def foo: (untyped) -> untyped
19
+ class MergeUntyped < RuboCop::RBS::CopBase
20
+ extend AutoCorrector
21
+
22
+ # @sig decl: ::RBS::AST::Members::MethodDefinition
23
+ def on_rbs_def(decl)
24
+ decl.overloads.each do |overload|
25
+ overload.method_type.type.tap do |fun|
26
+ fun.each_param do |param|
27
+ check_type(param.type)
28
+ end
29
+ check_type(fun.return_type)
30
+ end
31
+ end
32
+ end
33
+
34
+ def check_type(type)
35
+ find_replacement(type) do |method, t, replaced|
36
+ case method
37
+ when :replace
38
+ range = location_to_range(t.location)
39
+ add_offense(range, message: "Use `#{replaced}` instead of `#{t}`") do |corrector|
40
+ corrector.replace(range, replaced.to_s)
41
+ end
42
+ when :remove
43
+ range = t
44
+ add_offense(range, message: "Remove `?` in Optional") do |corrector|
45
+ corrector.remove(range)
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ def find_replacement(type, &block)
52
+ case type
53
+ when ::RBS::Types::Optional
54
+ case type.type
55
+ when ::RBS::Types::Bases::Any,
56
+ ::RBS::Types::Bases::Nil,
57
+ ::RBS::Types::Bases::Void,
58
+ ::RBS::Types::Bases::Top,
59
+ ::RBS::Types::Bases::Bottom
60
+ # untyped? => untyped
61
+ block.call([:replace, type, type.type])
62
+ when ::RBS::Types::Optional
63
+ # (Integer?)? => Integer?
64
+ range = Parser::Source::Range.new(processed_source.buffer, type.type.location.end_pos - 1,
65
+ type.type.location.end_pos)
66
+ block.call([:remove, range])
67
+ find_replacement(type.type, &block)
68
+ when ::RBS::Types::Union, ::RBS::Types::Intersection
69
+ find_replacement(type.type, &block)
70
+ end
71
+ when ::RBS::Types::Union, ::RBS::Types::Intersection
72
+ # (untyped | Integer) => untyped
73
+ # (untyped & Integer) => untyped
74
+ if type.types.any? { |t| t.is_a?(::RBS::Types::Bases::Any) }
75
+ block.call([:replace, type, 'untyped'])
76
+ end
77
+
78
+ uniqed = type.types.uniq
79
+ if uniqed.size < type.types.size
80
+ block.call([:replace, type, type.class.new(types: uniqed, location: nil)])
81
+ end
82
+ type.types.each do |t|
83
+ find_replacement(t, &block)
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RBS
6
+ module Style
7
+ # @example default
8
+ # # bad
9
+ # def foo: (nil?) -> void
10
+ #
11
+ # # good
12
+ # def foo: (nil) -> void
13
+ class OptionalNil < RuboCop::RBS::CopBase
14
+ extend AutoCorrector
15
+
16
+ # @sig decl: ::RBS::AST::Members::MethodDefinition
17
+ def on_rbs_def(decl)
18
+ decl.overloads.each do |overload|
19
+ overload.method_type.each_type do |type|
20
+ find_replacement(type) do |t, replaced|
21
+ range = location_to_range(t.location)
22
+ add_offense(range, message: "Use `#{replaced}` instead of `#{t}`") do |corrector|
23
+ corrector.replace(range, replaced.to_s)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ # @rbs type: ::RBS::Types::t
31
+ def find_replacement(type, &block)
32
+ case type
33
+ when ::RBS::Types::Optional
34
+ case type.type
35
+ when ::RBS::Types::Bases::Nil
36
+ block.call([type, ::RBS::Types::Bases::Nil.new(location: nil)])
37
+ else
38
+ find_replacement(type.type, &block)
39
+ end
40
+ else
41
+ type.each_type do |type|
42
+ find_replacement(type, &block)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RBS
6
+ module Style
7
+ # @example default
8
+ # # bad
9
+ # def foo: (true | false) -> (true | false)
10
+ #
11
+ # # bad
12
+ # def foo: (TrueClass | FalseClass) -> (TrueClass | FalseClass)
13
+ #
14
+ # # good
15
+ # def foo: (bool) -> bool
16
+ class TrueFalse < RuboCop::RBS::CopBase
17
+ extend AutoCorrector
18
+
19
+ # @sig decl: ::RBS::AST::Members::MethodDefinition
20
+ def on_rbs_def(decl)
21
+ decl.overloads.each do |overload|
22
+ overload.method_type.each_type do |type|
23
+ find_replacement(type) do |t, replaced|
24
+ range = location_to_range(t.location)
25
+ add_offense(range, message: "Use `#{replaced}` instead of `#{t}`") do |corrector|
26
+ corrector.replace(range, replaced.to_s)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ # @rbs type: ::RBS::Types::t
34
+ def find_replacement(type, &block)
35
+ case type
36
+ when ::RBS::Types::Union
37
+ has_true = has_false = false
38
+ type.types.each do |t|
39
+ case t
40
+ when ::RBS::Types::Literal
41
+ has_true = true if t.literal == true
42
+ has_false = true if t.literal == false
43
+ when ::RBS::Types::ClassInstance
44
+ case t.name.to_s
45
+ when 'TrueClass', '::TrueClass'
46
+ has_true = true
47
+ when 'FalseClass', '::FalseClass'
48
+ has_false = true
49
+ end
50
+ end
51
+ end
52
+ if has_true && has_false
53
+ replaced = type.types.dup
54
+ first_index = nil
55
+ i = -1
56
+ replaced.delete_if do |t|
57
+ i += 1
58
+ case t
59
+ when ::RBS::Types::Literal
60
+ (t.literal == true || t.literal == false).tap do |r|
61
+ first_index ||= i if r
62
+ end
63
+ when ::RBS::Types::ClassInstance
64
+ t.name.to_s.then do |s|
65
+ s == 'TrueClass' || s == '::TrueClass' || s == 'FalseClass' || s == '::FalseClass'
66
+ end.tap do |r|
67
+ first_index ||= i if r
68
+ end
69
+ end
70
+ end
71
+ replaced.insert(first_index || 0, ::RBS::Types::Bases::Bool.new(location: nil))
72
+ block.call([type, ::RBS::Types::Union.new(types: replaced, location: nil)])
73
+ end
74
+ else
75
+ type.each_type do |type|
76
+ find_replacement(type, &block)
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end