solargraph 0.54.0 → 0.58.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 (200) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linting.yml +127 -0
  3. data/.github/workflows/plugins.yml +184 -6
  4. data/.github/workflows/rspec.yml +55 -5
  5. data/.github/workflows/typecheck.yml +8 -3
  6. data/.gitignore +7 -0
  7. data/.overcommit.yml +72 -0
  8. data/.rspec +1 -0
  9. data/.rubocop.yml +66 -0
  10. data/.rubocop_todo.yml +1279 -0
  11. data/.yardopts +1 -0
  12. data/CHANGELOG.md +171 -0
  13. data/README.md +20 -6
  14. data/Rakefile +125 -13
  15. data/bin/solargraph +8 -5
  16. data/lib/solargraph/api_map/cache.rb +13 -3
  17. data/lib/solargraph/api_map/constants.rb +279 -0
  18. data/lib/solargraph/api_map/index.rb +193 -0
  19. data/lib/solargraph/api_map/source_to_yard.rb +13 -4
  20. data/lib/solargraph/api_map/store.rb +207 -132
  21. data/lib/solargraph/api_map.rb +394 -261
  22. data/lib/solargraph/bench.rb +18 -1
  23. data/lib/solargraph/complex_type/type_methods.rb +29 -12
  24. data/lib/solargraph/complex_type/unique_type.rb +205 -26
  25. data/lib/solargraph/complex_type.rb +126 -26
  26. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  27. data/lib/solargraph/convention/base.rb +20 -3
  28. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
  29. data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
  30. data/lib/solargraph/convention/data_definition.rb +105 -0
  31. data/lib/solargraph/convention/gemspec.rb +3 -2
  32. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -0
  33. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -0
  34. data/lib/solargraph/convention/struct_definition.rb +164 -0
  35. data/lib/solargraph/convention.rb +36 -4
  36. data/lib/solargraph/diagnostics/rubocop.rb +6 -1
  37. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  38. data/lib/solargraph/doc_map.rb +316 -64
  39. data/lib/solargraph/environ.rb +9 -2
  40. data/lib/solargraph/equality.rb +34 -0
  41. data/lib/solargraph/gem_pins.rb +64 -38
  42. data/lib/solargraph/language_server/host/dispatch.rb +2 -0
  43. data/lib/solargraph/language_server/host/message_worker.rb +54 -5
  44. data/lib/solargraph/language_server/host.rb +36 -18
  45. data/lib/solargraph/language_server/message/base.rb +20 -12
  46. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -0
  47. data/lib/solargraph/language_server/message/extended/document.rb +5 -2
  48. data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
  49. data/lib/solargraph/language_server/message/initialize.rb +3 -1
  50. data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
  51. data/lib/solargraph/language_server/message/text_document/definition.rb +5 -3
  52. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +3 -3
  53. data/lib/solargraph/language_server/message/text_document/formatting.rb +23 -2
  54. data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
  55. data/lib/solargraph/language_server/message/text_document/type_definition.rb +4 -3
  56. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
  57. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -2
  58. data/lib/solargraph/language_server/progress.rb +27 -2
  59. data/lib/solargraph/language_server/request.rb +4 -1
  60. data/lib/solargraph/library.rb +83 -73
  61. data/lib/solargraph/location.rb +45 -1
  62. data/lib/solargraph/logging.rb +12 -2
  63. data/lib/solargraph/page.rb +3 -0
  64. data/lib/solargraph/parser/comment_ripper.rb +20 -7
  65. data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -0
  66. data/lib/solargraph/parser/node_processor/base.rb +10 -5
  67. data/lib/solargraph/parser/node_processor.rb +26 -8
  68. data/lib/solargraph/parser/parser_gem/class_methods.rb +10 -18
  69. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
  70. data/lib/solargraph/parser/parser_gem/node_chainer.rb +13 -11
  71. data/lib/solargraph/parser/parser_gem/node_methods.rb +10 -19
  72. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
  73. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -0
  74. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +26 -20
  75. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +7 -4
  76. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +2 -1
  77. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
  78. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -3
  79. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +2 -1
  80. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
  81. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -0
  82. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +4 -2
  83. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -1
  84. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +14 -2
  85. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +8 -7
  86. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -0
  87. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -0
  88. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +3 -1
  89. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +16 -6
  90. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +64 -32
  91. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +3 -1
  92. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
  93. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
  94. data/lib/solargraph/parser/parser_gem/node_processors.rb +14 -0
  95. data/lib/solargraph/parser/region.rb +4 -1
  96. data/lib/solargraph/parser/snippet.rb +2 -0
  97. data/lib/solargraph/parser.rb +3 -5
  98. data/lib/solargraph/pin/base.rb +417 -42
  99. data/lib/solargraph/pin/base_variable.rb +21 -12
  100. data/lib/solargraph/pin/block.rb +9 -26
  101. data/lib/solargraph/pin/breakable.rb +9 -0
  102. data/lib/solargraph/pin/callable.rb +231 -0
  103. data/lib/solargraph/pin/closure.rb +30 -10
  104. data/lib/solargraph/pin/common.rb +12 -7
  105. data/lib/solargraph/pin/constant.rb +2 -0
  106. data/lib/solargraph/pin/conversions.rb +3 -2
  107. data/lib/solargraph/pin/delegated_method.rb +20 -1
  108. data/lib/solargraph/pin/documenting.rb +16 -0
  109. data/lib/solargraph/pin/instance_variable.rb +2 -2
  110. data/lib/solargraph/pin/keyword.rb +7 -2
  111. data/lib/solargraph/pin/local_variable.rb +15 -7
  112. data/lib/solargraph/pin/method.rb +241 -70
  113. data/lib/solargraph/pin/method_alias.rb +3 -0
  114. data/lib/solargraph/pin/namespace.rb +21 -13
  115. data/lib/solargraph/pin/parameter.rb +94 -32
  116. data/lib/solargraph/pin/proxy_type.rb +17 -7
  117. data/lib/solargraph/pin/reference/override.rb +24 -6
  118. data/lib/solargraph/pin/reference/require.rb +2 -2
  119. data/lib/solargraph/pin/reference/superclass.rb +5 -0
  120. data/lib/solargraph/pin/reference.rb +17 -0
  121. data/lib/solargraph/pin/search.rb +6 -1
  122. data/lib/solargraph/pin/signature.rb +39 -121
  123. data/lib/solargraph/pin/singleton.rb +1 -1
  124. data/lib/solargraph/pin/symbol.rb +8 -2
  125. data/lib/solargraph/pin/until.rb +18 -0
  126. data/lib/solargraph/pin/while.rb +18 -0
  127. data/lib/solargraph/pin.rb +8 -2
  128. data/lib/solargraph/pin_cache.rb +245 -0
  129. data/lib/solargraph/position.rb +19 -0
  130. data/lib/solargraph/range.rb +23 -4
  131. data/lib/solargraph/rbs_map/conversions.rb +315 -99
  132. data/lib/solargraph/rbs_map/core_fills.rb +50 -16
  133. data/lib/solargraph/rbs_map/core_map.rb +41 -11
  134. data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
  135. data/lib/solargraph/rbs_map.rb +87 -16
  136. data/lib/solargraph/shell.rb +117 -17
  137. data/lib/solargraph/source/chain/array.rb +13 -8
  138. data/lib/solargraph/source/chain/block_symbol.rb +1 -1
  139. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  140. data/lib/solargraph/source/chain/call.rb +135 -66
  141. data/lib/solargraph/source/chain/constant.rb +3 -66
  142. data/lib/solargraph/source/chain/hash.rb +9 -3
  143. data/lib/solargraph/source/chain/head.rb +1 -1
  144. data/lib/solargraph/source/chain/if.rb +7 -2
  145. data/lib/solargraph/source/chain/link.rb +38 -6
  146. data/lib/solargraph/source/chain/literal.rb +27 -2
  147. data/lib/solargraph/source/chain/or.rb +2 -2
  148. data/lib/solargraph/source/chain/z_super.rb +1 -1
  149. data/lib/solargraph/source/chain.rb +140 -63
  150. data/lib/solargraph/source/change.rb +2 -2
  151. data/lib/solargraph/source/cursor.rb +4 -4
  152. data/lib/solargraph/source/source_chainer.rb +3 -3
  153. data/lib/solargraph/source.rb +110 -89
  154. data/lib/solargraph/source_map/clip.rb +22 -28
  155. data/lib/solargraph/source_map/data.rb +34 -0
  156. data/lib/solargraph/source_map/mapper.rb +11 -7
  157. data/lib/solargraph/source_map.rb +50 -43
  158. data/lib/solargraph/type_checker/checks.rb +4 -0
  159. data/lib/solargraph/type_checker/param_def.rb +2 -0
  160. data/lib/solargraph/type_checker/rules.rb +35 -8
  161. data/lib/solargraph/type_checker.rb +331 -189
  162. data/lib/solargraph/version.rb +1 -1
  163. data/lib/solargraph/views/_method.erb +10 -10
  164. data/lib/solargraph/views/_namespace.erb +3 -3
  165. data/lib/solargraph/views/document.erb +10 -10
  166. data/lib/solargraph/views/environment.erb +3 -5
  167. data/lib/solargraph/workspace/config.rb +25 -5
  168. data/lib/solargraph/workspace/require_paths.rb +97 -0
  169. data/lib/solargraph/workspace.rb +53 -72
  170. data/lib/solargraph/yard_map/helpers.rb +29 -1
  171. data/lib/solargraph/yard_map/mapper/to_constant.rb +8 -5
  172. data/lib/solargraph/yard_map/mapper/to_method.rb +55 -19
  173. data/lib/solargraph/yard_map/mapper/to_namespace.rb +11 -7
  174. data/lib/solargraph/yard_map/mapper.rb +5 -3
  175. data/lib/solargraph/yard_map/to_method.rb +6 -3
  176. data/lib/solargraph/yardoc.rb +45 -10
  177. data/lib/solargraph.rb +35 -1
  178. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  179. data/rbs/fills/open3/0/open3.rbs +172 -0
  180. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  181. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  182. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  183. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  184. data/rbs/fills/tuple/tuple.rbs +149 -0
  185. data/rbs_collection.yaml +19 -0
  186. data/sig/shims/ast/0/node.rbs +5 -0
  187. data/sig/shims/ast/2.4/.rbs_meta.yaml +9 -0
  188. data/sig/shims/ast/2.4/ast.rbs +73 -0
  189. data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  190. data/sig/shims/parser/3.2.0.1/manifest.yaml +7 -0
  191. data/sig/shims/parser/3.2.0.1/parser.rbs +201 -0
  192. data/sig/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  193. data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  194. data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
  195. data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
  196. data/solargraph.gemspec +32 -10
  197. metadata +237 -37
  198. data/lib/.rubocop.yml +0 -22
  199. data/lib/solargraph/cache.rb +0 -77
  200. data/lib/solargraph/parser/node_methods.rb +0 -83
@@ -11,18 +11,35 @@ module Solargraph
11
11
  # @return [Workspace]
12
12
  attr_reader :workspace
13
13
 
14
+ # @return [SourceMap]
15
+ attr_reader :live_map
16
+
14
17
  # @return [Set<String>]
15
18
  attr_reader :external_requires
16
19
 
17
20
  # @param source_maps [Array<SourceMap>, Set<SourceMap>]
18
21
  # @param workspace [Workspace]
22
+ # @param live_map [SourceMap, nil]
19
23
  # @param external_requires [Array<String>, Set<String>]
20
- def initialize source_maps: [], workspace: Workspace.new, external_requires: []
24
+ def initialize source_maps: [], workspace: Workspace.new, live_map: nil, external_requires: []
21
25
  @source_maps = source_maps.to_set
22
26
  @workspace = workspace
27
+ @live_map = live_map
23
28
  @external_requires = external_requires.reject { |path| workspace.would_require?(path) }
24
29
  .compact
25
30
  .to_set
26
31
  end
32
+
33
+ # @return [Hash{String => SourceMap}]
34
+ def source_map_hash
35
+ # @todo Work around #to_h bug in current Ruby head (3.5) with #map#to_h
36
+ @source_map_hash ||= source_maps.map { |s| [s.filename, s] }
37
+ .to_h
38
+ end
39
+
40
+ # @return [Set<SourceMap>]
41
+ def icebox
42
+ @icebox ||= (source_maps - [live_map])
43
+ end
27
44
  end
28
45
  end
@@ -12,12 +12,20 @@ module Solargraph
12
12
  # @rooted: boolish
13
13
  # methods:
14
14
  # transform()
15
+ # all_params()
16
+ # rooted?()
17
+ # can_root_name?()
15
18
  module TypeMethods
16
19
  # @!method transform(new_name = nil, &transform_type)
17
20
  # @param new_name [String, nil]
18
21
  # @yieldparam t [UniqueType]
19
22
  # @yieldreturn [UniqueType]
20
23
  # @return [UniqueType, nil]
24
+ # @!method all_params
25
+ # @return [Array<ComplexType>]
26
+ # @!method rooted?
27
+ # @!method can_root_name?(name_to_check = nil)
28
+ # @param name_to_check [String, nil]
21
29
 
22
30
  # @return [String]
23
31
  attr_reader :name
@@ -35,6 +43,10 @@ module Solargraph
35
43
  @rooted_tag ||= rooted_name + rooted_substring
36
44
  end
37
45
 
46
+ def interface?
47
+ name.start_with?('_')
48
+ end
49
+
38
50
  # @return [Boolean]
39
51
  def duck_type?
40
52
  @duck_type ||= name.start_with?('#')
@@ -45,11 +57,6 @@ module Solargraph
45
57
  @nil_type ||= (name.casecmp('nil') == 0)
46
58
  end
47
59
 
48
- # @return [Boolean]
49
- def parameters?
50
- !substring.empty?
51
- end
52
-
53
60
  def tuple?
54
61
  @tuple_type ||= (name == 'Tuple') || (name == 'Array' && subtypes.length >= 1 && fixed_parameters?)
55
62
  end
@@ -85,6 +92,7 @@ module Solargraph
85
92
  # @return [Symbol, nil]
86
93
  attr_reader :parameters_type
87
94
 
95
+ # @type [Hash{String => Symbol}]
88
96
  PARAMETERS_TYPE_BY_STARTING_TAG = {
89
97
  '{' => :hash,
90
98
  '(' => :fixed,
@@ -126,15 +134,23 @@ module Solargraph
126
134
  end.call
127
135
  end
128
136
 
137
+ # @return [self]
138
+ def namespace_type
139
+ return ComplexType.parse('::Object') if duck_type?
140
+ return ComplexType.parse('::NilClass') if nil_type?
141
+ return subtypes.first if (name == 'Class' || name == 'Module') && !subtypes.empty?
142
+ self
143
+ end
144
+
129
145
  # @return [String]
130
146
  def rooted_namespace
131
- return namespace unless rooted?
147
+ return namespace unless rooted? && can_root_name?(namespace)
132
148
  "::#{namespace}"
133
149
  end
134
150
 
135
151
  # @return [String]
136
152
  def rooted_name
137
- return name unless rooted?
153
+ return name unless @rooted && can_root_name?
138
154
  "::#{name}"
139
155
  end
140
156
 
@@ -161,7 +177,11 @@ module Solargraph
161
177
  elsif fixed_parameters?
162
178
  "(#{subtypes_str})"
163
179
  else
164
- "<#{subtypes_str}>"
180
+ if name == 'Hash'
181
+ "<#{key_types_str}, #{subtypes_str}>"
182
+ else
183
+ "<#{key_types_str}#{subtypes_str}>"
184
+ end
165
185
  end
166
186
  end
167
187
 
@@ -174,13 +194,10 @@ module Solargraph
174
194
  # @param other [Object]
175
195
  def == other
176
196
  return false unless self.class == other.class
197
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
177
198
  tag == other.tag
178
199
  end
179
200
 
180
- def rooted?
181
- @rooted
182
- end
183
-
184
201
  # Generate a ComplexType that fully qualifies this type's namespaces.
185
202
  #
186
203
  # @param api_map [ApiMap] The ApiMap that performs qualification
@@ -7,9 +7,15 @@ module Solargraph
7
7
  #
8
8
  class UniqueType
9
9
  include TypeMethods
10
+ include Equality
10
11
 
11
12
  attr_reader :all_params, :subtypes, :key_types
12
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
+
13
19
  # Create a UniqueType with the specified name and an optional substring.
14
20
  # The substring is the parameter section of a parametrized type, e.g.,
15
21
  # for the type `Array<String>`, the name is `Array` and the substring is
@@ -21,11 +27,13 @@ module Solargraph
21
27
  # @return [UniqueType]
22
28
  def self.parse name, substring = '', make_rooted: nil
23
29
  if name.start_with?(':::')
24
- raise "Illegal prefix: #{name}"
30
+ raise ComplexTypeError, "Illegal prefix: #{name}"
25
31
  end
26
32
  if name.start_with?('::')
27
33
  name = name[2..-1]
28
34
  rooted = true
35
+ elsif !can_root_name?(name)
36
+ rooted = true
29
37
  else
30
38
  rooted = false
31
39
  end
@@ -40,12 +48,15 @@ module Solargraph
40
48
  subs = ComplexType.parse(substring[1..-2], partial: true)
41
49
  parameters_type = PARAMETERS_TYPE_BY_STARTING_TAG.fetch(substring[0])
42
50
  if parameters_type == :hash
43
- raise ComplexTypeError, "Bad hash type" unless !subs.is_a?(ComplexType) and subs.length == 2 and !subs[0].is_a?(UniqueType) and !subs[1].is_a?(UniqueType)
44
- # @todo should be able to resolve map; both types have it
45
- # with same return type
46
- # @sg-ignore
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
47
59
  key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
48
- # @sg-ignore
49
60
  subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
50
61
  else
51
62
  subtypes.concat subs
@@ -63,21 +74,92 @@ module Solargraph
63
74
  if parameters_type.nil?
64
75
  raise "You must supply parameters_type if you provide parameters" unless key_types.empty? && subtypes.empty?
65
76
  end
66
- raise "Please remove leading :: and set rooted instead - #{name}" if name.start_with?('::')
77
+ raise "Please remove leading :: and set rooted instead - #{name.inspect}" if name.start_with?('::')
67
78
  @name = name
68
- @key_types = key_types
69
- @subtypes = subtypes
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
70
87
  @rooted = rooted
71
88
  @all_params = []
72
- @all_params.concat key_types
73
- @all_params.concat subtypes
74
- @parameters_type = parameters_type
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
75
98
  end
76
99
 
77
100
  def to_s
78
101
  tag
79
102
  end
80
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
+
81
163
  # @return [Array<UniqueType>]
82
164
  def items
83
165
  [self]
@@ -87,11 +169,18 @@ module Solargraph
87
169
  def rbs_name
88
170
  if name == 'undefined'
89
171
  'untyped'
172
+ elsif literal?
173
+ name
90
174
  else
91
175
  rooted_name
92
176
  end
93
177
  end
94
178
 
179
+ # @return [String]
180
+ def desc
181
+ rooted_tags
182
+ end
183
+
95
184
  # @return [String]
96
185
  def to_rbs
97
186
  if duck_type?
@@ -108,7 +197,11 @@ module Solargraph
108
197
  # tuples don't have a name; they're just [foo, bar, baz].
109
198
  if substring == '()'
110
199
  # but there are no zero element tuples, so we go with an array
111
- 'Array[]'
200
+ if rooted?
201
+ '::Array[]'
202
+ else
203
+ 'Array[]'
204
+ end
112
205
  else
113
206
  # already generated surrounded by []
114
207
  parameters_as_rbs
@@ -149,9 +242,26 @@ module Solargraph
149
242
  name == GENERIC_TAG_NAME || all_params.any?(&:generic?)
150
243
  end
151
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
+
152
262
  # @param generics_to_resolve [Enumerable<String>]
153
263
  # @param context_type [UniqueType, nil]
154
- # @param resolved_generic_values [Hash{String => ComplexType}] Added to as types are encountered or resolved
264
+ # @param resolved_generic_values [Hash{String => ComplexType, ComplexType::UniqueType}] Added to as types are encountered or resolved
155
265
  # @return [UniqueType, ComplexType]
156
266
  def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
157
267
  if name == ComplexType::GENERIC_TAG_NAME
@@ -176,7 +286,7 @@ module Solargraph
176
286
  end
177
287
 
178
288
  # @param generics_to_resolve [Enumerable<String>]
179
- # @param context_type [UniqueType]
289
+ # @param context_type [UniqueType, nil]
180
290
  # @param resolved_generic_values [Hash{String => ComplexType}]
181
291
  # @yieldreturn [Array<ComplexType>]
182
292
  # @return [Array<ComplexType>]
@@ -209,9 +319,26 @@ module Solargraph
209
319
 
210
320
  transform(name) do |t|
211
321
  if t.name == GENERIC_TAG_NAME
212
- idx = definitions.generics.index(t.subtypes.first&.name)
322
+ generic_name = t.subtypes.first&.name
323
+ idx = definitions.generics.index(generic_name)
213
324
  next t if idx.nil?
214
- context_type.all_params[idx] || ComplexType::UNDEFINED
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
215
342
  else
216
343
  t
217
344
  end
@@ -232,12 +359,13 @@ module Solargraph
232
359
 
233
360
  # @param new_name [String, nil]
234
361
  # @param make_rooted [Boolean, nil]
235
- # @param new_key_types [Array<UniqueType>, nil]
362
+ # @param new_key_types [Array<ComplexType>, nil]
236
363
  # @param rooted [Boolean, nil]
237
- # @param new_subtypes [Array<UniqueType>, nil]
364
+ # @param new_subtypes [Array<ComplexType>, nil]
238
365
  # @return [self]
239
366
  def recreate(new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil)
240
367
  raise "Please remove leading :: and set rooted instead - #{new_name}" if new_name&.start_with?('::')
368
+
241
369
  new_name ||= name
242
370
  new_key_types ||= @key_types
243
371
  new_subtypes ||= @subtypes
@@ -278,17 +406,26 @@ module Solargraph
278
406
  new_key_types = @key_types.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
279
407
  new_subtypes = @subtypes.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
280
408
  end
281
- new_type = recreate(new_name: new_name || name, new_key_types: new_key_types, new_subtypes: new_subtypes)
409
+ new_type = recreate(new_name: new_name || name, new_key_types: new_key_types, new_subtypes: new_subtypes, make_rooted: @rooted)
282
410
  yield new_type
283
411
  end
284
412
 
285
- # Transform references to the 'self' type to the specified concrete namespace
286
- # @param dst [String]
287
- # @return [UniqueType]
288
- def self_to dst
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
289
419
  transform do |t|
290
- next t if t.name != 'self'
291
- t.recreate(new_name: dst, new_key_types: [], new_subtypes: [])
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)
292
429
  end
293
430
  end
294
431
 
@@ -296,8 +433,50 @@ module Solargraph
296
433
  @name == 'self' || @key_types.any?(&:selfy?) || @subtypes.any?(&:selfy?)
297
434
  end
298
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
+
299
466
  UNDEFINED = UniqueType.new('undefined', rooted: false)
300
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
301
480
  end
302
481
  end
303
482
  end