solargraph 0.58.2 → 0.59.0.dev.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 (203) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +4 -5
  4. data/.github/workflows/plugins.yml +41 -34
  5. data/.github/workflows/rspec.yml +44 -23
  6. data/.github/workflows/typecheck.yml +2 -2
  7. data/.rubocop.yml +32 -5
  8. data/.rubocop_todo.yml +50 -966
  9. data/Gemfile +3 -1
  10. data/README.md +3 -3
  11. data/Rakefile +26 -23
  12. data/bin/solargraph +2 -1
  13. data/lib/solargraph/api_map/cache.rb +3 -3
  14. data/lib/solargraph/api_map/constants.rb +13 -3
  15. data/lib/solargraph/api_map/index.rb +23 -18
  16. data/lib/solargraph/api_map/source_to_yard.rb +22 -9
  17. data/lib/solargraph/api_map/store.rb +33 -28
  18. data/lib/solargraph/api_map.rb +150 -82
  19. data/lib/solargraph/bench.rb +44 -45
  20. data/lib/solargraph/complex_type/conformance.rb +176 -0
  21. data/lib/solargraph/complex_type/type_methods.rb +28 -17
  22. data/lib/solargraph/complex_type/unique_type.rb +218 -57
  23. data/lib/solargraph/complex_type.rb +170 -57
  24. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -61
  25. data/lib/solargraph/convention/data_definition/data_definition_node.rb +7 -5
  26. data/lib/solargraph/convention/data_definition.rb +5 -2
  27. data/lib/solargraph/convention/gemfile.rb +15 -15
  28. data/lib/solargraph/convention/gemspec.rb +23 -23
  29. data/lib/solargraph/convention/rakefile.rb +17 -17
  30. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
  31. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -3
  32. data/lib/solargraph/convention/struct_definition.rb +8 -4
  33. data/lib/solargraph/convention.rb +78 -78
  34. data/lib/solargraph/converters/dd.rb +19 -17
  35. data/lib/solargraph/converters/dl.rb +17 -15
  36. data/lib/solargraph/converters/dt.rb +17 -15
  37. data/lib/solargraph/converters/misc.rb +3 -1
  38. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  39. data/lib/solargraph/diagnostics/rubocop.rb +11 -10
  40. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  41. data/lib/solargraph/diagnostics/type_check.rb +11 -10
  42. data/lib/solargraph/diagnostics/update_errors.rb +37 -41
  43. data/lib/solargraph/doc_map.rb +133 -373
  44. data/lib/solargraph/equality.rb +4 -4
  45. data/lib/solargraph/gem_pins.rb +21 -20
  46. data/lib/solargraph/language_server/error_codes.rb +20 -20
  47. data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
  48. data/lib/solargraph/language_server/host/dispatch.rb +3 -3
  49. data/lib/solargraph/language_server/host/message_worker.rb +4 -3
  50. data/lib/solargraph/language_server/host/sources.rb +2 -1
  51. data/lib/solargraph/language_server/host.rb +30 -22
  52. data/lib/solargraph/language_server/message/base.rb +97 -97
  53. data/lib/solargraph/language_server/message/client/register_capability.rb +13 -15
  54. data/lib/solargraph/language_server/message/completion_item/resolve.rb +58 -60
  55. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +12 -18
  56. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  57. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
  58. data/lib/solargraph/language_server/message/extended/download_core.rb +20 -19
  59. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  60. data/lib/solargraph/language_server/message/initialize.rb +197 -191
  61. data/lib/solargraph/language_server/message/text_document/completion.rb +10 -8
  62. data/lib/solargraph/language_server/message/text_document/definition.rb +41 -32
  63. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +23 -16
  64. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +29 -19
  65. data/lib/solargraph/language_server/message/text_document/formatting.rb +8 -6
  66. data/lib/solargraph/language_server/message/text_document/hover.rb +5 -5
  67. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +18 -11
  68. data/lib/solargraph/language_server/message/text_document/references.rb +23 -16
  69. data/lib/solargraph/language_server/message/text_document/rename.rb +26 -19
  70. data/lib/solargraph/language_server/message/text_document/signature_help.rb +3 -2
  71. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -17
  72. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +41 -35
  73. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +48 -40
  74. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +32 -26
  75. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +27 -17
  76. data/lib/solargraph/language_server/message.rb +94 -94
  77. data/lib/solargraph/language_server/request.rb +29 -27
  78. data/lib/solargraph/language_server/transport/data_reader.rb +72 -74
  79. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  80. data/lib/solargraph/library.rb +85 -44
  81. data/lib/solargraph/location.rb +17 -14
  82. data/lib/solargraph/logging.rb +24 -4
  83. data/lib/solargraph/page.rb +92 -92
  84. data/lib/solargraph/parser/comment_ripper.rb +19 -4
  85. data/lib/solargraph/parser/flow_sensitive_typing.rb +326 -108
  86. data/lib/solargraph/parser/node_processor/base.rb +34 -4
  87. data/lib/solargraph/parser/node_processor.rb +8 -7
  88. data/lib/solargraph/parser/parser_gem/class_methods.rb +32 -14
  89. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -19
  90. data/lib/solargraph/parser/parser_gem/node_chainer.rb +50 -25
  91. data/lib/solargraph/parser/parser_gem/node_methods.rb +91 -70
  92. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  93. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +13 -11
  94. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  95. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +12 -12
  96. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +10 -3
  97. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +38 -37
  98. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  99. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +5 -3
  100. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  101. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  102. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +3 -3
  103. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  104. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  105. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  106. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -5
  107. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +124 -113
  108. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -29
  109. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  110. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +6 -2
  111. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  112. data/lib/solargraph/parser/parser_gem.rb +14 -12
  113. data/lib/solargraph/parser/region.rb +9 -3
  114. data/lib/solargraph/parser/snippet.rb +3 -1
  115. data/lib/solargraph/parser.rb +25 -23
  116. data/lib/solargraph/pin/base.rb +126 -80
  117. data/lib/solargraph/pin/base_variable.rb +273 -24
  118. data/lib/solargraph/pin/block.rb +29 -6
  119. data/lib/solargraph/pin/breakable.rb +7 -1
  120. data/lib/solargraph/pin/callable.rb +65 -21
  121. data/lib/solargraph/pin/closure.rb +7 -10
  122. data/lib/solargraph/pin/common.rb +24 -6
  123. data/lib/solargraph/pin/compound_statement.rb +55 -0
  124. data/lib/solargraph/pin/constant.rb +43 -45
  125. data/lib/solargraph/pin/conversions.rb +10 -4
  126. data/lib/solargraph/pin/delegated_method.rb +19 -8
  127. data/lib/solargraph/pin/documenting.rb +4 -2
  128. data/lib/solargraph/pin/instance_variable.rb +5 -1
  129. data/lib/solargraph/pin/keyword.rb +0 -4
  130. data/lib/solargraph/pin/local_variable.rb +15 -59
  131. data/lib/solargraph/pin/method.rb +153 -104
  132. data/lib/solargraph/pin/method_alias.rb +8 -0
  133. data/lib/solargraph/pin/namespace.rb +19 -12
  134. data/lib/solargraph/pin/parameter.rb +100 -36
  135. data/lib/solargraph/pin/proxy_type.rb +4 -1
  136. data/lib/solargraph/pin/reference/override.rb +1 -1
  137. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  138. data/lib/solargraph/pin/reference.rb +19 -0
  139. data/lib/solargraph/pin/search.rb +3 -2
  140. data/lib/solargraph/pin/signature.rb +15 -12
  141. data/lib/solargraph/pin/symbol.rb +2 -1
  142. data/lib/solargraph/pin/until.rb +2 -4
  143. data/lib/solargraph/pin/while.rb +2 -4
  144. data/lib/solargraph/pin.rb +2 -0
  145. data/lib/solargraph/pin_cache.rb +490 -73
  146. data/lib/solargraph/position.rb +14 -10
  147. data/lib/solargraph/range.rb +16 -15
  148. data/lib/solargraph/rbs_map/conversions.rb +343 -214
  149. data/lib/solargraph/rbs_map/core_fills.rb +91 -84
  150. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  151. data/lib/solargraph/rbs_map/stdlib_map.rb +33 -5
  152. data/lib/solargraph/rbs_map.rb +77 -32
  153. data/lib/solargraph/server_methods.rb +16 -16
  154. data/lib/solargraph/shell.rb +128 -73
  155. data/lib/solargraph/source/chain/array.rb +39 -37
  156. data/lib/solargraph/source/chain/call.rb +96 -56
  157. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  158. data/lib/solargraph/source/chain/constant.rb +5 -1
  159. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  160. data/lib/solargraph/source/chain/hash.rb +8 -5
  161. data/lib/solargraph/source/chain/if.rb +12 -10
  162. data/lib/solargraph/source/chain/instance_variable.rb +24 -1
  163. data/lib/solargraph/source/chain/link.rb +99 -109
  164. data/lib/solargraph/source/chain/literal.rb +9 -6
  165. data/lib/solargraph/source/chain/or.rb +10 -4
  166. data/lib/solargraph/source/chain/q_call.rb +13 -11
  167. data/lib/solargraph/source/chain/variable.rb +15 -13
  168. data/lib/solargraph/source/chain/z_super.rb +28 -30
  169. data/lib/solargraph/source/chain.rb +49 -38
  170. data/lib/solargraph/source/change.rb +12 -5
  171. data/lib/solargraph/source/cursor.rb +23 -17
  172. data/lib/solargraph/source/encoding_fixes.rb +6 -7
  173. data/lib/solargraph/source/source_chainer.rb +56 -32
  174. data/lib/solargraph/source/updater.rb +5 -1
  175. data/lib/solargraph/source.rb +59 -35
  176. data/lib/solargraph/source_map/clip.rb +48 -29
  177. data/lib/solargraph/source_map/data.rb +4 -1
  178. data/lib/solargraph/source_map/mapper.rb +71 -42
  179. data/lib/solargraph/source_map.rb +21 -9
  180. data/lib/solargraph/type_checker/problem.rb +3 -1
  181. data/lib/solargraph/type_checker/rules.rb +81 -8
  182. data/lib/solargraph/type_checker.rb +195 -120
  183. data/lib/solargraph/version.rb +1 -1
  184. data/lib/solargraph/workspace/config.rb +13 -10
  185. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  186. data/lib/solargraph/workspace/require_paths.rb +1 -0
  187. data/lib/solargraph/workspace.rb +149 -30
  188. data/lib/solargraph/yard_map/helpers.rb +8 -3
  189. data/lib/solargraph/yard_map/mapper/to_method.rb +13 -7
  190. data/lib/solargraph/yard_map/mapper/to_namespace.rb +2 -1
  191. data/lib/solargraph/yard_map/mapper.rb +13 -8
  192. data/lib/solargraph/yard_tags.rb +20 -20
  193. data/lib/solargraph/yardoc.rb +33 -23
  194. data/lib/solargraph.rb +29 -8
  195. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  196. data/rbs/fills/tuple/tuple.rbs +28 -0
  197. data/rbs/shims/ast/0/node.rbs +1 -1
  198. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  199. data/solargraph.gemspec +36 -34
  200. metadata +38 -33
  201. data/lib/solargraph/type_checker/checks.rb +0 -124
  202. data/lib/solargraph/type_checker/param_def.rb +0 -37
  203. data/lib/solargraph/yard_map/to_method.rb +0 -89
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'open3'
4
4
  require 'json'
5
+ require 'yaml'
5
6
 
6
7
  module Solargraph
7
8
  # A workspace consists of the files in a project's directory and the
@@ -9,7 +10,10 @@ module Solargraph
9
10
  # in an associated Library or ApiMap.
10
11
  #
11
12
  class Workspace
13
+ include Logging
14
+
12
15
  autoload :Config, 'solargraph/workspace/config'
16
+ autoload :Gemspecs, 'solargraph/workspace/gemspecs'
13
17
  autoload :RequirePaths, 'solargraph/workspace/require_paths'
14
18
 
15
19
  # @return [String]
@@ -19,7 +23,8 @@ module Solargraph
19
23
  attr_reader :gemnames
20
24
  alias source_gems gemnames
21
25
 
22
- # @param directory [String] TODO: Remove '' and '*' special cases
26
+ # @todo Remove '' and '*' special cases
27
+ # @param directory [String]
23
28
  # @param config [Config, nil]
24
29
  # @param server [Hash]
25
30
  def initialize directory = '', config = nil, server = {}
@@ -50,9 +55,71 @@ module Solargraph
50
55
  @config ||= Solargraph::Workspace::Config.new(directory)
51
56
  end
52
57
 
58
+ # @param stdlib_name [String]
59
+ #
60
+ # @return [Array<String>]
61
+ def stdlib_dependencies stdlib_name
62
+ gemspecs.stdlib_dependencies(stdlib_name)
63
+ end
64
+
65
+ # @param out [IO, nil] output stream for logging
66
+ # @param gemspec [Gem::Specification]
67
+ # @return [Array<Gem::Specification>]
68
+ def fetch_dependencies gemspec, out: $stderr
69
+ gemspecs.fetch_dependencies(gemspec, out: out)
70
+ end
71
+
72
+ # @param require [String] The string sent to 'require' in the code to resolve, e.g. 'rails', 'bundler/require'
73
+ # @return [Array<Gem::Specification>, nil]
74
+ def resolve_require require
75
+ gemspecs.resolve_require(require)
76
+ end
77
+
78
+ # @return [Solargraph::PinCache]
79
+ def pin_cache
80
+ @pin_cache ||= fresh_pincache
81
+ end
82
+
83
+ # @return [Environ]
84
+ def global_environ
85
+ # empty docmap, since the result needs to work in any possible
86
+ # context here
87
+ @global_environ ||= Convention.for_global(DocMap.new([], self, out: nil))
88
+ end
89
+
90
+ # @param gemspec [Gem::Specification]
91
+ # @param out [StringIO, IO, nil] output stream for logging
92
+ # @param rebuild [Boolean] whether to rebuild the pins even if they are cached
93
+ #
94
+ # @return [void]
95
+ def cache_gem gemspec, out: nil, rebuild: false
96
+ pin_cache.cache_gem(gemspec: gemspec, out: out, rebuild: rebuild)
97
+ end
98
+
99
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
100
+ # @param out [StringIO, IO, nil] output stream for logging
101
+ #
102
+ # @return [void]
103
+ def uncache_gem gemspec, out: nil
104
+ pin_cache.uncache_gem(gemspec, out: out)
105
+ end
106
+
107
+ # @return [Solargraph::PinCache]
108
+ def fresh_pincache
109
+ PinCache.new(rbs_collection_path: rbs_collection_path,
110
+ rbs_collection_config_path: rbs_collection_config_path,
111
+ yard_plugins: yard_plugins,
112
+ directory: directory)
113
+ end
114
+
115
+ # @return [Array<String>]
116
+ def yard_plugins
117
+ @yard_plugins ||= global_environ.yard_plugins.sort.uniq
118
+ end
119
+
53
120
  # @param level [Symbol]
54
121
  # @return [TypeChecker::Rules]
55
- def rules(level)
122
+ def rules level
56
123
  @rules ||= TypeChecker::Rules.new(level, config.type_checker_rules)
57
124
  end
58
125
 
@@ -63,6 +130,7 @@ module Solargraph
63
130
  # @param sources [Array<Solargraph::Source>]
64
131
  # @return [Boolean] True if the source was added to the workspace
65
132
  def merge *sources
133
+ # @sg-ignore Need to add nil check here
66
134
  unless directory == '*' || sources.all? { |source| source_hash.key?(source.filename) }
67
135
  # Reload the config to determine if a new source should be included
68
136
  @config = Solargraph::Workspace::Config.new(directory)
@@ -70,10 +138,12 @@ module Solargraph
70
138
 
71
139
  includes_any = false
72
140
  sources.each do |source|
73
- if directory == "*" || config.calculated.include?(source.filename)
74
- source_hash[source.filename] = source
75
- includes_any = true
76
- end
141
+ # @sg-ignore Need to add nil check here
142
+ next unless directory == '*' || config.calculated.include?(source.filename)
143
+
144
+ # @sg-ignore Need to add nil check here
145
+ source_hash[source.filename] = source
146
+ includes_any = true
77
147
  end
78
148
 
79
149
  includes_any
@@ -121,24 +191,76 @@ module Solargraph
121
191
  def would_require? path
122
192
  require_paths.each do |rp|
123
193
  full = File.join rp, path
124
- return true if File.file?(full) || File.file?(full << ".rb")
194
+ return true if File.file?(full) || File.file?(full << '.rb')
125
195
  end
126
196
  false
127
197
  end
128
198
 
199
+ # True if the workspace contains at least one gemspec file.
200
+ #
201
+ # @return [Boolean]
202
+ def gemspec?
203
+ !gemspec_files.empty?
204
+ end
205
+
206
+ # Get an array of all gemspec files in the workspace.
207
+ #
208
+ # @return [Array<String>]
209
+ def gemspec_files
210
+ return [] if directory.empty? || directory == '*'
211
+ @gemspec_files ||= Dir[File.join(directory, '**/*.gemspec')].select do |gs|
212
+ config.allow? gs
213
+ end
214
+ end
215
+
129
216
  # @return [String, nil]
130
217
  def rbs_collection_path
131
- @gem_rbs_collection ||= read_rbs_collection_path
218
+ @rbs_collection_path ||= read_rbs_collection_path
132
219
  end
133
220
 
134
221
  # @return [String, nil]
135
222
  def rbs_collection_config_path
136
- @rbs_collection_config_path ||= begin
223
+ @rbs_collection_config_path ||=
137
224
  unless directory.empty? || directory == '*'
138
225
  yaml_file = File.join(directory, 'rbs_collection.yaml')
139
226
  yaml_file if File.file?(yaml_file)
140
227
  end
228
+ end
229
+
230
+ # @param name [String]
231
+ # @param version [String, nil]
232
+ # @param out [IO, nil]
233
+ #
234
+ # @return [Gem::Specification, nil]
235
+ def find_gem name, version = nil, out: nil
236
+ gemspecs.find_gem(name, version, out: out)
237
+ end
238
+
239
+ # @return [Array<Gem::Specification>]
240
+ def all_gemspecs_from_bundle
241
+ gemspecs.all_gemspecs_from_bundle
242
+ end
243
+
244
+ # @param out [StringIO, IO, nil] output stream for logging
245
+ # @param rebuild [Boolean] whether to rebuild the pins even if they are cached
246
+ # @return [void]
247
+ def cache_all_for_workspace! out, rebuild: false
248
+ PinCache.cache_core(out: out) unless PinCache.core? && !rebuild
249
+
250
+ gem_specs = all_gemspecs_from_bundle
251
+ # try any possible standard libraries, but be quiet about it
252
+ stdlib_specs = pin_cache.possible_stdlibs.map { |stdlib| find_gem(stdlib, out: nil) }.compact
253
+ specs = (gem_specs + stdlib_specs)
254
+ specs.each do |spec|
255
+ pin_cache.cache_gem(gemspec: spec, rebuild: rebuild, out: out) unless pin_cache.cached?(spec)
141
256
  end
257
+ out&.puts "Documentation cached for all #{specs.length} gems."
258
+
259
+ # do this after so that we prefer stdlib requires from gems,
260
+ # which are likely to be newer and have more pins
261
+ pin_cache.cache_all_stdlibs(out: out, rebuild: rebuild)
262
+
263
+ out&.puts 'Documentation cached for core, standard library and gems.'
142
264
  end
143
265
 
144
266
  # Synchronize the workspace from the provided updater.
@@ -149,7 +271,9 @@ module Solargraph
149
271
  source_hash[updater.filename] = source_hash[updater.filename].synchronize(updater)
150
272
  end
151
273
 
274
+ # @sg-ignore Need to validate config
152
275
  # @return [String]
276
+ # @sg-ignore Need to validate config
153
277
  def command_path
154
278
  server['commandPath'] || 'solargraph'
155
279
  end
@@ -160,12 +284,9 @@ module Solargraph
160
284
  directory
161
285
  end
162
286
 
163
- # True if the workspace has a root Gemfile.
164
- #
165
- # @todo Handle projects with custom Bundler/Gemfile setups (see DocMap#gemspecs_required_from_bundler)
166
- #
167
- def gemfile?
168
- directory && File.file?(File.join(directory, 'Gemfile'))
287
+ # @return [Solargraph::Workspace::Gemspecs]
288
+ def gemspecs
289
+ @gemspecs ||= Solargraph::Workspace::Gemspecs.new(directory_or_nil)
169
290
  end
170
291
 
171
292
  private
@@ -184,27 +305,25 @@ module Solargraph
184
305
  # @return [void]
185
306
  def load_sources
186
307
  source_hash.clear
187
- unless directory.empty? || directory == '*'
188
- size = config.calculated.length
189
- raise WorkspaceTooLargeError, "The workspace is too large to index (#{size} files, #{config.max_files} max)" if config.max_files > 0 and size > config.max_files
190
- config.calculated.each do |filename|
191
- begin
192
- source_hash[filename] = Solargraph::Source.load(filename)
193
- rescue Errno::ENOENT => e
194
- Solargraph.logger.warn("Error loading #{filename}: [#{e.class}] #{e.message}")
195
- end
196
- end
308
+ return if directory.empty? || directory == '*'
309
+ size = config.calculated.length
310
+ if config.max_files.positive? && (size > config.max_files)
311
+ raise WorkspaceTooLargeError,
312
+ "The workspace is too large to index (#{size} files, #{config.max_files} max)"
313
+ end
314
+ config.calculated.each do |filename|
315
+ source_hash[filename] = Solargraph::Source.load(filename)
316
+ rescue Errno::ENOENT => e
317
+ Solargraph.logger.warn("Error loading #{filename}: [#{e.class}] #{e.message}")
197
318
  end
198
319
  end
199
320
 
200
321
  # @return [void]
201
322
  def require_plugins
202
323
  config.plugins.each do |plugin|
203
- begin
204
- require plugin
205
- rescue LoadError
206
- Solargraph.logger.warn "Failed to load plugin '#{plugin}'"
207
- end
324
+ require plugin
325
+ rescue LoadError
326
+ Solargraph.logger.warn "Failed to load plugin '#{plugin}'"
208
327
  end
209
328
  end
210
329
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Solargraph
2
4
  class YardMap
3
5
  module Helpers
@@ -5,7 +7,7 @@ module Solargraph
5
7
 
6
8
  # @param code_object [YARD::CodeObjects::Base]
7
9
  # @param spec [Gem::Specification, nil]
8
- # @return [Solargraph::Location, nil]
10
+ # @return [Solargraph::Location]
9
11
  def object_location code_object, spec
10
12
  if spec.nil? || code_object.nil? || code_object.file.nil? || code_object.line.nil?
11
13
  if code_object.namespace.is_a?(YARD::CodeObjects::NamespaceObject)
@@ -14,6 +16,7 @@ module Solargraph
14
16
  end
15
17
  return Solargraph::Location.new(__FILE__, Solargraph::Range.from_to(__LINE__ - 1, 0, __LINE__ - 1, 0))
16
18
  end
19
+ # @sg-ignore flow sensitive typing should be able to identify more blocks that always return
17
20
  file = File.join(spec.full_gem_path, code_object.file)
18
21
  Solargraph::Location.new(file, Solargraph::Range.from_to(code_object.line - 1, 0, code_object.line - 1, 0))
19
22
  end
@@ -21,10 +24,12 @@ module Solargraph
21
24
  # @param code_object [YARD::CodeObjects::Base]
22
25
  # @param spec [Gem::Specification, nil]
23
26
  # @return [Solargraph::Pin::Namespace]
24
- def create_closure_namespace_for(code_object, spec)
27
+ def create_closure_namespace_for code_object, spec
25
28
  code_object_for_location = code_object
26
29
  # code_object.namespace is sometimes a YARD proxy object pointing to a method path ("Object#new")
27
- code_object_for_location = code_object.namespace if code_object.namespace.is_a?(YARD::CodeObjects::NamespaceObject)
30
+ if code_object.namespace.is_a?(YARD::CodeObjects::NamespaceObject)
31
+ code_object_for_location = code_object.namespace
32
+ end
28
33
  namespace_location = object_location(code_object_for_location, spec)
29
34
  ns_name = code_object.namespace.to_s
30
35
  if ns_name.empty?
@@ -6,10 +6,11 @@ module Solargraph
6
6
  module ToMethod
7
7
  extend YardMap::Helpers
8
8
 
9
+ # @type [Hash{Array<String, Symbol, String> => Symbol}]
9
10
  VISIBILITY_OVERRIDE = {
10
11
  # YARD pays attention to 'private' statements prior to class methods but shouldn't
11
- ["Rails::Engine", :class, "find_root_with_flag"] => :public
12
- }
12
+ ['Rails::Engine', :class, 'find_root_with_flag'] => :public
13
+ }.freeze
13
14
 
14
15
  # @param code_object [YARD::CodeObjects::MethodObject]
15
16
  # @param name [String, nil]
@@ -25,10 +26,15 @@ module Solargraph
25
26
  return_type = ComplexType::SELF if name == 'new'
26
27
  comments = code_object.docstring ? code_object.docstring.all.to_s : ''
27
28
  final_scope = scope || code_object.scope
29
+ # @sg-ignore Need to add nil check here
28
30
  override_key = [closure.path, final_scope, name]
29
31
  final_visibility = VISIBILITY_OVERRIDE[override_key]
32
+ # @sg-ignore Need to add nil check here
30
33
  final_visibility ||= VISIBILITY_OVERRIDE[[closure.path, final_scope]]
31
- final_visibility ||= :private if closure.path == 'Kernel' && Kernel.private_instance_methods(false).include?(name.to_sym)
34
+ # @sg-ignore Need to add nil check here
35
+ if closure.path == 'Kernel' && Kernel.private_instance_methods(false).include?(name.to_sym)
36
+ final_visibility ||= :private
37
+ end
32
38
  final_visibility ||= visibility
33
39
  final_visibility ||= :private if code_object.module_function? && final_scope == :instance
34
40
  final_visibility ||= :public if code_object.module_function? && final_scope == :class
@@ -46,9 +52,10 @@ module Solargraph
46
52
  explicit: code_object.is_explicit?,
47
53
  return_type: return_type,
48
54
  parameters: [],
49
- source: :yardoc,
55
+ source: :yardoc
50
56
  )
51
57
  else
58
+ # @sg-ignore Need to add nil check here
52
59
  pin = Pin::Method.new(
53
60
  location: location,
54
61
  closure: closure,
@@ -61,7 +68,7 @@ module Solargraph
61
68
  return_type: return_type,
62
69
  attribute: code_object.is_attribute?,
63
70
  parameters: [],
64
- source: :yardoc,
71
+ source: :yardoc
65
72
  )
66
73
  pin.parameters.concat get_parameters(code_object, location, comments, pin)
67
74
  pin.parameters.freeze
@@ -85,7 +92,6 @@ module Solargraph
85
92
  # HACK: Skip `nil` and `self` parameters that are sometimes emitted
86
93
  # for methods defined in C
87
94
  # See https://github.com/castwide/solargraph/issues/345
88
- # @sg-ignore https://github.com/castwide/solargraph/pull/1114
89
95
  code_object.parameters.select { |a| a[0] && a[0] != 'self' }.map do |a|
90
96
  Solargraph::Pin::Parameter.new(
91
97
  location: location,
@@ -95,7 +101,7 @@ module Solargraph
95
101
  presence: nil,
96
102
  decl: arg_type(a),
97
103
  asgn_code: a[1],
98
- source: :yardoc,
104
+ source: :yardoc
99
105
  )
100
106
  end
101
107
  end
@@ -21,8 +21,9 @@ module Solargraph
21
21
  type: code_object.is_a?(YARD::CodeObjects::ClassObject) ? :class : :module,
22
22
  visibility: code_object.visibility,
23
23
  closure: closure,
24
+ # @sg-ignore need to add a nil check here
24
25
  gates: closure.gates,
25
- source: :yardoc,
26
+ source: :yardoc
26
27
  )
27
28
  end
28
29
  end
@@ -24,6 +24,7 @@ module Solargraph
24
24
  end
25
25
  # Some yardocs contain documentation for dependencies that can be
26
26
  # ignored here. The YardMap will load dependencies separately.
27
+ # @sg-ignore Need to add nil check here
27
28
  @pins.keep_if { |pin| pin.location.nil? || File.file?(pin.location.filename) } if @spec
28
29
  @pins
29
30
  end
@@ -34,24 +35,27 @@ module Solargraph
34
35
  # @return [Array<Pin::Base>]
35
36
  def generate_pins code_object
36
37
  result = []
37
- if code_object.is_a?(YARD::CodeObjects::NamespaceObject)
38
+ case code_object
39
+ when YARD::CodeObjects::NamespaceObject
38
40
  nspin = ToNamespace.make(code_object, @spec, @namespace_pins[code_object.namespace.to_s])
39
41
  @namespace_pins[code_object.path] = nspin
40
42
  result.push nspin
41
- if code_object.is_a?(YARD::CodeObjects::ClassObject) and !code_object.superclass.nil?
43
+ if code_object.is_a?(YARD::CodeObjects::ClassObject) && !code_object.superclass.nil?
42
44
  # This method of superclass detection is a bit of a hack. If
43
45
  # the superclass is a Proxy, it is assumed to be undefined in its
44
46
  # yardoc and converted to a fully qualified namespace.
45
47
  superclass = if code_object.superclass.is_a?(YARD::CodeObjects::Proxy)
46
- "::#{code_object.superclass}"
47
- else
48
- code_object.superclass.to_s
49
- end
48
+ "::#{code_object.superclass}"
49
+ else
50
+ code_object.superclass.to_s
51
+ end
50
52
  result.push Solargraph::Pin::Reference::Superclass.new(name: superclass, closure: nspin, source: :yard_map)
51
53
  end
54
+ # @sg-ignore flow sensitive typing ought to be able to handle 'when ClassName'
52
55
  code_object.class_mixins.each do |m|
53
56
  result.push Solargraph::Pin::Reference::Extend.new(closure: nspin, name: m.path, source: :yard_map)
54
57
  end
58
+ # @sg-ignore flow sensitive typing ought to be able to handle 'when ClassName'
55
59
  code_object.instance_mixins.each do |m|
56
60
  result.push Solargraph::Pin::Reference::Include.new(
57
61
  closure: nspin, # @todo Fix this
@@ -59,8 +63,9 @@ module Solargraph
59
63
  source: :yard_map
60
64
  )
61
65
  end
62
- elsif code_object.is_a?(YARD::CodeObjects::MethodObject)
66
+ when YARD::CodeObjects::MethodObject
63
67
  closure = @namespace_pins[code_object.namespace.to_s]
68
+ # @sg-ignore flow sensitive typing ought to be able to handle 'when ClassName'
64
69
  if code_object.name == :initialize && code_object.scope == :instance
65
70
  # @todo Check the visibility of <Class>.new
66
71
  result.push ToMethod.make(code_object, 'new', :class, :public, closure, @spec)
@@ -68,7 +73,7 @@ module Solargraph
68
73
  else
69
74
  result.push ToMethod.make(code_object, nil, nil, nil, closure, @spec)
70
75
  end
71
- elsif code_object.is_a?(YARD::CodeObjects::ConstantObject)
76
+ when YARD::CodeObjects::ConstantObject
72
77
  closure = @namespace_pins[code_object.namespace]
73
78
  result.push ToConstant.make(code_object, closure, @spec)
74
79
  end
@@ -1,20 +1,20 @@
1
- # frozen_string_literal: true
2
-
3
- require 'yard'
4
-
5
- # Change YARD log IO to avoid sending unexpected messages to STDOUT
6
- YARD::Logger.instance.io = File.new(File::NULL, 'w')
7
-
8
- module Solargraph
9
- # A placeholder for the @!domain directive. It doesn't need to do anything
10
- # for yardocs. It's only used for Solargraph API maps.
11
- class DomainDirective < YARD::Tags::Directive
12
- def call; end
13
- end
14
- end
15
-
16
- # Define a @type tag for documenting variables
17
- YARD::Tags::Library.define_tag("Type", :type, :with_types_and_name)
18
-
19
- # Define an @!override directive for overriding method tags
20
- YARD::Tags::Library.define_directive("override", :with_name, Solargraph::DomainDirective)
1
+ # frozen_string_literal: true
2
+
3
+ require 'yard'
4
+
5
+ # Change YARD log IO to avoid sending unexpected messages to STDOUT
6
+ YARD::Logger.instance.io = File.new(File::NULL, 'w')
7
+
8
+ module Solargraph
9
+ # A placeholder for the @!domain directive. It doesn't need to do anything
10
+ # for yardocs. It's only used for Solargraph API maps.
11
+ class DomainDirective < YARD::Tags::Directive
12
+ def call; end
13
+ end
14
+ end
15
+
16
+ # Define a @type tag for documenting variables
17
+ YARD::Tags::Library.define_tag('Type', :type, :with_types_and_name)
18
+
19
+ # Define an @!override directive for overriding method tags
20
+ YARD::Tags::Library.define_directive('override', :with_name, Solargraph::DomainDirective)
@@ -8,15 +8,15 @@ module Solargraph
8
8
  module Yardoc
9
9
  module_function
10
10
 
11
- # Build and cache a gem's yardoc and return the path. If the cache already
12
- # exists, do nothing and return the path.
11
+ # Build and save a gem's yardoc into a given path.
13
12
  #
14
- # @param yard_plugins [Array<String>] The names of YARD plugins to use.
13
+ # @param gem_yardoc_path [String] the path to the yardoc cache of a particular gem
14
+ # @param yard_plugins [Array<String>]
15
15
  # @param gemspec [Gem::Specification]
16
- # @return [String] The path to the cached yardoc.
17
- def cache(yard_plugins, gemspec)
18
- path = PinCache.yardoc_path gemspec
19
- return path if cached?(gemspec)
16
+ #
17
+ # @return [void]
18
+ def build_docs gem_yardoc_path, yard_plugins, gemspec
19
+ return if docs_built?(gem_yardoc_path)
20
20
 
21
21
  unless Dir.exist? gemspec.gem_dir
22
22
  # Can happen in at least some (old?) RubyGems versions when we
@@ -24,35 +24,44 @@ module Solargraph
24
24
  #
25
25
  # https://github.com/apiology/solargraph/actions/runs/17650140201/job/50158676842?pr=10
26
26
  Solargraph.logger.info { "Bad info from gemspec - #{gemspec.gem_dir} does not exist" }
27
- return path
27
+ return
28
28
  end
29
29
 
30
30
  Solargraph.logger.info "Caching yardoc for #{gemspec.name} #{gemspec.version}"
31
- cmd = "yardoc --db #{path} --no-output --plugin solargraph"
31
+ cmd = "yardoc --db #{gem_yardoc_path} --no-output --plugin solargraph"
32
32
  yard_plugins.each { |plugin| cmd << " --plugin #{plugin}" }
33
33
  Solargraph.logger.debug { "Running: #{cmd}" }
34
34
  # @todo set these up to run in parallel
35
+ # @sg-ignore Our fill won't work properly due to an issue in
36
+ # Callable#arity_matches? - see comment there
35
37
  stdout_and_stderr_str, status = Open3.capture2e(current_bundle_env_tweaks, cmd, chdir: gemspec.gem_dir)
36
- unless status.success?
37
- Solargraph.logger.warn { "YARD failed running #{cmd.inspect} in #{gemspec.gem_dir}" }
38
- Solargraph.logger.info stdout_and_stderr_str
39
- end
40
- path
38
+ return if status.success?
39
+ Solargraph.logger.warn { "YARD failed running #{cmd.inspect} in #{gemspec.gem_dir}" }
40
+ Solargraph.logger.info stdout_and_stderr_str
41
+ end
42
+
43
+ # @param gem_yardoc_path [String] the path to the yardoc cache of a particular gem
44
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
45
+ # @param out [StringIO, IO, nil] where to log messages
46
+ # @return [Array<Pin::Base>]
47
+ def build_pins gem_yardoc_path, gemspec, out: $stderr
48
+ yardoc = load!(gem_yardoc_path)
49
+ YardMap::Mapper.new(yardoc, gemspec).map
41
50
  end
42
51
 
43
52
  # True if the gem yardoc is cached.
44
53
  #
45
- # @param gemspec [Gem::Specification]
46
- def cached?(gemspec)
47
- yardoc = File.join(PinCache.yardoc_path(gemspec), 'complete')
54
+ # @param gem_yardoc_path [String]
55
+ def docs_built? gem_yardoc_path
56
+ yardoc = File.join(gem_yardoc_path, 'complete')
48
57
  File.exist?(yardoc)
49
58
  end
50
59
 
51
60
  # True if another process is currently building the yardoc cache.
52
61
  #
53
- # @param gemspec [Gem::Specification]
54
- def processing?(gemspec)
55
- yardoc = File.join(PinCache.yardoc_path(gemspec), 'processing')
62
+ # @param gem_yardoc_path [String] the path to the yardoc cache of a particular gem
63
+ def processing? gem_yardoc_path
64
+ yardoc = File.join(gem_yardoc_path, 'processing')
56
65
  File.exist?(yardoc)
57
66
  end
58
67
 
@@ -60,10 +69,10 @@ module Solargraph
60
69
  #
61
70
  # @note This method modifies the global YARD registry.
62
71
  #
63
- # @param gemspec [Gem::Specification]
72
+ # @param gem_yardoc_path [String] the path to the yardoc cache of a particular gem
64
73
  # @return [Array<YARD::CodeObjects::Base>]
65
- def load!(gemspec)
66
- YARD::Registry.load! PinCache.yardoc_path gemspec
74
+ def load! gem_yardoc_path
75
+ YARD::Registry.load! gem_yardoc_path
67
76
  YARD::Registry.all
68
77
  end
69
78
 
@@ -78,6 +87,7 @@ module Solargraph
78
87
  # @return [Hash{String => String}] a hash of environment variables to override
79
88
  def current_bundle_env_tweaks
80
89
  tweaks = {}
90
+ # @sg-ignore Translate to something flow sensitive typing understands
81
91
  if ENV['BUNDLE_GEMFILE'] && !ENV['BUNDLE_GEMFILE'].empty?
82
92
  tweaks['BUNDLE_GEMFILE'] = File.expand_path(ENV['BUNDLE_GEMFILE'])
83
93
  end
data/lib/solargraph.rb CHANGED
@@ -55,8 +55,8 @@ module Solargraph
55
55
 
56
56
  CHDIR_MUTEX = Mutex.new
57
57
 
58
- # @param type [Symbol] Type of assert.
59
- def self.asserts_on?(type)
58
+ def self.asserts_on?
59
+ # @sg-ignore Translate to something flow sensitive typing understands
60
60
  if ENV['SOLARGRAPH_ASSERTS'].nil? || ENV['SOLARGRAPH_ASSERTS'].empty?
61
61
  false
62
62
  elsif ENV['SOLARGRAPH_ASSERTS'] == 'on'
@@ -71,8 +71,29 @@ module Solargraph
71
71
  # @param msg [String, nil] An optional message to log
72
72
  # @param block [Proc] A block that returns a message to log
73
73
  # @return [void]
74
- def self.assert_or_log(type, msg = nil, &block)
75
- raise (msg || block.call) if asserts_on?(type) && ![:combine_with_visibility].include?(type)
74
+ def self.assert_or_log type, msg = nil, &block
75
+ if asserts_on?
76
+ # @type [String, nil]
77
+ msg ||= block.call
78
+
79
+ raise "No message given for #{type.inspect}" if msg.nil?
80
+
81
+ # conditional aliases to handle compatibility corner cases
82
+ # @sg-ignore flow sensitive typing needs to handle 'raise if'
83
+ return if type == :alias_target_missing && msg.include?('highline/compatibility.rb')
84
+ # @sg-ignore flow sensitive typing needs to handle 'raise if'
85
+ return if type == :alias_target_missing && msg.include?('lib/json/add/date.rb')
86
+ # @todo :combine_with_visibility is not ready for prime time -
87
+ # lots of disagreements found in practice that heuristics need
88
+ # to be created for and/or debugging needs to resolve in pin
89
+ # generation.
90
+ # @todo :api_map_namespace_pin_stack triggers in a badly handled
91
+ # self type case - 'keeps track of self type in method
92
+ # parameters in subclass' in call_spec.rb
93
+ return if %i[api_map_namespace_pin_stack combine_with_visibility].include?(type)
94
+
95
+ raise msg
96
+ end
76
97
  logger.info msg, &block
77
98
  end
78
99
 
@@ -92,10 +113,10 @@ module Solargraph
92
113
  # @return [generic<T>]
93
114
  def self.with_clean_env &block
94
115
  meth = if Bundler.respond_to?(:with_original_env)
95
- :with_original_env
96
- else
97
- :with_clean_env
98
- end
116
+ :with_original_env
117
+ else
118
+ :with_clean_env
119
+ end
99
120
  Bundler.send meth, &block
100
121
  end
101
122
  end