solargraph 0.47.2 → 0.54.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 (191) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/plugins.yml +40 -0
  4. data/.github/workflows/rspec.yml +4 -8
  5. data/.github/workflows/typecheck.yml +34 -0
  6. data/.yardopts +2 -2
  7. data/CHANGELOG.md +166 -3
  8. data/LICENSE +1 -1
  9. data/README.md +19 -16
  10. data/SPONSORS.md +2 -9
  11. data/lib/solargraph/api_map/cache.rb +50 -20
  12. data/lib/solargraph/api_map/source_to_yard.rb +17 -10
  13. data/lib/solargraph/api_map/store.rb +68 -15
  14. data/lib/solargraph/api_map.rb +238 -112
  15. data/lib/solargraph/bench.rb +3 -2
  16. data/lib/solargraph/cache.rb +77 -0
  17. data/lib/solargraph/complex_type/type_methods.rb +116 -35
  18. data/lib/solargraph/complex_type/unique_type.rb +261 -33
  19. data/lib/solargraph/complex_type.rb +149 -30
  20. data/lib/solargraph/convention/rakefile.rb +17 -0
  21. data/lib/solargraph/convention.rb +2 -3
  22. data/lib/solargraph/converters/dd.rb +5 -0
  23. data/lib/solargraph/converters/dl.rb +3 -0
  24. data/lib/solargraph/converters/dt.rb +3 -0
  25. data/lib/solargraph/diagnostics/rubocop.rb +23 -8
  26. data/lib/solargraph/diagnostics/rubocop_helpers.rb +4 -1
  27. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  28. data/lib/solargraph/diagnostics.rb +2 -2
  29. data/lib/solargraph/doc_map.rb +187 -0
  30. data/lib/solargraph/gem_pins.rb +72 -0
  31. data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
  32. data/lib/solargraph/language_server/host/dispatch.rb +22 -5
  33. data/lib/solargraph/language_server/host/message_worker.rb +4 -0
  34. data/lib/solargraph/language_server/host/sources.rb +8 -65
  35. data/lib/solargraph/language_server/host.rb +88 -93
  36. data/lib/solargraph/language_server/message/base.rb +1 -1
  37. data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
  38. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
  39. data/lib/solargraph/language_server/message/extended/download_core.rb +1 -5
  40. data/lib/solargraph/language_server/message/initialize.rb +27 -0
  41. data/lib/solargraph/language_server/message/initialized.rb +1 -0
  42. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +4 -1
  43. data/lib/solargraph/language_server/message/text_document/formatting.rb +5 -4
  44. data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
  45. data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -6
  46. data/lib/solargraph/language_server/message/text_document/type_definition.rb +24 -0
  47. data/lib/solargraph/language_server/message/text_document.rb +1 -1
  48. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
  49. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +10 -3
  50. data/lib/solargraph/language_server/message.rb +1 -0
  51. data/lib/solargraph/language_server/progress.rb +118 -0
  52. data/lib/solargraph/language_server/transport/adapter.rb +16 -1
  53. data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
  54. data/lib/solargraph/language_server.rb +1 -0
  55. data/lib/solargraph/library.rb +231 -104
  56. data/lib/solargraph/location.rb +1 -0
  57. data/lib/solargraph/page.rb +6 -0
  58. data/lib/solargraph/parser/comment_ripper.rb +4 -0
  59. data/lib/solargraph/parser/node_methods.rb +47 -7
  60. data/lib/solargraph/parser/node_processor/base.rb +11 -1
  61. data/lib/solargraph/parser/node_processor.rb +1 -0
  62. data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +31 -9
  63. data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
  64. data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +57 -41
  65. data/lib/solargraph/parser/parser_gem/node_methods.rb +495 -0
  66. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
  67. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +53 -0
  68. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
  69. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
  70. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +14 -4
  71. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/cvasgn_node.rb +1 -1
  72. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/def_node.rb +7 -20
  73. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
  74. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
  75. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
  76. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +2 -2
  77. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +47 -0
  78. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
  79. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
  80. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
  81. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +42 -0
  82. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +7 -5
  83. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sym_node.rb +1 -1
  84. data/lib/solargraph/parser/parser_gem/node_processors.rb +56 -0
  85. data/lib/solargraph/parser/parser_gem.rb +12 -0
  86. data/lib/solargraph/parser/region.rb +1 -1
  87. data/lib/solargraph/parser/snippet.rb +2 -0
  88. data/lib/solargraph/parser.rb +9 -10
  89. data/lib/solargraph/pin/base.rb +69 -11
  90. data/lib/solargraph/pin/base_variable.rb +40 -7
  91. data/lib/solargraph/pin/block.rb +81 -33
  92. data/lib/solargraph/pin/closure.rb +17 -2
  93. data/lib/solargraph/pin/common.rb +7 -3
  94. data/lib/solargraph/pin/conversions.rb +34 -8
  95. data/lib/solargraph/pin/delegated_method.rb +101 -0
  96. data/lib/solargraph/pin/documenting.rb +25 -32
  97. data/lib/solargraph/pin/instance_variable.rb +4 -0
  98. data/lib/solargraph/pin/local_variable.rb +13 -1
  99. data/lib/solargraph/pin/method.rb +273 -17
  100. data/lib/solargraph/pin/namespace.rb +17 -1
  101. data/lib/solargraph/pin/parameter.rb +40 -28
  102. data/lib/solargraph/pin/reference/override.rb +2 -2
  103. data/lib/solargraph/pin/reference.rb +8 -0
  104. data/lib/solargraph/pin/search.rb +4 -4
  105. data/lib/solargraph/pin/signature.rb +143 -0
  106. data/lib/solargraph/pin.rb +2 -1
  107. data/lib/solargraph/range.rb +4 -6
  108. data/lib/solargraph/rbs_map/conversions.rb +607 -0
  109. data/lib/solargraph/rbs_map/core_fills.rb +50 -0
  110. data/lib/solargraph/rbs_map/core_map.rb +28 -0
  111. data/lib/solargraph/rbs_map/stdlib_map.rb +33 -0
  112. data/lib/solargraph/rbs_map.rb +92 -0
  113. data/lib/solargraph/shell.rb +85 -59
  114. data/lib/solargraph/source/chain/array.rb +32 -0
  115. data/lib/solargraph/source/chain/block_symbol.rb +13 -0
  116. data/lib/solargraph/source/chain/call.rb +125 -61
  117. data/lib/solargraph/source/chain/constant.rb +15 -1
  118. data/lib/solargraph/source/chain/if.rb +23 -0
  119. data/lib/solargraph/source/chain/link.rb +8 -2
  120. data/lib/solargraph/source/chain/or.rb +1 -1
  121. data/lib/solargraph/source/chain/z_super.rb +3 -3
  122. data/lib/solargraph/source/chain.rb +64 -14
  123. data/lib/solargraph/source/change.rb +3 -0
  124. data/lib/solargraph/source/cursor.rb +2 -0
  125. data/lib/solargraph/source/source_chainer.rb +8 -5
  126. data/lib/solargraph/source/updater.rb +1 -0
  127. data/lib/solargraph/source.rb +18 -63
  128. data/lib/solargraph/source_map/clip.rb +31 -23
  129. data/lib/solargraph/source_map/mapper.rb +23 -7
  130. data/lib/solargraph/source_map.rb +36 -11
  131. data/lib/solargraph/type_checker/checks.rb +10 -2
  132. data/lib/solargraph/type_checker.rb +229 -100
  133. data/lib/solargraph/version.rb +1 -1
  134. data/lib/solargraph/views/environment.erb +2 -2
  135. data/lib/solargraph/workspace/config.rb +15 -11
  136. data/lib/solargraph/workspace.rb +41 -17
  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 +23 -7
  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 -443
  143. data/lib/solargraph/yard_tags.rb +20 -0
  144. data/lib/solargraph/yardoc.rb +52 -0
  145. data/lib/solargraph.rb +8 -6
  146. data/solargraph.gemspec +19 -8
  147. metadata +164 -99
  148. data/.travis.yml +0 -19
  149. data/lib/solargraph/api_map/bundler_methods.rb +0 -22
  150. data/lib/solargraph/compat.rb +0 -37
  151. data/lib/solargraph/convention/rspec.rb +0 -30
  152. data/lib/solargraph/documentor.rb +0 -76
  153. data/lib/solargraph/language_server/host/cataloger.rb +0 -56
  154. data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
  155. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
  156. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -35
  157. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
  158. data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +0 -23
  159. data/lib/solargraph/parser/legacy/node_processors/def_node.rb +0 -63
  160. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +0 -21
  161. data/lib/solargraph/parser/legacy/node_processors.rb +0 -54
  162. data/lib/solargraph/parser/legacy.rb +0 -12
  163. data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -144
  164. data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
  165. data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -315
  166. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
  167. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
  168. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -22
  169. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -57
  170. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
  171. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
  172. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
  173. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
  174. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
  175. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
  176. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
  177. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
  178. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -45
  179. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -21
  180. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
  181. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -277
  182. data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +0 -18
  183. data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -63
  184. data/lib/solargraph/parser/rubyvm.rb +0 -40
  185. data/lib/solargraph/yard_map/core_docs.rb +0 -170
  186. data/lib/solargraph/yard_map/core_fills.rb +0 -208
  187. data/lib/solargraph/yard_map/core_gen.rb +0 -76
  188. data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -140
  189. data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
  190. data/lib/yard-solargraph.rb +0 -33
  191. data/yardoc/2.2.2.tar.gz +0 -0
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rubygems'
4
- require 'set'
5
3
  require 'pathname'
6
4
  require 'yard'
7
- require 'yard-solargraph'
5
+ require 'solargraph/yard_tags'
8
6
 
9
7
  module Solargraph
10
8
  # An aggregate provider for information about workspaces, sources, gems, and
@@ -14,13 +12,12 @@ module Solargraph
14
12
  autoload :Cache, 'solargraph/api_map/cache'
15
13
  autoload :SourceToYard, 'solargraph/api_map/source_to_yard'
16
14
  autoload :Store, 'solargraph/api_map/store'
17
- autoload :BundlerMethods, 'solargraph/api_map/bundler_methods'
18
-
19
- include SourceToYard
20
15
 
21
16
  # @return [Array<String>]
22
17
  attr_reader :unresolved_requires
23
18
 
19
+ @@core_map = RbsMap::CoreMap.new
20
+
24
21
  # @return [Array<String>]
25
22
  attr_reader :missing_docs
26
23
 
@@ -32,6 +29,25 @@ module Solargraph
32
29
  index pins
33
30
  end
34
31
 
32
+ #
33
+ # This is a mutable object, which is cached in the Chain class -
34
+ # if you add any fields which change the results of calls (not
35
+ # just caches), please also change `equality_fields` below.
36
+ #
37
+
38
+ def eql?(other)
39
+ self.class == other.class &&
40
+ equality_fields == other.equality_fields
41
+ end
42
+
43
+ def ==(other)
44
+ self.eql?(other)
45
+ end
46
+
47
+ def hash
48
+ equality_fields.hash
49
+ end
50
+
35
51
  # @param pins [Array<Pin::Base>]
36
52
  # @return [self]
37
53
  def index pins
@@ -40,7 +56,7 @@ module Solargraph
40
56
  @source_map_hash = {}
41
57
  implicit.clear
42
58
  cache.clear
43
- @store = Store.new(yard_map.pins + pins)
59
+ @store = Store.new(@@core_map.pins + pins)
44
60
  self
45
61
  end
46
62
 
@@ -57,32 +73,50 @@ module Solargraph
57
73
  # Catalog a bench.
58
74
  #
59
75
  # @param bench [Bench]
76
+ # @return [self]
60
77
  def catalog bench
61
- implicit.clear
62
- @cache.clear
78
+ old_api_hash = @source_map_hash&.values&.map(&:api_hash)
79
+ need_to_uncache = (old_api_hash != bench.source_maps.map(&:api_hash))
63
80
  @source_map_hash = bench.source_maps.map { |s| [s.filename, s] }.to_h
64
- pins = bench.source_maps.map(&:pins).flatten
65
- external_requires = bench.external_requires
81
+ pins = bench.source_maps.flat_map(&:pins).flatten
82
+ implicit.clear
66
83
  source_map_hash.each_value do |map|
67
84
  implicit.merge map.environ
68
85
  end
69
- external_requires.merge implicit.requires
70
- external_requires.merge bench.workspace.config.required
71
- yard_map.change(external_requires, bench.workspace.directory, bench.workspace.source_gems)
72
- @store = Store.new(yard_map.pins + implicit.pins + pins)
73
- @unresolved_requires = yard_map.unresolved_requires
74
- @missing_docs = yard_map.missing_docs
75
- @rebindable_method_names = nil
76
- store.block_pins.each { |blk| blk.rebind(self) }
86
+ unresolved_requires = (bench.external_requires + implicit.requires + bench.workspace.config.required).to_a.compact.uniq
87
+ if @unresolved_requires != unresolved_requires || @doc_map&.uncached_gemspecs&.any?
88
+ @doc_map = DocMap.new(unresolved_requires, [], bench.workspace.rbs_collection_path) # @todo Implement gem preferences
89
+ @unresolved_requires = unresolved_requires
90
+ need_to_uncache = true
91
+ end
92
+ @store = Store.new(@@core_map.pins + @doc_map.pins + implicit.pins + pins)
93
+ @cache.clear if need_to_uncache
94
+
95
+ @missing_docs = [] # @todo Implement missing docs
77
96
  self
78
97
  end
79
98
 
99
+ protected def equality_fields
100
+ [self.class, @source_map_hash, implicit, @doc_map, @unresolved_requires, @missing_docs]
101
+ end
102
+
103
+ # @return [::Array<Gem::Specification>]
104
+ def uncached_gemspecs
105
+ @doc_map&.uncached_gemspecs || []
106
+ end
107
+
108
+ # @return [Array<Pin::Base>]
109
+ def core_pins
110
+ @@core_map.pins
111
+ end
112
+
80
113
  # @param name [String]
81
114
  # @return [YARD::Tags::MacroDirective, nil]
82
115
  def named_macro name
83
116
  store.named_macros[name]
84
117
  end
85
118
 
119
+ # @return [Set<String>]
86
120
  def required
87
121
  @required ||= Set.new
88
122
  end
@@ -108,7 +142,7 @@ module Solargraph
108
142
  # @return [SourceMap::Clip]
109
143
  def clip_at filename, position
110
144
  position = Position.normalize(position)
111
- SourceMap::Clip.new(self, cursor_at(filename, position))
145
+ clip(cursor_at(filename, position))
112
146
  end
113
147
 
114
148
  # Create an ApiMap with a workspace in the specified directory.
@@ -125,21 +159,33 @@ module Solargraph
125
159
  api_map
126
160
  end
127
161
 
162
+ # Create an ApiMap with a workspace in the specified directory and cache
163
+ # any missing gems.
164
+ #
165
+ #
166
+ # @todo IO::NULL is incorrectly inferred to be a String.
167
+ # @sg-ignore
168
+ #
169
+ # @param directory [String]
170
+ # @param out [IO] The output stream for messages
171
+ # @return [ApiMap]
172
+ def self.load_with_cache directory, out = IO::NULL
173
+ api_map = load(directory)
174
+ return api_map if api_map.uncached_gemspecs.empty?
175
+
176
+ api_map.uncached_gemspecs.each do |gemspec|
177
+ out.puts "Caching gem #{gemspec.name} #{gemspec.version}"
178
+ pins = GemPins.build(gemspec)
179
+ Solargraph::Cache.save('gems', "#{gemspec.name}-#{gemspec.version}.ser", pins)
180
+ end
181
+ load(directory)
182
+ end
183
+
128
184
  # @return [Array<Solargraph::Pin::Base>]
129
185
  def pins
130
186
  store.pins
131
187
  end
132
188
 
133
- def rebindable_method_names
134
- @rebindable_method_names ||= begin
135
- result = yard_map.rebindable_method_names
136
- source_maps.each do |map|
137
- result.merge map.rebindable_method_names
138
- end
139
- result
140
- end
141
- end
142
-
143
189
  # An array of pins based on Ruby keywords (`if`, `end`, etc.).
144
190
  #
145
191
  # @return [Enumerable<Solargraph::Pin::Keyword>]
@@ -186,22 +232,60 @@ module Solargraph
186
232
  result
187
233
  end
188
234
 
189
- # Get a fully qualified namespace name. This method will start the search
190
- # in the specified context until it finds a match for the name.
191
- #
192
- # @param namespace [String, nil] The namespace to match
193
- # @param context [String] The context to search
194
- # @return [String]
195
- def qualify namespace, context = ''
196
- return namespace if ['self', nil].include?(namespace)
197
- cached = cache.get_qualified_namespace(namespace, context)
235
+ # @param namespace [String]
236
+ # @param context [String]
237
+ # @return [Array<Pin::Namespace>]
238
+ def get_namespace_pins namespace, context
239
+ store.fqns_pins(qualify(namespace, context))
240
+ end
241
+
242
+ # Determine fully qualified tag for a given tag used inside the
243
+ # definition of another tag ("context"). This method will start
244
+ # the search in the specified context until it finds a match for
245
+ # the tag.
246
+ #
247
+ # Does not recurse into qualifying the type parameters, but
248
+ # returns any which were passed in unchanged.
249
+ #
250
+ # @param tag [String, nil] The namespace to
251
+ # match, complete with generic parameters set to appropriate
252
+ # values if available
253
+ # @param context_tag [String] The context in which the tag was
254
+ # referenced; start from here to resolve the name
255
+ # @return [String, nil] fully qualified tag
256
+ def qualify tag, context_tag = ''
257
+ return tag if ['self', nil].include?(tag)
258
+ context_type = ComplexType.try_parse(context_tag)
259
+ return unless context_type
260
+
261
+ type = ComplexType.try_parse(tag)
262
+ return unless type
263
+
264
+ fqns = qualify_namespace(type.rooted_namespace, context_type.rooted_namespace)
265
+ return unless fqns
266
+
267
+ fqns + type.substring
268
+ end
269
+
270
+ # Determine fully qualified namespace for a given namespace used
271
+ # inside the definition of another tag ("context"). This method
272
+ # will start the search in the specified context until it finds a
273
+ # match for the namespace.
274
+ #
275
+ # @param namespace [String, nil] The namespace to
276
+ # match
277
+ # @param context_namespace [String] The context namespace in which the
278
+ # tag was referenced; start from here to resolve the name
279
+ # @return [String, nil] fully qualified namespace
280
+ def qualify_namespace(namespace, context_namespace = '')
281
+ cached = cache.get_qualified_namespace(namespace, context_namespace)
198
282
  return cached.clone unless cached.nil?
199
283
  result = if namespace.start_with?('::')
200
284
  inner_qualify(namespace[2..-1], '', Set.new)
201
285
  else
202
- inner_qualify(namespace, context, Set.new)
286
+ inner_qualify(namespace, context_namespace, Set.new)
203
287
  end
204
- cache.set_qualified_namespace(namespace, context, result)
288
+ cache.set_qualified_namespace(namespace, context_namespace, result)
205
289
  result
206
290
  end
207
291
 
@@ -227,49 +311,70 @@ module Solargraph
227
311
  # Get an array of class variable pins for a namespace.
228
312
  #
229
313
  # @param namespace [String] A fully qualified namespace
230
- # @return [Array<Solargraph::Pin::ClassVariable>]
314
+ # @return [Enumerable<Solargraph::Pin::ClassVariable>]
231
315
  def get_class_variable_pins(namespace)
232
316
  prefer_non_nil_variables(store.get_class_variables(namespace))
233
317
  end
234
318
 
235
- # @return [Array<Solargraph::Pin::Base>]
319
+ # @return [Enumerable<Solargraph::Pin::Base>]
236
320
  def get_symbols
237
321
  store.get_symbols
238
322
  end
239
323
 
240
- # @return [Array<Solargraph::Pin::GlobalVariable>]
324
+ # @return [Enumerable<Solargraph::Pin::GlobalVariable>]
241
325
  def get_global_variable_pins
242
326
  store.pins_by_class(Pin::GlobalVariable)
243
327
  end
244
328
 
245
329
  # Get an array of methods available in a particular context.
246
330
  #
247
- # @param fqns [String] The fully qualified namespace to search for methods
331
+ # @param rooted_tag [String] The fully qualified namespace to search for methods
248
332
  # @param scope [Symbol] :class or :instance
249
333
  # @param visibility [Array<Symbol>] :public, :protected, and/or :private
250
334
  # @param deep [Boolean] True to include superclasses, mixins, etc.
251
335
  # @return [Array<Solargraph::Pin::Method>]
252
- def get_methods fqns, scope: :instance, visibility: [:public], deep: true
253
- cached = cache.get_methods(fqns, scope, visibility, deep)
336
+ def get_methods rooted_tag, scope: :instance, visibility: [:public], deep: true
337
+ cached = cache.get_methods(rooted_tag, scope, visibility, deep)
254
338
  return cached.clone unless cached.nil?
255
339
  result = []
256
340
  skip = Set.new
257
- if fqns == ''
341
+ if rooted_tag == ''
258
342
  # @todo Implement domains
259
343
  implicit.domains.each do |domain|
260
344
  type = ComplexType.try_parse(domain)
261
345
  next if type.undefined?
262
346
  result.concat inner_get_methods(type.name, type.scope, visibility, deep, skip)
263
347
  end
264
- result.concat inner_get_methods(fqns, :class, visibility, deep, skip)
265
- result.concat inner_get_methods(fqns, :instance, visibility, deep, skip)
348
+ result.concat inner_get_methods(rooted_tag, :class, visibility, deep, skip)
349
+ result.concat inner_get_methods(rooted_tag, :instance, visibility, deep, skip)
266
350
  result.concat inner_get_methods('Kernel', :instance, visibility, deep, skip)
267
351
  else
268
- result.concat inner_get_methods(fqns, scope, visibility, deep, skip)
352
+ result.concat inner_get_methods(rooted_tag, scope, visibility, deep, skip)
353
+ unless %w[Class Class<Class>].include?(rooted_tag)
354
+ result.map! do |pin|
355
+ next pin unless pin.path == 'Class#new'
356
+ init_pin = get_method_stack(rooted_tag, 'initialize').first
357
+ next pin unless init_pin
358
+
359
+ type = ComplexType.try_parse(ComplexType.try_parse(rooted_tag).namespace)
360
+ Pin::Method.new(
361
+ name: 'new',
362
+ scope: :class,
363
+ location: init_pin.location,
364
+ parameters: init_pin.parameters,
365
+ signatures: init_pin.signatures.map { |sig| sig.proxy(type) },
366
+ return_type: type,
367
+ comments: init_pin.comments,
368
+ closure: init_pin.closure
369
+ # @todo Hack to force TypeChecker#internal_or_core?
370
+ ).tap { |pin| pin.source = :rbs }
371
+ end
372
+ end
269
373
  result.concat inner_get_methods('Kernel', :instance, [:public], deep, skip) if visibility.include?(:private)
374
+ result.concat inner_get_methods('Module', scope, visibility, deep, skip) if scope == :module
270
375
  end
271
376
  resolved = resolve_method_aliases(result, visibility)
272
- cache.set_methods(fqns, scope, visibility, deep, resolved)
377
+ cache.set_methods(rooted_tag, scope, visibility, deep, resolved)
273
378
  resolved
274
379
  end
275
380
 
@@ -307,27 +412,27 @@ module Solargraph
307
412
  visibility.push :protected
308
413
  visibility.push :private if internal
309
414
  end
310
- result.merge get_methods(type.namespace, scope: type.scope, visibility: visibility)
415
+ result.merge get_methods(type.tag, scope: type.scope, visibility: visibility)
311
416
  end
312
417
  end
313
418
  end
314
419
  result.to_a
315
420
  end
316
421
 
317
- # Get a stack of method pins for a method name in a namespace. The order
318
- # of the pins corresponds to the ancestry chain, with highest precedence
319
- # first.
422
+ # Get a stack of method pins for a method name in a potentially
423
+ # parameterized namespace. The order of the pins corresponds to
424
+ # the ancestry chain, with highest precedence first.
320
425
  #
321
426
  # @example
322
427
  # api_map.get_method_stack('Subclass', 'method_name')
323
428
  # #=> [ <Subclass#method_name pin>, <Superclass#method_name pin> ]
324
429
  #
325
- # @param fqns [String]
326
- # @param name [String]
430
+ # @param rooted_tag [String] Parameterized namespace, fully qualified
431
+ # @param name [String] Method name to look up
327
432
  # @param scope [Symbol] :instance or :class
328
433
  # @return [Array<Solargraph::Pin::Method>]
329
- def get_method_stack fqns, name, scope: :instance
330
- get_methods(fqns, scope: scope, visibility: [:private, :protected, :public]).select { |p| p.name == name }
434
+ def get_method_stack rooted_tag, name, scope: :instance
435
+ get_methods(rooted_tag, scope: scope, visibility: [:private, :protected, :public]).select { |p| p.name == name }
331
436
  end
332
437
 
333
438
  # Get an array of all suggestions that match the specified path.
@@ -335,7 +440,7 @@ module Solargraph
335
440
  # @deprecated Use #get_path_pins instead.
336
441
  #
337
442
  # @param path [String] The path to find
338
- # @return [Array<Solargraph::Pin::Base>]
443
+ # @return [Enumerable<Solargraph::Pin::Base>]
339
444
  def get_path_suggestions path
340
445
  return [] if path.nil?
341
446
  resolve_method_aliases store.get_path_pins(path)
@@ -344,7 +449,7 @@ module Solargraph
344
449
  # Get an array of pins that match the specified path.
345
450
  #
346
451
  # @param path [String]
347
- # @return [Array<Pin::Base>]
452
+ # @return [Enumerable<Pin::Base>]
348
453
  def get_path_pins path
349
454
  get_path_suggestions(path)
350
455
  end
@@ -357,15 +462,9 @@ module Solargraph
357
462
  # @param query [String] The text to match
358
463
  # @return [Array<String>]
359
464
  def search query
360
- rake_yard(store)
361
- found = []
362
- code_object_paths.each do |k|
363
- if (found.empty? || (query.include?('.') || query.include?('#')) || !(k.include?('.') || k.include?('#'))) &&
364
- k.downcase.include?(query.downcase)
365
- found.push k
366
- end
367
- end
368
- found
465
+ pins.map(&:path)
466
+ .compact
467
+ .select { |path| path.downcase.include?(query.downcase) }
369
468
  end
370
469
 
371
470
  # Get YARD documentation for the specified path.
@@ -373,13 +472,13 @@ module Solargraph
373
472
  # @example
374
473
  # api_map.document('String#split')
375
474
  #
475
+ # @todo This method is likely superfluous. Calling get_path_pins directly
476
+ # should be sufficient.
477
+ #
376
478
  # @param path [String] The path to find
377
- # @return [Array<YARD::CodeObjects::Base>]
479
+ # @return [Enumerable<Pin::Base>]
378
480
  def document path
379
- rake_yard(store)
380
- docs = []
381
- docs.push code_object_at(path) unless code_object_at(path).nil?
382
- docs
481
+ get_path_pins(path)
383
482
  end
384
483
 
385
484
  # Get an array of all symbols in the workspace that match the query.
@@ -405,6 +504,7 @@ module Solargraph
405
504
  # @return [SourceMap::Clip]
406
505
  def clip cursor
407
506
  raise FileNotFoundError, "ApiMap did not catalog #{cursor.filename}" unless source_map_hash.key?(cursor.filename)
507
+
408
508
  SourceMap::Clip.new(self, cursor)
409
509
  end
410
510
 
@@ -447,25 +547,24 @@ module Solargraph
447
547
  def super_and_sub?(sup, sub)
448
548
  fqsup = qualify(sup)
449
549
  cls = qualify(sub)
450
- until fqsup.nil? || cls.nil?
550
+ tested = []
551
+ until fqsup.nil? || cls.nil? || tested.include?(cls)
451
552
  return true if cls == fqsup
553
+ tested.push cls
452
554
  cls = qualify_superclass(cls)
453
555
  end
454
556
  false
455
557
  end
456
558
 
457
- # @return [YardMap]
458
- def yard_map
459
- @yard_map ||= YardMap.new
460
- end
461
-
462
- # Check if the host class includes the specified module.
559
+ # Check if the host class includes the specified module, ignoring
560
+ # type parameters used.
561
+ #
562
+ # @param host_ns [String] The class namesapce (no type parameters)
563
+ # @param module_ns [String] The module namespace (no type parameters)
463
564
  #
464
- # @param host [String] The class
465
- # @param mod [String] The module
466
565
  # @return [Boolean]
467
- def type_include?(host, mod)
468
- store.get_includes(host).include?(mod)
566
+ def type_include?(host_ns, module_ns)
567
+ store.get_includes(host_ns).map { |inc_tag| ComplexType.parse(inc_tag).name }.include?(module_ns)
469
568
  end
470
569
 
471
570
  private
@@ -483,15 +582,19 @@ module Solargraph
483
582
  # @return [Solargraph::ApiMap::Cache]
484
583
  attr_reader :cache
485
584
 
486
- # @param fqns [String] A fully qualified namespace
585
+ # @param rooted_tag [String] A fully qualified namespace, with
586
+ # generic parameter values if applicable
487
587
  # @param scope [Symbol] :class or :instance
488
588
  # @param visibility [Array<Symbol>] :public, :protected, and/or :private
489
589
  # @param deep [Boolean]
490
590
  # @param skip [Set<String>]
491
591
  # @param no_core [Boolean] Skip core classes if true
492
592
  # @return [Array<Pin::Base>]
493
- def inner_get_methods fqns, scope, visibility, deep, skip, no_core = false
494
- return [] if no_core && fqns =~ /^(Object|BasicObject|Class|Module|Kernel)$/
593
+ def inner_get_methods rooted_tag, scope, visibility, deep, skip, no_core = false
594
+ rooted_type = ComplexType.parse(rooted_tag)
595
+ fqns = rooted_type.namespace
596
+ fqns_generic_params = rooted_type.all_params
597
+ return [] if no_core && fqns =~ /^(Object|BasicObject|Class|Module)$/
495
598
  reqstr = "#{fqns}|#{scope}|#{visibility.sort}|#{deep}"
496
599
  return [] if skip.include?(reqstr)
497
600
  skip.add reqstr
@@ -502,12 +605,33 @@ module Solargraph
502
605
  result.concat inner_get_methods(fqim, scope, visibility, deep, skip, true) unless fqim.nil?
503
606
  end
504
607
  end
505
- result.concat store.get_methods(fqns, scope: scope, visibility: visibility).sort{ |a, b| a.name <=> b.name }
608
+ # Store#get_methods doesn't know about full tags, just
609
+ # namespaces; resolving the generics in the method pins is this
610
+ # class' responsibility
611
+ raw_methods = store.get_methods(fqns, scope: scope, visibility: visibility).sort{ |a, b| a.name <=> b.name }
612
+ namespace_pin = store.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
613
+ methods = if namespace_pin && rooted_tag != fqns
614
+ methods = raw_methods.map do |method_pin|
615
+ method_pin.resolve_generics(namespace_pin, rooted_type)
616
+ end
617
+ else
618
+ raw_methods
619
+ end
620
+ result.concat methods
506
621
  if deep
507
622
  if scope == :instance
508
- store.get_includes(fqns).reverse.each do |im|
509
- fqim = qualify(im, fqns)
510
- result.concat inner_get_methods(fqim, scope, visibility, deep, skip, true) unless fqim.nil?
623
+ store.get_includes(fqns).reverse.each do |include_tag|
624
+ rooted_include_tag = qualify(include_tag, rooted_tag)
625
+ # Ensure the types returned by the included methods are
626
+ # relative to the generics passed to the include. e.g.,
627
+ # Foo<String> might include Enumerable<String>
628
+ #
629
+ # @todo perform the same translation in the other areas
630
+ # here after adding a spec and handling things correctly
631
+ # in ApiMap::Store and RbsMap::Conversions
632
+ resolved_include_type = ComplexType.parse(rooted_include_tag).resolve_generics(namespace_pin, rooted_type)
633
+ methods = inner_get_methods(resolved_include_type.tag, scope, visibility, deep, skip, true)
634
+ result.concat methods
511
635
  end
512
636
  fqsc = qualify_superclass(fqns)
513
637
  unless fqsc.nil?
@@ -571,6 +695,8 @@ module Solargraph
571
695
  qualify namespace, context.split('::')[0..-2].join('::')
572
696
  end
573
697
 
698
+ # @param fqsub [String]
699
+ # @return [String, nil]
574
700
  def qualify_superclass fqsub
575
701
  sup = store.get_superclass(fqsub)
576
702
  return nil if sup.nil?
@@ -580,11 +706,12 @@ module Solargraph
580
706
  qualify(sup, parts.join('::'))
581
707
  end
582
708
 
583
- # @param name [String]
584
- # @param root [String]
585
- # @param skip [Set<String>]
586
- # @return [String, nil]
709
+ # @param name [String] Namespace to fully qualify
710
+ # @param root [String] The context to search
711
+ # @param skip [Set<String>] Contexts already searched
712
+ # @return [String, nil] Fully qualified ("rooted") namespace
587
713
  def inner_qualify name, root, skip
714
+ return name if name == ComplexType::GENERIC_TAG_NAME
588
715
  return nil if name.nil?
589
716
  return nil if skip.include?(root)
590
717
  skip.add root
@@ -634,8 +761,8 @@ module Solargraph
634
761
 
635
762
  # Sort an array of pins to put nil or undefined variables last.
636
763
  #
637
- # @param pins [Array<Solargraph::Pin::Base>]
638
- # @return [Array<Solargraph::Pin::Base>]
764
+ # @param pins [Enumerable<Solargraph::Pin::Base>]
765
+ # @return [Enumerable<Solargraph::Pin::Base>]
639
766
  def prefer_non_nil_variables pins
640
767
  result = []
641
768
  nil_pins = []
@@ -649,27 +776,26 @@ module Solargraph
649
776
  result + nil_pins
650
777
  end
651
778
 
652
- # @param pins [Array<Pin::Base>]
653
- # @param visibility [Array<Symbol>]
779
+ # @param pins [Enumerable<Pin::Base>]
780
+ # @param visibility [Enumerable<Symbol>]
654
781
  # @return [Array<Pin::Base>]
655
782
  def resolve_method_aliases pins, visibility = [:public, :private, :protected]
656
- result = []
657
- pins.each do |pin|
783
+ pins.map do |pin|
658
784
  resolved = resolve_method_alias(pin)
659
- next if resolved.respond_to?(:visibility) && !visibility.include?(resolved.visibility)
660
- result.push resolved
661
- end
662
- result
785
+ next pin if resolved.respond_to?(:visibility) && !visibility.include?(resolved.visibility)
786
+ resolved
787
+ end.compact
663
788
  end
664
789
 
665
790
  # @param pin [Pin::MethodAlias, Pin::Base]
666
791
  # @return [Pin::Method]
667
792
  def resolve_method_alias pin
668
- return pin if !pin.is_a?(Pin::MethodAlias) || @method_alias_stack.include?(pin.path)
793
+ return pin unless pin.is_a?(Pin::MethodAlias)
794
+ return nil if @method_alias_stack.include?(pin.path)
669
795
  @method_alias_stack.push pin.path
670
- origin = get_method_stack(pin.full_context.namespace, pin.original, scope: pin.scope).first
796
+ origin = get_method_stack(pin.full_context.tag, pin.original, scope: pin.scope).first
671
797
  @method_alias_stack.pop
672
- return pin if origin.nil?
798
+ return nil if origin.nil?
673
799
  args = {
674
800
  location: pin.location,
675
801
  closure: pin.closure,
@@ -677,7 +803,7 @@ module Solargraph
677
803
  comments: origin.comments,
678
804
  scope: origin.scope,
679
805
  visibility: origin.visibility,
680
- parameters: origin.parameters,
806
+ signatures: origin.signatures,
681
807
  attribute: origin.attribute?
682
808
  }
683
809
  Pin::Method.new **args
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'set'
4
3
 
5
4
  module Solargraph
6
5
  # A container of source maps and workspace data to be cataloged in an ApiMap.
@@ -21,7 +20,9 @@ module Solargraph
21
20
  def initialize source_maps: [], workspace: Workspace.new, external_requires: []
22
21
  @source_maps = source_maps.to_set
23
22
  @workspace = workspace
24
- @external_requires = external_requires.to_set
23
+ @external_requires = external_requires.reject { |path| workspace.would_require?(path) }
24
+ .compact
25
+ .to_set
25
26
  end
26
27
  end
27
28
  end