solargraph 0.56.0 → 0.58.2

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 (191) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -0
  3. data/.github/workflows/linting.yml +127 -0
  4. data/.github/workflows/plugins.yml +183 -7
  5. data/.github/workflows/rspec.yml +55 -5
  6. data/.github/workflows/typecheck.yml +6 -3
  7. data/.gitignore +6 -0
  8. data/.overcommit.yml +72 -0
  9. data/.rspec +1 -0
  10. data/.rubocop.yml +66 -0
  11. data/.rubocop_todo.yml +1279 -0
  12. data/.yardopts +1 -0
  13. data/CHANGELOG.md +92 -1
  14. data/README.md +8 -4
  15. data/Rakefile +125 -13
  16. data/bin/solargraph +3 -0
  17. data/lib/solargraph/api_map/cache.rb +110 -109
  18. data/lib/solargraph/api_map/constants.rb +279 -0
  19. data/lib/solargraph/api_map/index.rb +193 -175
  20. data/lib/solargraph/api_map/source_to_yard.rb +97 -88
  21. data/lib/solargraph/api_map/store.rb +384 -266
  22. data/lib/solargraph/api_map.rb +945 -973
  23. data/lib/solargraph/bench.rb +1 -0
  24. data/lib/solargraph/complex_type/type_methods.rb +228 -222
  25. data/lib/solargraph/complex_type/unique_type.rb +482 -475
  26. data/lib/solargraph/complex_type.rb +444 -423
  27. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  28. data/lib/solargraph/convention/base.rb +17 -0
  29. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
  30. data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
  31. data/lib/solargraph/convention/data_definition.rb +105 -0
  32. data/lib/solargraph/convention/gemspec.rb +3 -2
  33. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -60
  34. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -100
  35. data/lib/solargraph/convention/struct_definition.rb +164 -101
  36. data/lib/solargraph/convention.rb +32 -2
  37. data/lib/solargraph/diagnostics/require_not_found.rb +53 -53
  38. data/lib/solargraph/diagnostics/rubocop.rb +118 -113
  39. data/lib/solargraph/diagnostics/rubocop_helpers.rb +68 -66
  40. data/lib/solargraph/diagnostics/type_check.rb +55 -55
  41. data/lib/solargraph/doc_map.rb +439 -405
  42. data/lib/solargraph/environ.rb +9 -2
  43. data/lib/solargraph/equality.rb +34 -33
  44. data/lib/solargraph/gem_pins.rb +98 -88
  45. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  46. data/lib/solargraph/language_server/host/dispatch.rb +130 -128
  47. data/lib/solargraph/language_server/host/message_worker.rb +112 -109
  48. data/lib/solargraph/language_server/host/sources.rb +99 -99
  49. data/lib/solargraph/language_server/host.rb +878 -871
  50. data/lib/solargraph/language_server/message/base.rb +2 -1
  51. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +114 -114
  52. data/lib/solargraph/language_server/message/extended/document.rb +23 -23
  53. data/lib/solargraph/language_server/message/text_document/completion.rb +56 -56
  54. data/lib/solargraph/language_server/message/text_document/definition.rb +40 -38
  55. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +26 -26
  56. data/lib/solargraph/language_server/message/text_document/formatting.rb +148 -131
  57. data/lib/solargraph/language_server/message/text_document/hover.rb +58 -58
  58. data/lib/solargraph/language_server/message/text_document/signature_help.rb +24 -24
  59. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -24
  60. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
  61. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -23
  62. data/lib/solargraph/language_server/progress.rb +8 -0
  63. data/lib/solargraph/language_server/request.rb +4 -1
  64. data/lib/solargraph/library.rb +683 -666
  65. data/lib/solargraph/location.rb +82 -79
  66. data/lib/solargraph/logging.rb +37 -28
  67. data/lib/solargraph/page.rb +3 -0
  68. data/lib/solargraph/parser/comment_ripper.rb +69 -62
  69. data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -227
  70. data/lib/solargraph/parser/node_processor/base.rb +92 -87
  71. data/lib/solargraph/parser/node_processor.rb +62 -46
  72. data/lib/solargraph/parser/parser_gem/class_methods.rb +149 -159
  73. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
  74. data/lib/solargraph/parser/parser_gem/node_chainer.rb +166 -164
  75. data/lib/solargraph/parser/parser_gem/node_methods.rb +486 -497
  76. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -21
  77. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +59 -59
  78. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +15 -15
  79. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +46 -45
  80. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +1 -21
  81. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +53 -53
  82. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -21
  83. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +40 -40
  84. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +29 -29
  85. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +59 -53
  86. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +0 -22
  87. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -41
  88. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -16
  89. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +38 -37
  90. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +52 -43
  91. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +291 -271
  92. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +1 -0
  93. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -29
  94. data/lib/solargraph/parser/parser_gem/node_processors.rb +70 -66
  95. data/lib/solargraph/parser/region.rb +69 -66
  96. data/lib/solargraph/parser/snippet.rb +17 -15
  97. data/lib/solargraph/pin/base.rb +729 -651
  98. data/lib/solargraph/pin/base_variable.rb +126 -125
  99. data/lib/solargraph/pin/block.rb +104 -103
  100. data/lib/solargraph/pin/breakable.rb +9 -9
  101. data/lib/solargraph/pin/callable.rb +231 -218
  102. data/lib/solargraph/pin/closure.rb +72 -74
  103. data/lib/solargraph/pin/common.rb +79 -75
  104. data/lib/solargraph/pin/constant.rb +2 -0
  105. data/lib/solargraph/pin/conversions.rb +123 -123
  106. data/lib/solargraph/pin/delegated_method.rb +120 -120
  107. data/lib/solargraph/pin/documenting.rb +114 -114
  108. data/lib/solargraph/pin/instance_variable.rb +34 -34
  109. data/lib/solargraph/pin/keyword.rb +20 -20
  110. data/lib/solargraph/pin/local_variable.rb +75 -76
  111. data/lib/solargraph/pin/method.rb +672 -651
  112. data/lib/solargraph/pin/method_alias.rb +34 -31
  113. data/lib/solargraph/pin/namespace.rb +115 -115
  114. data/lib/solargraph/pin/parameter.rb +275 -261
  115. data/lib/solargraph/pin/proxy_type.rb +39 -35
  116. data/lib/solargraph/pin/reference/override.rb +47 -33
  117. data/lib/solargraph/pin/reference/superclass.rb +15 -10
  118. data/lib/solargraph/pin/reference.rb +39 -22
  119. data/lib/solargraph/pin/search.rb +61 -56
  120. data/lib/solargraph/pin/signature.rb +61 -59
  121. data/lib/solargraph/pin/symbol.rb +53 -48
  122. data/lib/solargraph/pin/until.rb +18 -18
  123. data/lib/solargraph/pin/while.rb +18 -18
  124. data/lib/solargraph/pin.rb +44 -44
  125. data/lib/solargraph/pin_cache.rb +245 -185
  126. data/lib/solargraph/position.rb +132 -116
  127. data/lib/solargraph/range.rb +112 -107
  128. data/lib/solargraph/rbs_map/conversions.rb +823 -773
  129. data/lib/solargraph/rbs_map/core_fills.rb +18 -0
  130. data/lib/solargraph/rbs_map/core_map.rb +58 -51
  131. data/lib/solargraph/rbs_map/stdlib_map.rb +43 -43
  132. data/lib/solargraph/rbs_map.rb +163 -150
  133. data/lib/solargraph/shell.rb +352 -268
  134. data/lib/solargraph/source/chain/call.rb +337 -333
  135. data/lib/solargraph/source/chain/constant.rb +26 -89
  136. data/lib/solargraph/source/chain/hash.rb +34 -34
  137. data/lib/solargraph/source/chain/if.rb +28 -28
  138. data/lib/solargraph/source/chain/instance_variable.rb +13 -13
  139. data/lib/solargraph/source/chain/link.rb +11 -2
  140. data/lib/solargraph/source/chain/literal.rb +48 -48
  141. data/lib/solargraph/source/chain/or.rb +23 -23
  142. data/lib/solargraph/source/chain.rb +291 -282
  143. data/lib/solargraph/source/change.rb +82 -82
  144. data/lib/solargraph/source/cursor.rb +166 -167
  145. data/lib/solargraph/source/encoding_fixes.rb +23 -23
  146. data/lib/solargraph/source/source_chainer.rb +194 -194
  147. data/lib/solargraph/source/updater.rb +55 -55
  148. data/lib/solargraph/source.rb +498 -495
  149. data/lib/solargraph/source_map/clip.rb +226 -234
  150. data/lib/solargraph/source_map/data.rb +34 -30
  151. data/lib/solargraph/source_map/mapper.rb +259 -259
  152. data/lib/solargraph/source_map.rb +212 -200
  153. data/lib/solargraph/type_checker/checks.rb +124 -124
  154. data/lib/solargraph/type_checker/param_def.rb +37 -35
  155. data/lib/solargraph/type_checker/problem.rb +32 -32
  156. data/lib/solargraph/type_checker/rules.rb +84 -62
  157. data/lib/solargraph/type_checker.rb +814 -699
  158. data/lib/solargraph/version.rb +5 -5
  159. data/lib/solargraph/workspace/config.rb +255 -239
  160. data/lib/solargraph/workspace/require_paths.rb +97 -0
  161. data/lib/solargraph/workspace.rb +220 -249
  162. data/lib/solargraph/yard_map/helpers.rb +44 -16
  163. data/lib/solargraph/yard_map/mapper/to_constant.rb +5 -5
  164. data/lib/solargraph/yard_map/mapper/to_method.rb +130 -134
  165. data/lib/solargraph/yard_map/mapper/to_namespace.rb +31 -30
  166. data/lib/solargraph/yard_map/mapper.rb +79 -79
  167. data/lib/solargraph/yard_map/to_method.rb +89 -88
  168. data/lib/solargraph/yardoc.rb +87 -49
  169. data/lib/solargraph.rb +105 -90
  170. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  171. data/rbs/fills/open3/0/open3.rbs +172 -0
  172. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  173. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  174. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  175. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  176. data/rbs/fills/{tuple.rbs → tuple/tuple.rbs} +2 -3
  177. data/rbs/shims/ast/0/node.rbs +5 -0
  178. data/rbs/shims/ast/2.4/.rbs_meta.yaml +9 -0
  179. data/rbs/shims/ast/2.4/ast.rbs +73 -0
  180. data/rbs/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  181. data/rbs/shims/parser/3.2.0.1/manifest.yaml +7 -0
  182. data/rbs/shims/parser/3.2.0.1/parser.rbs +201 -0
  183. data/rbs/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  184. data/rbs/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  185. data/rbs/shims/thor/1.2.0.1/manifest.yaml +7 -0
  186. data/rbs/shims/thor/1.2.0.1/thor.rbs +17 -0
  187. data/rbs_collection.yaml +4 -4
  188. data/solargraph.gemspec +26 -5
  189. metadata +187 -15
  190. data/lib/.rubocop.yml +0 -22
  191. data/lib/solargraph/parser/node_methods.rb +0 -97
@@ -1,475 +1,482 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- class ComplexType
5
- # An individual type signature. A complex type can consist of multiple
6
- # unique types.
7
- #
8
- class UniqueType
9
- include TypeMethods
10
- include Equality
11
-
12
- attr_reader :all_params, :subtypes, :key_types
13
-
14
- # @sg-ignore Fix "Not enough arguments to Module#protected"
15
- protected def equality_fields
16
- [@name, @all_params, @subtypes, @key_types]
17
- end
18
-
19
- # Create a UniqueType with the specified name and an optional substring.
20
- # The substring is the parameter section of a parametrized type, e.g.,
21
- # for the type `Array<String>`, the name is `Array` and the substring is
22
- # `<String>`.
23
- #
24
- # @param name [String] The name of the type
25
- # @param substring [String] The substring of the type
26
- # @param make_rooted [Boolean, nil]
27
- # @return [UniqueType]
28
- def self.parse name, substring = '', make_rooted: nil
29
- if name.start_with?(':::')
30
- raise ComplexTypeError, "Illegal prefix: #{name}"
31
- end
32
- if name.start_with?('::')
33
- name = name[2..-1]
34
- rooted = true
35
- elsif !can_root_name?(name)
36
- rooted = true
37
- else
38
- rooted = false
39
- end
40
- rooted = make_rooted unless make_rooted.nil?
41
-
42
- # @type [Array<ComplexType>]
43
- key_types = []
44
- # @type [Array<ComplexType>]
45
- subtypes = []
46
- parameters_type = nil
47
- unless substring.empty?
48
- subs = ComplexType.parse(substring[1..-2], partial: true)
49
- parameters_type = PARAMETERS_TYPE_BY_STARTING_TAG.fetch(substring[0])
50
- if parameters_type == :hash
51
- raise ComplexTypeError, "Bad hash type: name=#{name}, substring=#{substring}" unless !subs.is_a?(ComplexType) and subs.length == 2 and !subs[0].is_a?(UniqueType) and !subs[1].is_a?(UniqueType)
52
- # @todo should be able to resolve map; both types have it
53
- # with same return type
54
- # @sg-ignore
55
- key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
56
- # @sg-ignore
57
- subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
58
- elsif parameters_type == :list && name == 'Hash'
59
- # Treat Hash<A, B> as Hash{A => B}
60
- if subs.length != 2
61
- raise ComplexTypeError, "Bad hash type: name=#{name}, substring=#{substring} - must have exactly two parameters"
62
- end
63
- key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
64
- subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
65
- else
66
- subtypes.concat subs
67
- end
68
- end
69
- new(name, key_types, subtypes, rooted: rooted, parameters_type: parameters_type)
70
- end
71
-
72
- # @param name [String]
73
- # @param key_types [Array<ComplexType>]
74
- # @param subtypes [Array<ComplexType>]
75
- # @param rooted [Boolean]
76
- # @param parameters_type [Symbol, nil]
77
- def initialize(name, key_types = [], subtypes = [], rooted:, parameters_type: nil)
78
- if parameters_type.nil?
79
- raise "You must supply parameters_type if you provide parameters" unless key_types.empty? && subtypes.empty?
80
- end
81
- raise "Please remove leading :: and set rooted instead - #{name.inspect}" if name.start_with?('::')
82
- @name = name
83
- @parameters_type = parameters_type
84
- if implicit_union?
85
- @key_types = key_types.uniq
86
- @subtypes = subtypes.uniq
87
- else
88
- @key_types = key_types
89
- @subtypes = subtypes
90
- end
91
- @rooted = rooted
92
- @all_params = []
93
- @all_params.concat @key_types
94
- @all_params.concat @subtypes
95
- end
96
-
97
- def implicit_union?
98
- # @todo use api_map to establish number of generics in type;
99
- # if only one is allowed but multiple are passed in, treat
100
- # those as implicit unions
101
- ['Hash', 'Array', 'Set', '_ToAry', 'Enumerable', '_Each'].include?(name) && parameters_type != :fixed
102
- end
103
-
104
- def to_s
105
- tag
106
- end
107
-
108
- def simplify_literals
109
- transform do |t|
110
- next t unless t.literal?
111
- t.recreate(new_name: t.non_literal_name)
112
- end
113
- end
114
-
115
- def literal?
116
- non_literal_name != name
117
- end
118
-
119
- def non_literal_name
120
- @non_literal_name ||= determine_non_literal_name
121
- end
122
-
123
- def determine_non_literal_name
124
- # https://github.com/ruby/rbs/blob/master/docs/syntax.md
125
- #
126
- # _literal_ ::= _string-literal_
127
- # | _symbol-literal_
128
- # | _integer-literal_
129
- # | `true`
130
- # | `false`
131
- return name if name.empty?
132
- return 'NilClass' if name == 'nil'
133
- return 'Boolean' if ['true', 'false'].include?(name)
134
- return 'Symbol' if name[0] == ':'
135
- return 'String' if ['"', "'"].include?(name[0])
136
- return 'Integer' if name.match?(/^-?\d+$/)
137
- name
138
- end
139
-
140
- def eql?(other)
141
- self.class == other.class &&
142
- @name == other.name &&
143
- @key_types == other.key_types &&
144
- @subtypes == other.subtypes &&
145
- @rooted == other.rooted? &&
146
- @all_params == other.all_params &&
147
- @parameters_type == other.parameters_type
148
- end
149
-
150
- def ==(other)
151
- eql?(other)
152
- end
153
-
154
- def hash
155
- [self.class, @name, @key_types, @sub_types, @rooted, @all_params, @parameters_type].hash
156
- end
157
-
158
- # @return [Array<UniqueType>]
159
- def items
160
- [self]
161
- end
162
-
163
- # @return [String]
164
- def rbs_name
165
- if name == 'undefined'
166
- 'untyped'
167
- elsif literal?
168
- name
169
- else
170
- rooted_name
171
- end
172
- end
173
-
174
- def desc
175
- rooted_tags
176
- end
177
-
178
- # @return [String]
179
- def to_rbs
180
- if duck_type?
181
- 'untyped'
182
- elsif name == 'Boolean'
183
- 'bool'
184
- elsif name.downcase == 'nil'
185
- 'nil'
186
- elsif name == GENERIC_TAG_NAME
187
- all_params.first.name
188
- elsif ['Class', 'Module'].include?(name)
189
- rbs_name
190
- elsif ['Tuple', 'Array'].include?(name) && fixed_parameters?
191
- # tuples don't have a name; they're just [foo, bar, baz].
192
- if substring == '()'
193
- # but there are no zero element tuples, so we go with an array
194
- if rooted?
195
- '::Array[]'
196
- else
197
- 'Array[]'
198
- end
199
- else
200
- # already generated surrounded by []
201
- parameters_as_rbs
202
- end
203
- else
204
- "#{rbs_name}#{parameters_as_rbs}"
205
- end
206
- end
207
-
208
- # @return [Boolean]
209
- def parameters?
210
- !all_params.empty?
211
- end
212
-
213
- # @param types [Array<UniqueType, ComplexType>]
214
- # @return [String]
215
- def rbs_union(types)
216
- if types.length == 1
217
- types.first.to_rbs
218
- else
219
- "(#{types.map(&:to_rbs).join(' | ')})"
220
- end
221
- end
222
-
223
- # @return [String]
224
- def parameters_as_rbs
225
- return '' unless parameters?
226
-
227
- return "[#{all_params.map(&:to_rbs).join(', ')}]" if key_types.empty?
228
-
229
- # handle, e.g., Hash[K, V] case
230
- key_types_str = rbs_union(key_types)
231
- subtypes_str = rbs_union(subtypes)
232
- "[#{key_types_str}, #{subtypes_str}]"
233
- end
234
-
235
- def generic?
236
- name == GENERIC_TAG_NAME || all_params.any?(&:generic?)
237
- end
238
-
239
- # @param api_map [ApiMap] The ApiMap that performs qualification
240
- # @param atype [ComplexType] type which may be assigned to this type
241
- def can_assign?(api_map, atype)
242
- logger.debug { "UniqueType#can_assign?(self=#{rooted_tags.inspect}, atype=#{atype.rooted_tags.inspect})" }
243
- downcasted_atype = atype.downcast_to_literal_if_possible
244
- out = downcasted_atype.all? do |autype|
245
- autype.name == name || api_map.super_and_sub?(name, autype.name)
246
- end
247
- logger.debug { "UniqueType#can_assign?(self=#{rooted_tags.inspect}, atype=#{atype.rooted_tags.inspect}) => #{out}" }
248
- out
249
- end
250
-
251
- # @return [UniqueType]
252
- def downcast_to_literal_if_possible
253
- SINGLE_SUBTYPE.fetch(rooted_tag, self)
254
- end
255
-
256
- # @param generics_to_resolve [Enumerable<String>]
257
- # @param context_type [UniqueType, nil]
258
- # @param resolved_generic_values [Hash{String => ComplexType}] Added to as types are encountered or resolved
259
- # @return [UniqueType, ComplexType]
260
- def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
261
- if name == ComplexType::GENERIC_TAG_NAME
262
- type_param = subtypes.first&.name
263
- return self unless generics_to_resolve.include? type_param
264
- unless context_type.nil? || !resolved_generic_values[type_param].nil?
265
- new_binding = true
266
- resolved_generic_values[type_param] = context_type
267
- end
268
- if new_binding
269
- resolved_generic_values.transform_values! do |complex_type|
270
- complex_type.resolve_generics_from_context(generics_to_resolve, nil, resolved_generic_values: resolved_generic_values)
271
- end
272
- end
273
- return resolved_generic_values[type_param] || self
274
- end
275
-
276
- # @todo typechecking should complain when the method being called has no @yieldparam tag
277
- new_key_types = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values, &:key_types)
278
- new_subtypes = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values, &:subtypes)
279
- recreate(new_key_types: new_key_types, new_subtypes: new_subtypes)
280
- end
281
-
282
- # @param generics_to_resolve [Enumerable<String>]
283
- # @param context_type [UniqueType]
284
- # @param resolved_generic_values [Hash{String => ComplexType}]
285
- # @yieldreturn [Array<ComplexType>]
286
- # @return [Array<ComplexType>]
287
- def resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values)
288
- types = yield self
289
- types.each_with_index.flat_map do |ct, i|
290
- ct.items.flat_map do |ut|
291
- context_params = yield context_type if context_type
292
- if context_params && context_params[i]
293
- type_arg = context_params[i]
294
- type_arg.map do |new_unique_context_type|
295
- ut.resolve_generics_from_context generics_to_resolve, new_unique_context_type, resolved_generic_values: resolved_generic_values
296
- end
297
- else
298
- ut.resolve_generics_from_context generics_to_resolve, nil, resolved_generic_values: resolved_generic_values
299
- end
300
- end
301
- end
302
- end
303
-
304
- # Probe the concrete type for each of the generic type
305
- # parameters used in this type, and return a new type if
306
- # possible.
307
- #
308
- # @param definitions [Pin::Namespace, Pin::Method] The module/class/method which uses generic types
309
- # @param context_type [ComplexType] The receiver type
310
- # @return [UniqueType, ComplexType]
311
- def resolve_generics definitions, context_type
312
- return self if definitions.nil? || definitions.generics.empty?
313
-
314
- transform(name) do |t|
315
- if t.name == GENERIC_TAG_NAME
316
- generic_name = t.subtypes.first&.name
317
- idx = definitions.generics.index(generic_name)
318
- next t if idx.nil?
319
- if context_type.parameters_type == :hash
320
- if idx == 0
321
- next ComplexType.new(context_type.key_types)
322
- elsif idx == 1
323
- next ComplexType.new(context_type.subtypes)
324
- else
325
- next ComplexType::UNDEFINED
326
- end
327
- elsif context_type.all?(&:implicit_union?)
328
- if idx == 0 && !context_type.all_params.empty?
329
- ComplexType.new(context_type.all_params)
330
- else
331
- ComplexType::UNDEFINED
332
- end
333
- else
334
- context_type.all_params[idx] || definitions.generic_defaults[generic_name] || ComplexType::UNDEFINED
335
- end
336
- else
337
- t
338
- end
339
- end
340
- end
341
-
342
- # @yieldparam t [self]
343
- # @yieldreturn [self]
344
- # @return [Array<self>]
345
- def map &block
346
- [block.yield(self)]
347
- end
348
-
349
- # @return [Array<UniqueType>]
350
- def to_a
351
- [self]
352
- end
353
-
354
- # @param new_name [String, nil]
355
- # @param make_rooted [Boolean, nil]
356
- # @param new_key_types [Array<UniqueType>, nil]
357
- # @param rooted [Boolean, nil]
358
- # @param new_subtypes [Array<UniqueType>, nil]
359
- # @return [self]
360
- def recreate(new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil)
361
- raise "Please remove leading :: and set rooted instead - #{new_name}" if new_name&.start_with?('::')
362
-
363
- new_name ||= name
364
- new_key_types ||= @key_types
365
- new_subtypes ||= @subtypes
366
- make_rooted = @rooted if make_rooted.nil?
367
- UniqueType.new(new_name, new_key_types, new_subtypes, rooted: make_rooted, parameters_type: parameters_type)
368
- end
369
-
370
- # @return [String]
371
- def rooted_tags
372
- rooted_tag
373
- end
374
-
375
- # @return [String]
376
- def tags
377
- tag
378
- end
379
-
380
- # @return [self]
381
- def force_rooted
382
- transform do |t|
383
- t.recreate(make_rooted: true)
384
- end
385
- end
386
-
387
- # Apply the given transformation to each subtype and then finally to this type
388
- #
389
- # @param new_name [String, nil]
390
- # @yieldparam t [UniqueType]
391
- # @yieldreturn [self]
392
- # @return [self]
393
- def transform(new_name = nil, &transform_type)
394
- raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}" if new_name&.start_with?('::')
395
- if name == ComplexType::GENERIC_TAG_NAME
396
- # doesn't make sense to manipulate the name of the generic
397
- new_key_types = @key_types
398
- new_subtypes = @subtypes
399
- else
400
- new_key_types = @key_types.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
401
- new_subtypes = @subtypes.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
402
- end
403
- new_type = recreate(new_name: new_name || name, new_key_types: new_key_types, new_subtypes: new_subtypes, make_rooted: @rooted)
404
- yield new_type
405
- end
406
-
407
- # Generate a ComplexType that fully qualifies this type's namespaces.
408
- #
409
- # @param api_map [ApiMap] The ApiMap that performs qualification
410
- # @param context [String] The namespace from which to resolve names
411
- # @return [self, ComplexType, UniqueType] The generated ComplexType
412
- def qualify api_map, context = ''
413
- transform do |t|
414
- next t if t.name == GENERIC_TAG_NAME
415
- next t if t.duck_type? || t.void? || t.undefined?
416
- recon = (t.rooted? ? '' : context)
417
- fqns = api_map.qualify(t.name, recon)
418
- if fqns.nil?
419
- next UniqueType::BOOLEAN if t.tag == 'Boolean'
420
- next UniqueType::UNDEFINED
421
- end
422
- t.recreate(new_name: fqns, make_rooted: true)
423
- end
424
- end
425
-
426
- def selfy?
427
- @name == 'self' || @key_types.any?(&:selfy?) || @subtypes.any?(&:selfy?)
428
- end
429
-
430
- # @param dst [ComplexType]
431
- # @return [self]
432
- def self_to_type dst
433
- object_type_dst = dst.reduce_class_type
434
- transform do |t|
435
- next t if t.name != 'self'
436
- object_type_dst
437
- end
438
- end
439
-
440
- def all_rooted?
441
- return true if name == GENERIC_TAG_NAME
442
- rooted? && all_params.all?(&:rooted?)
443
- end
444
-
445
- def rooted?
446
- !can_root_name? || @rooted
447
- end
448
-
449
- def can_root_name?(name_to_check = name)
450
- self.class.can_root_name?(name_to_check)
451
- end
452
-
453
- # @param name [String]
454
- def self.can_root_name?(name)
455
- # name is not lowercase
456
- !name.empty? && name != name.downcase
457
- end
458
-
459
- UNDEFINED = UniqueType.new('undefined', rooted: false)
460
- BOOLEAN = UniqueType.new('Boolean', rooted: true)
461
- TRUE = UniqueType.new('true', rooted: true)
462
- FALSE = UniqueType.new('false', rooted: true)
463
- NIL = UniqueType.new('nil', rooted: true)
464
- # @type [Hash{String => UniqueType}]
465
- SINGLE_SUBTYPE = {
466
- '::TrueClass' => UniqueType::TRUE,
467
- '::FalseClass' => UniqueType::FALSE,
468
- '::NilClass' => UniqueType::NIL
469
- }.freeze
470
-
471
-
472
- include Logging
473
- end
474
- end
475
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class ComplexType
5
+ # An individual type signature. A complex type can consist of multiple
6
+ # unique types.
7
+ #
8
+ class UniqueType
9
+ include TypeMethods
10
+ include Equality
11
+
12
+ attr_reader :all_params, :subtypes, :key_types
13
+
14
+ # @sg-ignore Fix "Not enough arguments to Module#protected"
15
+ protected def equality_fields
16
+ [@name, @all_params, @subtypes, @key_types]
17
+ end
18
+
19
+ # Create a UniqueType with the specified name and an optional substring.
20
+ # The substring is the parameter section of a parametrized type, e.g.,
21
+ # for the type `Array<String>`, the name is `Array` and the substring is
22
+ # `<String>`.
23
+ #
24
+ # @param name [String] The name of the type
25
+ # @param substring [String] The substring of the type
26
+ # @param make_rooted [Boolean, nil]
27
+ # @return [UniqueType]
28
+ def self.parse name, substring = '', make_rooted: nil
29
+ if name.start_with?(':::')
30
+ raise ComplexTypeError, "Illegal prefix: #{name}"
31
+ end
32
+ if name.start_with?('::')
33
+ name = name[2..-1]
34
+ rooted = true
35
+ elsif !can_root_name?(name)
36
+ rooted = true
37
+ else
38
+ rooted = false
39
+ end
40
+ rooted = make_rooted unless make_rooted.nil?
41
+
42
+ # @type [Array<ComplexType>]
43
+ key_types = []
44
+ # @type [Array<ComplexType>]
45
+ subtypes = []
46
+ parameters_type = nil
47
+ unless substring.empty?
48
+ subs = ComplexType.parse(substring[1..-2], partial: true)
49
+ parameters_type = PARAMETERS_TYPE_BY_STARTING_TAG.fetch(substring[0])
50
+ if parameters_type == :hash
51
+ raise ComplexTypeError, "Bad hash type: name=#{name}, substring=#{substring}" unless !subs.is_a?(ComplexType) and subs.length == 2 and !subs[0].is_a?(UniqueType) and !subs[1].is_a?(UniqueType)
52
+ key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
53
+ subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
54
+ elsif parameters_type == :list && name == 'Hash'
55
+ # Treat Hash<A, B> as Hash{A => B}
56
+ if subs.length != 2
57
+ raise ComplexTypeError, "Bad hash type: name=#{name}, substring=#{substring} - must have exactly two parameters"
58
+ end
59
+ key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
60
+ subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
61
+ else
62
+ subtypes.concat subs
63
+ end
64
+ end
65
+ new(name, key_types, subtypes, rooted: rooted, parameters_type: parameters_type)
66
+ end
67
+
68
+ # @param name [String]
69
+ # @param key_types [Array<ComplexType>]
70
+ # @param subtypes [Array<ComplexType>]
71
+ # @param rooted [Boolean]
72
+ # @param parameters_type [Symbol, nil]
73
+ def initialize(name, key_types = [], subtypes = [], rooted:, parameters_type: nil)
74
+ if parameters_type.nil?
75
+ raise "You must supply parameters_type if you provide parameters" unless key_types.empty? && subtypes.empty?
76
+ end
77
+ raise "Please remove leading :: and set rooted instead - #{name.inspect}" if name.start_with?('::')
78
+ @name = name
79
+ @parameters_type = parameters_type
80
+ if implicit_union?
81
+ @key_types = key_types.uniq
82
+ @subtypes = subtypes.uniq
83
+ else
84
+ @key_types = key_types
85
+ @subtypes = subtypes
86
+ end
87
+ @rooted = rooted
88
+ @all_params = []
89
+ @all_params.concat @key_types
90
+ @all_params.concat @subtypes
91
+ end
92
+
93
+ def implicit_union?
94
+ # @todo use api_map to establish number of generics in type;
95
+ # if only one is allowed but multiple are passed in, treat
96
+ # those as implicit unions
97
+ ['Hash', 'Array', 'Set', '_ToAry', 'Enumerable', '_Each'].include?(name) && parameters_type != :fixed
98
+ end
99
+
100
+ def to_s
101
+ tag
102
+ end
103
+
104
+ # @return [self]
105
+ def simplify_literals
106
+ transform do |t|
107
+ next t unless t.literal?
108
+ t.recreate(new_name: t.non_literal_name)
109
+ end
110
+ end
111
+
112
+ def literal?
113
+ non_literal_name != name
114
+ end
115
+
116
+ # @return [String]
117
+ def non_literal_name
118
+ @non_literal_name ||= determine_non_literal_name
119
+ end
120
+
121
+ # @return [String]
122
+ def determine_non_literal_name
123
+ # https://github.com/ruby/rbs/blob/master/docs/syntax.md
124
+ #
125
+ # _literal_ ::= _string-literal_
126
+ # | _symbol-literal_
127
+ # | _integer-literal_
128
+ # | `true`
129
+ # | `false`
130
+ return name if name.empty?
131
+ return 'NilClass' if name == 'nil'
132
+ return 'Boolean' if ['true', 'false'].include?(name)
133
+ return 'Symbol' if name[0] == ':'
134
+ return 'String' if ['"', "'"].include?(name[0])
135
+ return 'Integer' if name.match?(/^-?\d+$/)
136
+ name
137
+ end
138
+
139
+ def eql?(other)
140
+ self.class == other.class &&
141
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
142
+ @name == other.name &&
143
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
144
+ @key_types == other.key_types &&
145
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
146
+ @subtypes == other.subtypes &&
147
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
148
+ @rooted == other.rooted? &&
149
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
150
+ @all_params == other.all_params &&
151
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
152
+ @parameters_type == other.parameters_type
153
+ end
154
+
155
+ def ==(other)
156
+ eql?(other)
157
+ end
158
+
159
+ def hash
160
+ [self.class, @name, @key_types, @sub_types, @rooted, @all_params, @parameters_type].hash
161
+ end
162
+
163
+ # @return [Array<UniqueType>]
164
+ def items
165
+ [self]
166
+ end
167
+
168
+ # @return [String]
169
+ def rbs_name
170
+ if name == 'undefined'
171
+ 'untyped'
172
+ elsif literal?
173
+ name
174
+ else
175
+ rooted_name
176
+ end
177
+ end
178
+
179
+ # @return [String]
180
+ def desc
181
+ rooted_tags
182
+ end
183
+
184
+ # @return [String]
185
+ def to_rbs
186
+ if duck_type?
187
+ 'untyped'
188
+ elsif name == 'Boolean'
189
+ 'bool'
190
+ elsif name.downcase == 'nil'
191
+ 'nil'
192
+ elsif name == GENERIC_TAG_NAME
193
+ all_params.first.name
194
+ elsif ['Class', 'Module'].include?(name)
195
+ rbs_name
196
+ elsif ['Tuple', 'Array'].include?(name) && fixed_parameters?
197
+ # tuples don't have a name; they're just [foo, bar, baz].
198
+ if substring == '()'
199
+ # but there are no zero element tuples, so we go with an array
200
+ if rooted?
201
+ '::Array[]'
202
+ else
203
+ 'Array[]'
204
+ end
205
+ else
206
+ # already generated surrounded by []
207
+ parameters_as_rbs
208
+ end
209
+ else
210
+ "#{rbs_name}#{parameters_as_rbs}"
211
+ end
212
+ end
213
+
214
+ # @return [Boolean]
215
+ def parameters?
216
+ !all_params.empty?
217
+ end
218
+
219
+ # @param types [Array<UniqueType, ComplexType>]
220
+ # @return [String]
221
+ def rbs_union(types)
222
+ if types.length == 1
223
+ types.first.to_rbs
224
+ else
225
+ "(#{types.map(&:to_rbs).join(' | ')})"
226
+ end
227
+ end
228
+
229
+ # @return [String]
230
+ def parameters_as_rbs
231
+ return '' unless parameters?
232
+
233
+ return "[#{all_params.map(&:to_rbs).join(', ')}]" if key_types.empty?
234
+
235
+ # handle, e.g., Hash[K, V] case
236
+ key_types_str = rbs_union(key_types)
237
+ subtypes_str = rbs_union(subtypes)
238
+ "[#{key_types_str}, #{subtypes_str}]"
239
+ end
240
+
241
+ def generic?
242
+ name == GENERIC_TAG_NAME || all_params.any?(&:generic?)
243
+ end
244
+
245
+ # @param api_map [ApiMap] The ApiMap that performs qualification
246
+ # @param atype [ComplexType] type which may be assigned to this type
247
+ def can_assign?(api_map, atype)
248
+ logger.debug { "UniqueType#can_assign?(self=#{rooted_tags.inspect}, atype=#{atype.rooted_tags.inspect})" }
249
+ downcasted_atype = atype.downcast_to_literal_if_possible
250
+ out = downcasted_atype.all? do |autype|
251
+ autype.name == name || api_map.super_and_sub?(name, autype.name)
252
+ end
253
+ logger.debug { "UniqueType#can_assign?(self=#{rooted_tags.inspect}, atype=#{atype.rooted_tags.inspect}) => #{out}" }
254
+ out
255
+ end
256
+
257
+ # @return [UniqueType]
258
+ def downcast_to_literal_if_possible
259
+ SINGLE_SUBTYPE.fetch(rooted_tag, self)
260
+ end
261
+
262
+ # @param generics_to_resolve [Enumerable<String>]
263
+ # @param context_type [UniqueType, nil]
264
+ # @param resolved_generic_values [Hash{String => ComplexType, ComplexType::UniqueType}] Added to as types are encountered or resolved
265
+ # @return [UniqueType, ComplexType]
266
+ def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
267
+ if name == ComplexType::GENERIC_TAG_NAME
268
+ type_param = subtypes.first&.name
269
+ return self unless generics_to_resolve.include? type_param
270
+ unless context_type.nil? || !resolved_generic_values[type_param].nil?
271
+ new_binding = true
272
+ resolved_generic_values[type_param] = context_type
273
+ end
274
+ if new_binding
275
+ resolved_generic_values.transform_values! do |complex_type|
276
+ complex_type.resolve_generics_from_context(generics_to_resolve, nil, resolved_generic_values: resolved_generic_values)
277
+ end
278
+ end
279
+ return resolved_generic_values[type_param] || self
280
+ end
281
+
282
+ # @todo typechecking should complain when the method being called has no @yieldparam tag
283
+ new_key_types = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values, &:key_types)
284
+ new_subtypes = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values, &:subtypes)
285
+ recreate(new_key_types: new_key_types, new_subtypes: new_subtypes)
286
+ end
287
+
288
+ # @param generics_to_resolve [Enumerable<String>]
289
+ # @param context_type [UniqueType, nil]
290
+ # @param resolved_generic_values [Hash{String => ComplexType}]
291
+ # @yieldreturn [Array<ComplexType>]
292
+ # @return [Array<ComplexType>]
293
+ def resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values)
294
+ types = yield self
295
+ types.each_with_index.flat_map do |ct, i|
296
+ ct.items.flat_map do |ut|
297
+ context_params = yield context_type if context_type
298
+ if context_params && context_params[i]
299
+ type_arg = context_params[i]
300
+ type_arg.map do |new_unique_context_type|
301
+ ut.resolve_generics_from_context generics_to_resolve, new_unique_context_type, resolved_generic_values: resolved_generic_values
302
+ end
303
+ else
304
+ ut.resolve_generics_from_context generics_to_resolve, nil, resolved_generic_values: resolved_generic_values
305
+ end
306
+ end
307
+ end
308
+ end
309
+
310
+ # Probe the concrete type for each of the generic type
311
+ # parameters used in this type, and return a new type if
312
+ # possible.
313
+ #
314
+ # @param definitions [Pin::Namespace, Pin::Method] The module/class/method which uses generic types
315
+ # @param context_type [ComplexType] The receiver type
316
+ # @return [UniqueType, ComplexType]
317
+ def resolve_generics definitions, context_type
318
+ return self if definitions.nil? || definitions.generics.empty?
319
+
320
+ transform(name) do |t|
321
+ if t.name == GENERIC_TAG_NAME
322
+ generic_name = t.subtypes.first&.name
323
+ idx = definitions.generics.index(generic_name)
324
+ next t if idx.nil?
325
+ if context_type.parameters_type == :hash
326
+ if idx == 0
327
+ next ComplexType.new(context_type.key_types)
328
+ elsif idx == 1
329
+ next ComplexType.new(context_type.subtypes)
330
+ else
331
+ next ComplexType::UNDEFINED
332
+ end
333
+ elsif context_type.all?(&:implicit_union?)
334
+ if idx == 0 && !context_type.all_params.empty?
335
+ ComplexType.new(context_type.all_params)
336
+ else
337
+ ComplexType::UNDEFINED
338
+ end
339
+ else
340
+ context_type.all_params[idx] || definitions.generic_defaults[generic_name] || ComplexType::UNDEFINED
341
+ end
342
+ else
343
+ t
344
+ end
345
+ end
346
+ end
347
+
348
+ # @yieldparam t [self]
349
+ # @yieldreturn [self]
350
+ # @return [Array<self>]
351
+ def map &block
352
+ [block.yield(self)]
353
+ end
354
+
355
+ # @return [Array<UniqueType>]
356
+ def to_a
357
+ [self]
358
+ end
359
+
360
+ # @param new_name [String, nil]
361
+ # @param make_rooted [Boolean, nil]
362
+ # @param new_key_types [Array<ComplexType>, nil]
363
+ # @param rooted [Boolean, nil]
364
+ # @param new_subtypes [Array<ComplexType>, nil]
365
+ # @return [self]
366
+ def recreate(new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil)
367
+ raise "Please remove leading :: and set rooted instead - #{new_name}" if new_name&.start_with?('::')
368
+
369
+ new_name ||= name
370
+ new_key_types ||= @key_types
371
+ new_subtypes ||= @subtypes
372
+ make_rooted = @rooted if make_rooted.nil?
373
+ UniqueType.new(new_name, new_key_types, new_subtypes, rooted: make_rooted, parameters_type: parameters_type)
374
+ end
375
+
376
+ # @return [String]
377
+ def rooted_tags
378
+ rooted_tag
379
+ end
380
+
381
+ # @return [String]
382
+ def tags
383
+ tag
384
+ end
385
+
386
+ # @return [self]
387
+ def force_rooted
388
+ transform do |t|
389
+ t.recreate(make_rooted: true)
390
+ end
391
+ end
392
+
393
+ # Apply the given transformation to each subtype and then finally to this type
394
+ #
395
+ # @param new_name [String, nil]
396
+ # @yieldparam t [UniqueType]
397
+ # @yieldreturn [self]
398
+ # @return [self]
399
+ def transform(new_name = nil, &transform_type)
400
+ raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}" if new_name&.start_with?('::')
401
+ if name == ComplexType::GENERIC_TAG_NAME
402
+ # doesn't make sense to manipulate the name of the generic
403
+ new_key_types = @key_types
404
+ new_subtypes = @subtypes
405
+ else
406
+ new_key_types = @key_types.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
407
+ new_subtypes = @subtypes.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
408
+ end
409
+ new_type = recreate(new_name: new_name || name, new_key_types: new_key_types, new_subtypes: new_subtypes, make_rooted: @rooted)
410
+ yield new_type
411
+ end
412
+
413
+ # Generate a ComplexType that fully qualifies this type's namespaces.
414
+ #
415
+ # @param api_map [ApiMap] The ApiMap that performs qualification
416
+ # @param context [String] The namespace from which to resolve names
417
+ # @return [self, ComplexType, UniqueType] The generated ComplexType
418
+ def qualify api_map, *gates
419
+ transform do |t|
420
+ next t if t.name == GENERIC_TAG_NAME
421
+ next t if t.duck_type? || t.void? || t.undefined? || t.literal?
422
+ open = t.rooted? ? [''] : gates
423
+ fqns = api_map.qualify(t.non_literal_name, *open)
424
+ if fqns.nil?
425
+ next UniqueType::BOOLEAN if t.tag == 'Boolean'
426
+ next UniqueType::UNDEFINED
427
+ end
428
+ t.recreate(new_name: fqns, make_rooted: true)
429
+ end
430
+ end
431
+
432
+ def selfy?
433
+ @name == 'self' || @key_types.any?(&:selfy?) || @subtypes.any?(&:selfy?)
434
+ end
435
+
436
+ # @param dst [ComplexType]
437
+ # @return [self]
438
+ def self_to_type dst
439
+ object_type_dst = dst.reduce_class_type
440
+ transform do |t|
441
+ next t if t.name != 'self'
442
+ object_type_dst
443
+ end
444
+ end
445
+
446
+ def all_rooted?
447
+ return true if name == GENERIC_TAG_NAME
448
+ rooted? && all_params.all?(&:rooted?)
449
+ end
450
+
451
+ def rooted?
452
+ !can_root_name? || @rooted
453
+ end
454
+
455
+ # @param name_to_check [String]
456
+ def can_root_name?(name_to_check = name)
457
+ self.class.can_root_name?(name_to_check)
458
+ end
459
+
460
+ # @param name [String]
461
+ def self.can_root_name?(name)
462
+ # name is not lowercase
463
+ !name.empty? && name != name.downcase
464
+ end
465
+
466
+ UNDEFINED = UniqueType.new('undefined', rooted: false)
467
+ BOOLEAN = UniqueType.new('Boolean', rooted: true)
468
+ TRUE = UniqueType.new('true', rooted: true)
469
+ FALSE = UniqueType.new('false', rooted: true)
470
+ NIL = UniqueType.new('nil', rooted: true)
471
+ # @type [Hash{String => UniqueType}]
472
+ SINGLE_SUBTYPE = {
473
+ '::TrueClass' => UniqueType::TRUE,
474
+ '::FalseClass' => UniqueType::FALSE,
475
+ '::NilClass' => UniqueType::NIL
476
+ }.freeze
477
+
478
+
479
+ include Logging
480
+ end
481
+ end
482
+ end