solargraph 0.51.2 → 0.54.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 (183) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/plugins.yml +40 -0
  3. data/.github/workflows/rspec.yml +1 -3
  4. data/.github/workflows/typecheck.yml +34 -0
  5. data/.yardopts +2 -2
  6. data/CHANGELOG.md +127 -5
  7. data/README.md +13 -16
  8. data/SPONSORS.md +1 -7
  9. data/lib/solargraph/api_map/cache.rb +50 -20
  10. data/lib/solargraph/api_map/source_to_yard.rb +17 -10
  11. data/lib/solargraph/api_map/store.rb +60 -15
  12. data/lib/solargraph/api_map.rb +282 -123
  13. data/lib/solargraph/bench.rb +3 -2
  14. data/lib/solargraph/cache.rb +29 -5
  15. data/lib/solargraph/complex_type/type_methods.rb +122 -39
  16. data/lib/solargraph/complex_type/unique_type.rb +310 -76
  17. data/lib/solargraph/complex_type.rb +166 -44
  18. data/lib/solargraph/convention.rb +0 -1
  19. data/lib/solargraph/converters/dd.rb +5 -0
  20. data/lib/solargraph/converters/dl.rb +3 -0
  21. data/lib/solargraph/converters/dt.rb +3 -0
  22. data/lib/solargraph/diagnostics/rubocop.rb +8 -7
  23. data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -0
  24. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  25. data/lib/solargraph/diagnostics.rb +2 -2
  26. data/lib/solargraph/doc_map.rb +187 -0
  27. data/lib/solargraph/gem_pins.rb +72 -0
  28. data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
  29. data/lib/solargraph/language_server/host/dispatch.rb +22 -5
  30. data/lib/solargraph/language_server/host/message_worker.rb +49 -5
  31. data/lib/solargraph/language_server/host/sources.rb +8 -65
  32. data/lib/solargraph/language_server/host.rb +65 -84
  33. data/lib/solargraph/language_server/message/base.rb +19 -12
  34. data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
  35. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
  36. data/lib/solargraph/language_server/message/initialize.rb +19 -2
  37. data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
  38. data/lib/solargraph/language_server/message/text_document/definition.rb +3 -3
  39. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +3 -3
  40. data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -0
  41. data/lib/solargraph/language_server/message/text_document/hover.rb +3 -1
  42. data/lib/solargraph/language_server/message/text_document/type_definition.rb +3 -3
  43. data/lib/solargraph/language_server/message/text_document.rb +0 -1
  44. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
  45. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -2
  46. data/lib/solargraph/language_server/progress.rb +135 -0
  47. data/lib/solargraph/language_server/transport/adapter.rb +16 -1
  48. data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
  49. data/lib/solargraph/language_server.rb +1 -0
  50. data/lib/solargraph/library.rb +207 -111
  51. data/lib/solargraph/location.rb +15 -1
  52. data/lib/solargraph/page.rb +6 -0
  53. data/lib/solargraph/parser/comment_ripper.rb +4 -0
  54. data/lib/solargraph/parser/node_methods.rb +47 -7
  55. data/lib/solargraph/parser/node_processor/base.rb +11 -1
  56. data/lib/solargraph/parser/node_processor.rb +1 -0
  57. data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +31 -9
  58. data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
  59. data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +62 -43
  60. data/lib/solargraph/parser/parser_gem/node_methods.rb +495 -0
  61. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
  62. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +57 -0
  63. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
  64. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
  65. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +2 -2
  66. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +1 -1
  67. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/def_node.rb +7 -20
  68. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
  69. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
  70. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
  71. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +4 -4
  72. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +53 -0
  73. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
  74. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
  75. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
  76. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sclass_node.rb +1 -1
  77. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +8 -6
  78. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/sym_node.rb +1 -1
  79. data/lib/solargraph/parser/parser_gem/node_processors.rb +56 -0
  80. data/lib/solargraph/parser/parser_gem.rb +12 -0
  81. data/lib/solargraph/parser/region.rb +1 -1
  82. data/lib/solargraph/parser/snippet.rb +2 -0
  83. data/lib/solargraph/parser.rb +8 -12
  84. data/lib/solargraph/pin/base.rb +78 -10
  85. data/lib/solargraph/pin/base_variable.rb +40 -7
  86. data/lib/solargraph/pin/block.rb +69 -46
  87. data/lib/solargraph/pin/callable.rb +147 -0
  88. data/lib/solargraph/pin/closure.rb +23 -3
  89. data/lib/solargraph/pin/common.rb +6 -6
  90. data/lib/solargraph/pin/conversions.rb +36 -5
  91. data/lib/solargraph/pin/delegated_method.rb +6 -2
  92. data/lib/solargraph/pin/documenting.rb +25 -32
  93. data/lib/solargraph/pin/instance_variable.rb +6 -2
  94. data/lib/solargraph/pin/local_variable.rb +13 -1
  95. data/lib/solargraph/pin/method.rb +205 -32
  96. data/lib/solargraph/pin/namespace.rb +20 -7
  97. data/lib/solargraph/pin/parameter.rb +41 -36
  98. data/lib/solargraph/pin/proxy_type.rb +1 -1
  99. data/lib/solargraph/pin/reference/override.rb +2 -2
  100. data/lib/solargraph/pin/reference.rb +8 -0
  101. data/lib/solargraph/pin/search.rb +3 -3
  102. data/lib/solargraph/pin/signature.rb +8 -14
  103. data/lib/solargraph/pin.rb +4 -2
  104. data/lib/solargraph/range.rb +4 -6
  105. data/lib/solargraph/rbs_map/conversions.rb +326 -76
  106. data/lib/solargraph/rbs_map/core_fills.rb +16 -33
  107. data/lib/solargraph/rbs_map/core_map.rb +3 -13
  108. data/lib/solargraph/rbs_map/stdlib_map.rb +2 -8
  109. data/lib/solargraph/rbs_map.rb +32 -13
  110. data/lib/solargraph/shell.rb +95 -72
  111. data/lib/solargraph/source/chain/array.rb +33 -0
  112. data/lib/solargraph/source/chain/block_symbol.rb +13 -0
  113. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  114. data/lib/solargraph/source/chain/call.rb +152 -69
  115. data/lib/solargraph/source/chain/constant.rb +15 -1
  116. data/lib/solargraph/source/chain/if.rb +23 -0
  117. data/lib/solargraph/source/chain/link.rb +17 -2
  118. data/lib/solargraph/source/chain/or.rb +2 -2
  119. data/lib/solargraph/source/chain/z_super.rb +3 -3
  120. data/lib/solargraph/source/chain.rb +85 -26
  121. data/lib/solargraph/source/change.rb +3 -0
  122. data/lib/solargraph/source/cursor.rb +16 -2
  123. data/lib/solargraph/source/source_chainer.rb +8 -5
  124. data/lib/solargraph/source/updater.rb +1 -0
  125. data/lib/solargraph/source.rb +120 -148
  126. data/lib/solargraph/source_map/clip.rb +16 -27
  127. data/lib/solargraph/source_map/data.rb +30 -0
  128. data/lib/solargraph/source_map/mapper.rb +15 -3
  129. data/lib/solargraph/source_map.rb +48 -24
  130. data/lib/solargraph/type_checker/checks.rb +10 -2
  131. data/lib/solargraph/type_checker/rules.rb +6 -1
  132. data/lib/solargraph/type_checker.rb +150 -39
  133. data/lib/solargraph/version.rb +1 -1
  134. data/lib/solargraph/views/environment.erb +3 -5
  135. data/lib/solargraph/workspace/config.rb +9 -6
  136. data/lib/solargraph/workspace.rb +30 -3
  137. data/lib/solargraph/yard_map/cache.rb +6 -0
  138. data/lib/solargraph/yard_map/helpers.rb +1 -1
  139. data/lib/solargraph/yard_map/mapper/to_method.rb +16 -3
  140. data/lib/solargraph/yard_map/mapper.rb +1 -1
  141. data/lib/solargraph/yard_map/to_method.rb +11 -4
  142. data/lib/solargraph/yard_map.rb +1 -292
  143. data/lib/solargraph/yard_tags.rb +20 -0
  144. data/lib/solargraph/yardoc.rb +52 -0
  145. data/lib/solargraph.rb +6 -4
  146. data/solargraph.gemspec +7 -6
  147. metadata +71 -82
  148. data/lib/solargraph/api_map/bundler_methods.rb +0 -22
  149. data/lib/solargraph/documentor.rb +0 -76
  150. data/lib/solargraph/language_server/host/cataloger.rb +0 -56
  151. data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
  152. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
  153. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -50
  154. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
  155. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +0 -18
  156. data/lib/solargraph/parser/legacy/node_processors.rb +0 -55
  157. data/lib/solargraph/parser/legacy.rb +0 -12
  158. data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -153
  159. data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
  160. data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -317
  161. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
  162. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
  163. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -33
  164. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
  165. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +0 -75
  166. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -68
  167. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
  168. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
  169. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
  170. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
  171. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
  172. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
  173. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
  174. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
  175. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -51
  176. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -32
  177. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
  178. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -279
  179. data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -64
  180. data/lib/solargraph/parser/rubyvm/node_wrapper.rb +0 -47
  181. data/lib/solargraph/parser/rubyvm.rb +0 -40
  182. data/lib/solargraph/rbs_map/core_signs.rb +0 -33
  183. data/lib/yard-solargraph.rb +0 -33
@@ -8,7 +8,7 @@ module Solargraph
8
8
  class UniqueType
9
9
  include TypeMethods
10
10
 
11
- attr_reader :all_params
11
+ attr_reader :all_params, :subtypes, :key_types
12
12
 
13
13
  # Create a UniqueType with the specified name and an optional substring.
14
14
  # The substring is the parameter section of a parametrized type, e.g.,
@@ -17,116 +17,350 @@ module Solargraph
17
17
  #
18
18
  # @param name [String] The name of the type
19
19
  # @param substring [String] The substring of the type
20
- def initialize name, substring = ''
20
+ # @param make_rooted [Boolean, nil]
21
+ # @return [UniqueType]
22
+ def self.parse name, substring = '', make_rooted: nil
23
+ if name.start_with?(':::')
24
+ raise "Illegal prefix: #{name}"
25
+ end
21
26
  if name.start_with?('::')
22
- @name = name[2..-1]
23
- @rooted = true
27
+ name = name[2..-1]
28
+ rooted = true
29
+ elsif !can_root_name?(name)
30
+ rooted = true
24
31
  else
25
- @name = name
26
- @rooted = false
32
+ rooted = false
27
33
  end
28
- @substring = substring
29
- @tag = @name + substring
30
- @key_types = []
31
- @subtypes = []
32
- @all_params = []
33
- return unless parameters?
34
- if @substring.start_with?('<(') && @substring.end_with?(')>')
35
- subs = ComplexType.parse(substring[2..-3], partial: true)
36
- else
34
+ rooted = make_rooted unless make_rooted.nil?
35
+
36
+ # @type [Array<ComplexType>]
37
+ key_types = []
38
+ # @type [Array<ComplexType>]
39
+ subtypes = []
40
+ parameters_type = nil
41
+ unless substring.empty?
37
42
  subs = ComplexType.parse(substring[1..-2], partial: true)
43
+ parameters_type = PARAMETERS_TYPE_BY_STARTING_TAG.fetch(substring[0])
44
+ if parameters_type == :hash
45
+ 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)
46
+ # @todo should be able to resolve map; both types have it
47
+ # with same return type
48
+ # @sg-ignore
49
+ key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
50
+ # @sg-ignore
51
+ subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
52
+ else
53
+ subtypes.concat subs
54
+ end
38
55
  end
39
- if hash_parameters?
40
- 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)
41
- @key_types.concat subs[0].map { |u| ComplexType.new([u]) }
42
- @subtypes.concat subs[1].map { |u| ComplexType.new([u]) }
43
- else
44
- @subtypes.concat subs
56
+ new(name, key_types, subtypes, rooted: rooted, parameters_type: parameters_type)
57
+ end
58
+
59
+ # @param name [String]
60
+ # @param key_types [Array<ComplexType>]
61
+ # @param subtypes [Array<ComplexType>]
62
+ # @param rooted [Boolean]
63
+ # @param parameters_type [Symbol, nil]
64
+ def initialize(name, key_types = [], subtypes = [], rooted:, parameters_type: nil)
65
+ if parameters_type.nil?
66
+ raise "You must supply parameters_type if you provide parameters" unless key_types.empty? && subtypes.empty?
45
67
  end
46
- @all_params.concat @key_types
47
- @all_params.concat @subtypes
68
+ raise "Please remove leading :: and set rooted instead - #{name.inspect}" if name.start_with?('::')
69
+ @name = name
70
+ @key_types = key_types
71
+ @subtypes = subtypes
72
+ @rooted = rooted
73
+ @all_params = []
74
+ @all_params.concat key_types
75
+ @all_params.concat subtypes
76
+ @parameters_type = parameters_type
48
77
  end
49
78
 
50
79
  def to_s
51
80
  tag
52
81
  end
53
82
 
54
- def to_rbs
55
- "#{namespace}#{parameters? ? "[#{subtypes.map { |s| s.to_rbs }.join(', ')}]" : ''}"
83
+ def eql?(other)
84
+ self.class == other.class &&
85
+ @name == other.name &&
86
+ @key_types == other.key_types &&
87
+ @subtypes == other.subtypes &&
88
+ @rooted == other.rooted? &&
89
+ @all_params == other.all_params &&
90
+ @parameters_type == other.parameters_type
56
91
  end
57
-
58
- def parameterized?
59
- name == 'param' || all_params.any?(&:parameterized?)
92
+
93
+ def ==(other)
94
+ eql?(other)
95
+ end
96
+
97
+ def hash
98
+ [self.class, @name, @key_types, @sub_types, @rooted, @all_params, @parameters_type].hash
99
+ end
100
+
101
+ # @return [Array<UniqueType>]
102
+ def items
103
+ [self]
60
104
  end
61
105
 
62
- def resolve_parameters definitions, context
63
- new_name = if name == 'param'
64
- idx = definitions.parameters.index(subtypes.first.name)
65
- return ComplexType::UNDEFINED if idx.nil?
66
- param_type = context.return_type.all_params[idx]
67
- return ComplexType::UNDEFINED unless param_type
68
- param_type.to_s
106
+ # @return [String]
107
+ def rbs_name
108
+ if name == 'undefined'
109
+ 'untyped'
69
110
  else
70
- name
111
+ rooted_name
71
112
  end
72
- new_key_types = if name != 'param'
73
- @key_types.map { |t| t.resolve_parameters(definitions, context) }.select(&:defined?)
113
+ end
114
+
115
+ # @return [String]
116
+ def to_rbs
117
+ if duck_type?
118
+ 'untyped'
119
+ elsif name == 'Boolean'
120
+ 'bool'
121
+ elsif name.downcase == 'nil'
122
+ 'nil'
123
+ elsif name == GENERIC_TAG_NAME
124
+ all_params.first.name
125
+ elsif ['Class', 'Module'].include?(name)
126
+ rbs_name
127
+ elsif ['Tuple', 'Array'].include?(name) && fixed_parameters?
128
+ # tuples don't have a name; they're just [foo, bar, baz].
129
+ if substring == '()'
130
+ # but there are no zero element tuples, so we go with an array
131
+ if rooted?
132
+ '::Array[]'
133
+ else
134
+ 'Array[]'
135
+ end
136
+ else
137
+ # already generated surrounded by []
138
+ parameters_as_rbs
139
+ end
74
140
  else
75
- []
141
+ "#{rbs_name}#{parameters_as_rbs}"
76
142
  end
77
- new_subtypes = if name != 'param'
78
- @subtypes.map { |t| t.resolve_parameters(definitions, context) }.select(&:defined?)
143
+ end
144
+
145
+ # @return [Boolean]
146
+ def parameters?
147
+ !all_params.empty?
148
+ end
149
+
150
+ # @param types [Array<UniqueType, ComplexType>]
151
+ # @return [String]
152
+ def rbs_union(types)
153
+ if types.length == 1
154
+ types.first.to_rbs
79
155
  else
80
- []
156
+ "(#{types.map(&:to_rbs).join(' | ')})"
81
157
  end
82
- if name != 'param' && !(new_key_types.empty? && new_subtypes.empty?)
83
- if hash_parameters?
84
- UniqueType.new(new_name, "{#{new_key_types.join(', ')} => #{new_subtypes.join(', ')}}")
85
- elsif parameters?
86
- if @substring.start_with?'<('
87
- UniqueType.new(new_name, "<(#{new_subtypes.join(', ')})>")
158
+ end
159
+
160
+ # @return [String]
161
+ def parameters_as_rbs
162
+ return '' unless parameters?
163
+
164
+ return "[#{all_params.map(&:to_rbs).join(', ')}]" if key_types.empty?
165
+
166
+ # handle, e.g., Hash[K, V] case
167
+ key_types_str = rbs_union(key_types)
168
+ subtypes_str = rbs_union(subtypes)
169
+ "[#{key_types_str}, #{subtypes_str}]"
170
+ end
171
+
172
+ def generic?
173
+ name == GENERIC_TAG_NAME || all_params.any?(&:generic?)
174
+ end
175
+
176
+ # @param generics_to_resolve [Enumerable<String>]
177
+ # @param context_type [UniqueType, nil]
178
+ # @param resolved_generic_values [Hash{String => ComplexType}] Added to as types are encountered or resolved
179
+ # @return [UniqueType, ComplexType]
180
+ def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
181
+ if name == ComplexType::GENERIC_TAG_NAME
182
+ type_param = subtypes.first&.name
183
+ return self unless generics_to_resolve.include? type_param
184
+ unless context_type.nil? || !resolved_generic_values[type_param].nil?
185
+ new_binding = true
186
+ resolved_generic_values[type_param] = context_type
187
+ end
188
+ if new_binding
189
+ resolved_generic_values.transform_values! do |complex_type|
190
+ complex_type.resolve_generics_from_context(generics_to_resolve, nil, resolved_generic_values: resolved_generic_values)
191
+ end
192
+ end
193
+ return resolved_generic_values[type_param] || self
194
+ end
195
+
196
+ # @todo typechecking should complain when the method being called has no @yieldparam tag
197
+ new_key_types = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values, &:key_types)
198
+ new_subtypes = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values, &:subtypes)
199
+ recreate(new_key_types: new_key_types, new_subtypes: new_subtypes)
200
+ end
201
+
202
+ # @param generics_to_resolve [Enumerable<String>]
203
+ # @param context_type [UniqueType]
204
+ # @param resolved_generic_values [Hash{String => ComplexType}]
205
+ # @yieldreturn [Array<ComplexType>]
206
+ # @return [Array<ComplexType>]
207
+ def resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values)
208
+ types = yield self
209
+ types.each_with_index.flat_map do |ct, i|
210
+ ct.items.flat_map do |ut|
211
+ context_params = yield context_type if context_type
212
+ if context_params && context_params[i]
213
+ type_arg = context_params[i]
214
+ type_arg.map do |new_unique_context_type|
215
+ ut.resolve_generics_from_context generics_to_resolve, new_unique_context_type, resolved_generic_values: resolved_generic_values
216
+ end
88
217
  else
89
- UniqueType.new(new_name, "<#{new_subtypes.join(', ')}>")
218
+ ut.resolve_generics_from_context generics_to_resolve, nil, resolved_generic_values: resolved_generic_values
90
219
  end
91
- else
92
- UniqueType.new(new_name)
93
220
  end
94
- else
95
- UniqueType.new(new_name)
96
221
  end
222
+ end
97
223
 
98
- # idx = definitions.parameters.index(subtypes.first.name)
99
- # STDERR.puts "Index: #{idx}"
100
- # return ComplexType::UNDEFINED if idx.nil?
101
- # param_type = context.return_type.all_params[idx]
102
- # return ComplexType::UNDEFINED unless param_type
103
- # ComplexType.try_parse(param_type.to_s)
104
- end
105
-
106
- def self_to dst
107
- return self unless selfy?
108
- new_name = (@name == 'self' ? dst : @name)
109
- new_key_types = @key_types.map { |t| t.self_to dst }
110
- new_subtypes = @subtypes.map { |t| t.self_to dst }
111
- if hash_parameters?
112
- UniqueType.new(new_name, "{#{new_key_types.join(', ')} => #{new_subtypes.join(', ')}}")
113
- elsif parameters?
114
- if @substring.start_with?'<('
115
- UniqueType.new(new_name, "<(#{new_subtypes.join(', ')})>")
224
+ # Probe the concrete type for each of the generic type
225
+ # parameters used in this type, and return a new type if
226
+ # possible.
227
+ #
228
+ # @param definitions [Pin::Namespace, Pin::Method] The module/class/method which uses generic types
229
+ # @param context_type [ComplexType] The receiver type
230
+ # @return [UniqueType, ComplexType]
231
+ def resolve_generics definitions, context_type
232
+ return self if definitions.nil? || definitions.generics.empty?
233
+
234
+ transform(name) do |t|
235
+ if t.name == GENERIC_TAG_NAME
236
+ idx = definitions.generics.index(t.subtypes.first&.name)
237
+ next t if idx.nil?
238
+ context_type.all_params[idx] || ComplexType::UNDEFINED
116
239
  else
117
- UniqueType.new(new_name, "<#{new_subtypes.join(', ')}>")
240
+ t
118
241
  end
242
+ end
243
+ end
244
+
245
+ # @yieldparam t [self]
246
+ # @yieldreturn [self]
247
+ # @return [Array<self>]
248
+ def map &block
249
+ [block.yield(self)]
250
+ end
251
+
252
+ # @return [Array<UniqueType>]
253
+ def to_a
254
+ [self]
255
+ end
256
+
257
+ # @param new_name [String, nil]
258
+ # @param make_rooted [Boolean, nil]
259
+ # @param new_key_types [Array<UniqueType>, nil]
260
+ # @param rooted [Boolean, nil]
261
+ # @param new_subtypes [Array<UniqueType>, nil]
262
+ # @return [self]
263
+ def recreate(new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil)
264
+ raise "Please remove leading :: and set rooted instead - #{new_name}" if new_name&.start_with?('::')
265
+
266
+ new_name ||= name
267
+ new_key_types ||= @key_types
268
+ new_subtypes ||= @subtypes
269
+ make_rooted = @rooted if make_rooted.nil?
270
+ UniqueType.new(new_name, new_key_types, new_subtypes, rooted: make_rooted, parameters_type: parameters_type)
271
+ end
272
+
273
+ # @return [String]
274
+ def rooted_tags
275
+ rooted_tag
276
+ end
277
+
278
+ # @return [String]
279
+ def tags
280
+ tag
281
+ end
282
+
283
+ # @return [self]
284
+ def force_rooted
285
+ transform do |t|
286
+ t.recreate(make_rooted: true)
287
+ end
288
+ end
289
+
290
+ # Apply the given transformation to each subtype and then finally to this type
291
+ #
292
+ # @param new_name [String, nil]
293
+ # @yieldparam t [UniqueType]
294
+ # @yieldreturn [self]
295
+ # @return [self]
296
+ def transform(new_name = nil, &transform_type)
297
+ raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}" if new_name&.start_with?('::')
298
+ if name == ComplexType::GENERIC_TAG_NAME
299
+ # doesn't make sense to manipulate the name of the generic
300
+ new_key_types = @key_types
301
+ new_subtypes = @subtypes
119
302
  else
120
- UniqueType.new(new_name)
303
+ new_key_types = @key_types.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
304
+ new_subtypes = @subtypes.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
305
+ end
306
+ new_type = recreate(new_name: new_name || name, new_key_types: new_key_types, new_subtypes: new_subtypes, make_rooted: @rooted)
307
+ yield new_type
308
+ end
309
+
310
+ # Generate a ComplexType that fully qualifies this type's namespaces.
311
+ #
312
+ # @param api_map [ApiMap] The ApiMap that performs qualification
313
+ # @param context [String] The namespace from which to resolve names
314
+ # @return [self, ComplexType, UniqueType] The generated ComplexType
315
+ def qualify api_map, context = ''
316
+ transform do |t|
317
+ next t if t.name == GENERIC_TAG_NAME
318
+ next t if t.duck_type? || t.void? || t.undefined?
319
+ recon = (t.rooted? ? '' : context)
320
+ fqns = api_map.qualify(t.name, recon)
321
+ if fqns.nil?
322
+ next UniqueType::BOOLEAN if t.tag == 'Boolean'
323
+ next UniqueType::UNDEFINED
324
+ end
325
+ t.recreate(new_name: fqns, make_rooted: true)
121
326
  end
122
327
  end
123
328
 
124
329
  def selfy?
125
330
  @name == 'self' || @key_types.any?(&:selfy?) || @subtypes.any?(&:selfy?)
126
331
  end
127
-
128
- UNDEFINED = UniqueType.new('undefined')
129
- BOOLEAN = UniqueType.new('Boolean')
332
+
333
+ # @param dst [ComplexType]
334
+ # @return [self]
335
+ def self_to_type dst
336
+ object_type_dst = dst.reduce_class_type
337
+ transform do |t|
338
+ next t if t.name != 'self'
339
+ object_type_dst
340
+ end
341
+ end
342
+
343
+ def all_rooted?
344
+ return true if name == GENERIC_TAG_NAME
345
+ rooted? && all_params.all?(&:rooted?)
346
+ end
347
+
348
+ def rooted?
349
+ !can_root_name? || @rooted
350
+ end
351
+
352
+ def can_root_name?(name_to_check = name)
353
+ self.class.can_root_name?(name_to_check)
354
+ end
355
+
356
+ # @param name [String]
357
+ def self.can_root_name?(name)
358
+ # name is not lowercase
359
+ !name.empty? && name != name.downcase
360
+ end
361
+
362
+ UNDEFINED = UniqueType.new('undefined', rooted: false)
363
+ BOOLEAN = UniqueType.new('Boolean', rooted: true)
130
364
  end
131
365
  end
132
366
  end