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
@@ -1,12 +1,437 @@
1
- require 'yard-activesupport-concern'
1
+ # frozen_string_literal: true
2
+
2
3
  require 'fileutils'
3
4
  require 'rbs'
5
+ require 'rubygems'
4
6
 
5
7
  module Solargraph
6
- module PinCache
8
+ class PinCache
9
+ include Logging
10
+
11
+ attr_reader :directory, :rbs_collection_path, :rbs_collection_config_path, :yard_plugins
12
+
13
+ # @param rbs_collection_path [String, nil]
14
+ # @param rbs_collection_config_path [String, nil]
15
+ # @param directory [String, nil]
16
+ # @param yard_plugins [Array<String>]
17
+ def initialize rbs_collection_path:, rbs_collection_config_path:,
18
+ directory:,
19
+ yard_plugins:
20
+ @rbs_collection_path = rbs_collection_path
21
+ @rbs_collection_config_path = rbs_collection_config_path
22
+ @directory = directory
23
+ @yard_plugins = yard_plugins
24
+ end
25
+
26
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
27
+ def cached? gemspec
28
+ rbs_version_cache_key = lookup_rbs_version_cache_key(gemspec)
29
+ combined_gem?(gemspec, rbs_version_cache_key)
30
+ end
31
+
32
+ # @param gemspec [Gem::Specification]
33
+ # @param rebuild [Boolean] whether to rebuild the cache regardless of whether it already exists
34
+ # @param out [StringIO, IO, nil] output stream for logging
35
+ # @return [void]
36
+ def cache_gem gemspec:, rebuild: false, out: nil
37
+ rbs_version_cache_key = lookup_rbs_version_cache_key(gemspec)
38
+
39
+ build_yard, build_rbs_collection, build_combined =
40
+ calculate_build_needs(gemspec,
41
+ rebuild: rebuild,
42
+ rbs_version_cache_key: rbs_version_cache_key)
43
+
44
+ return unless build_yard || build_rbs_collection || build_combined
45
+
46
+ build_combine_and_cache(gemspec,
47
+ rbs_version_cache_key,
48
+ build_yard: build_yard,
49
+ build_rbs_collection: build_rbs_collection,
50
+ build_combined: build_combined,
51
+ out: out)
52
+ end
53
+
54
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
55
+ # @param rbs_version_cache_key [String, nil]
56
+ def suppress_yard_cache? gemspec, rbs_version_cache_key
57
+ if gemspec.name == 'parser' && rbs_version_cache_key != RbsMap::CACHE_KEY_UNRESOLVED
58
+ # parser takes forever to build YARD pins, but has excellent RBS collection pins
59
+ return true
60
+ end
61
+ false
62
+ end
63
+
64
+ # @param out [StringIO, IO, nil] output stream for logging
65
+ # @param rebuild [Boolean] build pins regardless of whether we
66
+ # have cached them already
67
+ #
68
+ # @return [void]
69
+ def cache_all_stdlibs rebuild: false, out: $stderr
70
+ possible_stdlibs.each do |stdlib|
71
+ RbsMap::StdlibMap.new(stdlib, rebuild: rebuild, out: out)
72
+ end
73
+ end
74
+
75
+ # @param path [String] require path that might be in the RBS stdlib collection
76
+ # @return [void]
77
+ def cache_stdlib_rbs_map path
78
+ # these are held in memory in RbsMap::StdlibMap
79
+ map = RbsMap::StdlibMap.load(path)
80
+ if map.resolved?
81
+ logger.debug { "Loading stdlib pins for #{path}" }
82
+ pins = map.pins
83
+ logger.debug { "Loaded #{pins.length} stdlib pins for #{path}" }
84
+ pins
85
+ else
86
+ # @todo Temporarily ignoring unresolved `require 'set'`
87
+ logger.debug { "Require path #{path} could not be resolved in RBS" } unless path == 'set'
88
+ nil
89
+ end
90
+ end
91
+
92
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
93
+ #
94
+ # @return [String]
95
+ def lookup_rbs_version_cache_key gemspec
96
+ rbs_map = RbsMap.from_gemspec(gemspec, rbs_collection_path, rbs_collection_config_path)
97
+ rbs_map.cache_key
98
+ end
99
+
100
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
101
+ # @param rbs_version_cache_key [String, nil]
102
+ # @param yard_pins [Array<Pin::Base>]
103
+ # @param rbs_collection_pins [Array<Pin::Base>]
104
+ # @return [void]
105
+ def cache_combined_pins gemspec, rbs_version_cache_key, yard_pins, rbs_collection_pins
106
+ combined_pins = GemPins.combine(yard_pins, rbs_collection_pins)
107
+ serialize_combined_gem(gemspec, rbs_version_cache_key, combined_pins)
108
+ end
109
+
110
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
111
+ # @return [Array<Pin::Base>, nil]
112
+ def deserialize_combined_pin_cache gemspec
113
+ rbs_version_cache_key = lookup_rbs_version_cache_key(gemspec)
114
+
115
+ load_combined_gem(gemspec, rbs_version_cache_key)
116
+ end
117
+
118
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
119
+ # @param out [StringIO, IO, nil]
120
+ # @return [void]
121
+ def uncache_gem gemspec, out: nil
122
+ PinCache.uncache(yardoc_path(gemspec), out: out)
123
+ PinCache.uncache(yard_gem_path(gemspec), out: out)
124
+ uncache_by_prefix(rbs_collection_pins_path_prefix(gemspec), out: out)
125
+ uncache_by_prefix(combined_path_prefix(gemspec), out: out)
126
+ rbs_version_cache_key = lookup_rbs_version_cache_key(gemspec)
127
+ combined_pins_in_memory.delete([gemspec.name, gemspec.version, rbs_version_cache_key])
128
+ end
129
+
130
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
131
+ def yardoc_processing? gemspec
132
+ Yardoc.processing?(yardoc_path(gemspec))
133
+ end
134
+
135
+ # @return [Array<String>] a list of possible standard library names
136
+ def possible_stdlibs
137
+ # all dirs and .rb files in Gem::RUBYGEMS_DIR
138
+ Dir.glob(File.join(Gem::RUBYGEMS_DIR, '*')).map do |file_or_dir|
139
+ basename = File.basename(file_or_dir)
140
+ # remove .rb
141
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
142
+ basename = basename[0..-4] if basename.end_with?('.rb')
143
+ basename
144
+ end.sort.uniq
145
+ rescue StandardError => e
146
+ logger.info { "Failed to get possible stdlibs: #{e.message}" }
147
+ # @sg-ignore Need to add nil check here
148
+ logger.debug { e.backtrace.join("\n") }
149
+ []
150
+ end
151
+
152
+ private
153
+
154
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
155
+ # @param rebuild [Boolean] whether to rebuild the cache regardless of whether it already exists
156
+ # @param rbs_version_cache_key [String, nil] the cache key for the gem in the RBS collection
157
+ #
158
+ # @return [Array(Boolean, Boolean, Boolean)] whether to build YARD
159
+ # pins, RBS collection pins, and combined pins
160
+ def calculate_build_needs gemspec, rebuild:, rbs_version_cache_key:
161
+ if rebuild
162
+ build_yard = true
163
+ build_rbs_collection = true
164
+ build_combined = true
165
+ else
166
+ build_yard = !yard_gem?(gemspec)
167
+ build_rbs_collection = !rbs_collection_pins?(gemspec, rbs_version_cache_key)
168
+ # @sg-ignore Need to add nil check here
169
+ build_combined = !combined_gem?(gemspec, rbs_version_cache_key) || build_yard || build_rbs_collection
170
+ end
171
+
172
+ build_yard = false if suppress_yard_cache?(gemspec, rbs_version_cache_key)
173
+
174
+ [build_yard, build_rbs_collection, build_combined]
175
+ end
176
+
177
+ # @param gemspec [Gem::Specification]
178
+ # @param rbs_version_cache_key [String, nil]
179
+ # @param build_yard [Boolean]
180
+ # @param build_rbs_collection [Boolean]
181
+ # @param build_combined [Boolean]
182
+ # @param out [StringIO, IO, nil]
183
+ #
184
+ # @return [void]
185
+ def build_combine_and_cache gemspec,
186
+ rbs_version_cache_key,
187
+ build_yard:,
188
+ build_rbs_collection:,
189
+ build_combined:,
190
+ out:
191
+ log_cache_info(gemspec, rbs_version_cache_key,
192
+ build_yard: build_yard,
193
+ build_rbs_collection: build_rbs_collection,
194
+ build_combined: build_combined,
195
+ out: out)
196
+ cache_yard_pins(gemspec, out) if build_yard
197
+ # this can be nil even if we aren't told to build it - see suppress_yard_cache?
198
+ yard_pins = deserialize_yard_pin_cache(gemspec) || []
199
+ cache_rbs_collection_pins(gemspec, out) if build_rbs_collection
200
+ rbs_collection_pins = deserialize_rbs_collection_cache(gemspec, rbs_version_cache_key) || []
201
+ cache_combined_pins(gemspec, rbs_version_cache_key, yard_pins, rbs_collection_pins) if build_combined
202
+ end
203
+
204
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
205
+ # @param rbs_version_cache_key [String, nil]
206
+ # @param build_yard [Boolean]
207
+ # @param build_rbs_collection [Boolean]
208
+ # @param build_combined [Boolean]
209
+ # @param out [StringIO, IO, nil]
210
+ #
211
+ # @return [void]
212
+ def log_cache_info gemspec,
213
+ rbs_version_cache_key,
214
+ build_yard:,
215
+ build_rbs_collection:,
216
+ build_combined:,
217
+ out:
218
+ type = []
219
+ type << 'YARD' if build_yard
220
+ rbs_source_desc = RbsMap.rbs_source_desc(rbs_version_cache_key)
221
+ type << rbs_source_desc if build_rbs_collection && !rbs_source_desc.nil?
222
+ # we'll build it anyway, but it won't take long to build with
223
+ # only a single source
224
+
225
+ # 'combining' is awkward terminology in this case
226
+ just_yard = build_yard && rbs_source_desc.nil?
227
+
228
+ type << 'combined' if build_combined && !just_yard
229
+ out&.puts("Caching #{type.join(' and ')} pins for gem #{gemspec.name}:#{gemspec.version}")
230
+ end
231
+
232
+ # @param gemspec [Gem::Specification]
233
+ # @param out [StringIO, IO, nil]
234
+ # @return [Array<Pin::Base>]
235
+ def cache_yard_pins gemspec, out
236
+ gem_yardoc_path = yardoc_path(gemspec)
237
+ Yardoc.build_docs(gem_yardoc_path, yard_plugins, gemspec) unless Yardoc.docs_built?(gem_yardoc_path)
238
+ pins = Yardoc.build_pins(gem_yardoc_path, gemspec, out: out)
239
+ serialize_yard_gem(gemspec, pins)
240
+ logger.info { "Cached #{pins.length} YARD pins for gem #{gemspec.name}:#{gemspec.version}" } unless pins.empty?
241
+ pins
242
+ end
243
+
244
+ # @return [Hash{Array(String, String, String) => Array<Pin::Base>}]
245
+ def combined_pins_in_memory
246
+ PinCache.all_combined_pins_in_memory[yard_plugins] ||= {}
247
+ end
248
+
249
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
250
+ # @param _out [StringIO, IO, nil]
251
+ # @return [Array<Pin::Base>]
252
+ def cache_rbs_collection_pins gemspec, _out
253
+ rbs_map = RbsMap.from_gemspec(gemspec, rbs_collection_path, rbs_collection_config_path)
254
+ pins = rbs_map.pins
255
+ rbs_version_cache_key = rbs_map.cache_key
256
+ # cache pins even if result is zero, so we don't retry building pins
257
+ pins ||= []
258
+ serialize_rbs_collection_pins(gemspec, rbs_version_cache_key, pins)
259
+ logger.info do
260
+ unless pins.empty?
261
+ "Cached #{pins.length} RBS collection pins for gem #{gemspec.name} #{gemspec.version} with " \
262
+ "cache_key #{rbs_version_cache_key.inspect}"
263
+ end
264
+ end
265
+ pins
266
+ end
267
+
268
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
269
+ # @return [Array<Pin::Base>, nil]
270
+ def deserialize_yard_pin_cache gemspec
271
+ cached = load_yard_gem(gemspec)
272
+ if cached
273
+ cached
274
+ else
275
+ logger.debug "No YARD pin cache for #{gemspec.name}:#{gemspec.version}"
276
+ nil
277
+ end
278
+ end
279
+
280
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
281
+ # @param rbs_version_cache_key [String, nil]
282
+ # @return [Array<Pin::Base>, nil]
283
+ def deserialize_rbs_collection_cache gemspec, rbs_version_cache_key
284
+ cached = load_rbs_collection_pins(gemspec, rbs_version_cache_key)
285
+ Solargraph.assert_or_log(:pin_cache_rbs_collection, 'Asked for non-existent rbs collection') if cached.nil?
286
+ logger.info do
287
+ "Loaded #{cached&.length} pins from RBS collection cache for #{gemspec.name}:#{gemspec.version}"
288
+ end
289
+ cached
290
+ end
291
+
292
+ # @return [Array<String>]
293
+ def yard_path_components
294
+ ["yard-#{YARD::VERSION}",
295
+ yard_plugins.sort.uniq.join('-')]
296
+ end
297
+
298
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
299
+ # @return [String]
300
+ def yardoc_path gemspec
301
+ File.join(PinCache.base_dir,
302
+ *yard_path_components,
303
+ "#{gemspec.name}-#{gemspec.version}.yardoc")
304
+ end
305
+
306
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
307
+ # @return [String]
308
+ def yard_gem_path gemspec
309
+ File.join(PinCache.work_dir, *yard_path_components, "#{gemspec.name}-#{gemspec.version}.ser")
310
+ end
311
+
312
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
313
+ # @return [Array<Pin::Base>, nil]
314
+ def load_yard_gem gemspec
315
+ PinCache.load(yard_gem_path(gemspec))
316
+ end
317
+
318
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
319
+ # @param pins [Array<Pin::Base>]
320
+ # @return [void]
321
+ def serialize_yard_gem gemspec, pins
322
+ PinCache.save(yard_gem_path(gemspec), pins)
323
+ end
324
+
325
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
326
+ # @return [Boolean]
327
+ def yard_gem? gemspec
328
+ exist?(yard_gem_path(gemspec))
329
+ end
330
+
331
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
332
+ # @param hash [String, nil]
333
+ # @return [String]
334
+ def rbs_collection_pins_path gemspec, hash
335
+ rbs_collection_pins_path_prefix(gemspec) + "#{hash || 0}.ser"
336
+ end
337
+
338
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
339
+ # @return [String]
340
+ def rbs_collection_pins_path_prefix gemspec
341
+ File.join(PinCache.work_dir, 'rbs', "#{gemspec.name}-#{gemspec.version}-")
342
+ end
343
+
344
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
345
+ # @param hash [String, nil]
346
+ #
347
+ # @return [Array<Pin::Base>, nil]
348
+ def load_rbs_collection_pins gemspec, hash
349
+ PinCache.load(rbs_collection_pins_path(gemspec, hash))
350
+ end
351
+
352
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
353
+ # @param hash [String, nil]
354
+ # @param pins [Array<Pin::Base>]
355
+ # @return [void]
356
+ def serialize_rbs_collection_pins gemspec, hash, pins
357
+ PinCache.save(rbs_collection_pins_path(gemspec, hash), pins)
358
+ end
359
+
360
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
361
+ # @param hash [String, nil]
362
+ # @return [String]
363
+ def combined_path gemspec, hash
364
+ File.join(combined_path_prefix(gemspec) + "-#{hash || 0}.ser")
365
+ end
366
+
367
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
368
+ # @return [String]
369
+ def combined_path_prefix gemspec
370
+ File.join(PinCache.work_dir, 'combined', yard_plugins.sort.join('-'), "#{gemspec.name}-#{gemspec.version}")
371
+ end
372
+
373
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
374
+ # @param hash [String, nil]
375
+ # @param pins [Array<Pin::Base>]
376
+ # @return [void]
377
+ def serialize_combined_gem gemspec, hash, pins
378
+ PinCache.save(combined_path(gemspec, hash), pins)
379
+ end
380
+
381
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
382
+ # @param hash [String]
383
+ def combined_gem? gemspec, hash
384
+ exist?(combined_path(gemspec, hash))
385
+ end
386
+
387
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
388
+ # @param hash [String, nil]
389
+ # @return [Array<Pin::Base>, nil]
390
+ def load_combined_gem gemspec, hash
391
+ cached = combined_pins_in_memory[[gemspec.name, gemspec.version, hash]]
392
+ return cached if cached
393
+ loaded = PinCache.load(combined_path(gemspec, hash))
394
+ combined_pins_in_memory[[gemspec.name, gemspec.version, hash]] = loaded if loaded
395
+ loaded
396
+ end
397
+
398
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
399
+ # @param hash [String, nil]
400
+ def rbs_collection_pins? gemspec, hash
401
+ exist?(rbs_collection_pins_path(gemspec, hash))
402
+ end
403
+
404
+ include Logging
405
+
406
+ # @param path [String]
407
+ def exist? *path
408
+ File.file? File.join(*path)
409
+ end
410
+
411
+ # @return [void]
412
+ # @param path_segments [Array<String>]
413
+ # @param out [StringIO, IO, nil]
414
+ def uncache_by_prefix *path_segments, out: nil
415
+ path = File.join(*path_segments)
416
+ glob = "#{path}*"
417
+ out&.puts "Clearing pin cache in #{glob}"
418
+ Dir.glob(glob).each do |file|
419
+ next unless File.file?(file)
420
+ FileUtils.rm_rf file, secure: true
421
+ out&.puts "Clearing pin cache in #{file}"
422
+ end
423
+ end
424
+
7
425
  class << self
8
426
  include Logging
9
427
 
428
+ # @return [Hash{Array<String> => Hash{Array(String, String) =>
429
+ # Array<Pin::Base>}}] yard plugins, then gemspec name and
430
+ # version
431
+ def all_combined_pins_in_memory
432
+ @all_combined_pins_in_memory ||= {}
433
+ end
434
+
10
435
  # The base directory where cached YARD documentation and serialized pins are serialized
11
436
  #
12
437
  # @return [String]
@@ -18,6 +443,47 @@ module Solargraph
18
443
  File.join(Dir.home, '.cache', 'solargraph')
19
444
  end
20
445
 
446
+ # @param path_segments [Array<String>]
447
+ # @param out [IO, nil]
448
+ # @return [void]
449
+ def uncache *path_segments, out: nil
450
+ path = File.join(*path_segments)
451
+ if File.exist?(path)
452
+ FileUtils.rm_rf path, secure: true
453
+ out&.puts "Clearing pin cache in #{path}"
454
+ else
455
+ out&.puts "Pin cache file #{path} does not exist"
456
+ end
457
+ end
458
+
459
+ # @return [void]
460
+ # @param out [IO, nil]
461
+ # @param path_segments [Array<String>]
462
+ def uncache_by_prefix *path_segments, out: nil
463
+ path = File.join(*path_segments)
464
+ glob = "#{path}*"
465
+ out&.puts "Clearing pin cache in #{glob}"
466
+ Dir.glob(glob).each do |file|
467
+ next unless File.file?(file)
468
+ FileUtils.rm_rf file, secure: true
469
+ out&.puts "Clearing pin cache in #{file}"
470
+ end
471
+ end
472
+
473
+ # @param out [StringIO, IO, nil]
474
+ # @return [void]
475
+ def uncache_core out: nil
476
+ uncache(core_path, out: out)
477
+ # ApiMap keep this in memory
478
+ ApiMap.reset_core(out: out)
479
+ end
480
+
481
+ # @param out [StringIO, IO, nil]
482
+ # @return [void]
483
+ def uncache_stdlib out: nil
484
+ uncache(stdlib_path, out: out)
485
+ end
486
+
21
487
  # The working directory for the current Ruby, RBS, and Solargraph versions.
22
488
  #
23
489
  # @return [String]
@@ -27,15 +493,6 @@ module Solargraph
27
493
  File.join(base_dir, "ruby-#{RUBY_VERSION}", "rbs-#{RBS::VERSION}", "solargraph-#{Solargraph::VERSION}")
28
494
  end
29
495
 
30
- # @param gemspec [Gem::Specification]
31
- # @return [String]
32
- def yardoc_path gemspec
33
- File.join(base_dir,
34
- "yard-#{YARD::VERSION}",
35
- "yard-activesupport-concern-#{YARD::ActiveSupport::Concern::VERSION}",
36
- "#{gemspec.name}-#{gemspec.version}.yardoc")
37
- end
38
-
39
496
  # @return [String]
40
497
  def stdlib_path
41
498
  File.join(work_dir, 'stdlib')
@@ -84,40 +541,34 @@ module Solargraph
84
541
 
85
542
  # @param gemspec [Gem::Specification]
86
543
  # @return [Array<Pin::Base>, nil]
87
- def deserialize_yard_gem(gemspec)
544
+ def deserialize_yard_gem gemspec
88
545
  load(yard_gem_path(gemspec))
89
546
  end
90
547
 
91
548
  # @param gemspec [Gem::Specification]
92
549
  # @param pins [Array<Pin::Base>]
93
550
  # @return [void]
94
- def serialize_yard_gem(gemspec, pins)
551
+ def serialize_yard_gem gemspec, pins
95
552
  save(yard_gem_path(gemspec), pins)
96
553
  end
97
554
 
98
- # @param gemspec [Gem::Specification]
99
- # @return [Boolean]
100
- def has_yard?(gemspec)
101
- exist?(yard_gem_path(gemspec))
102
- end
103
-
104
555
  # @param gemspec [Gem::Specification]
105
556
  # @param hash [String, nil]
106
557
  # @return [String]
107
- def rbs_collection_path(gemspec, hash)
558
+ def rbs_collection_path gemspec, hash
108
559
  File.join(work_dir, 'rbs', "#{gemspec.name}-#{gemspec.version}-#{hash || 0}.ser")
109
560
  end
110
561
 
111
562
  # @param gemspec [Gem::Specification]
112
563
  # @return [String]
113
- def rbs_collection_path_prefix(gemspec)
564
+ def rbs_collection_path_prefix gemspec
114
565
  File.join(work_dir, 'rbs', "#{gemspec.name}-#{gemspec.version}-")
115
566
  end
116
567
 
117
568
  # @param gemspec [Gem::Specification]
118
569
  # @param hash [String, nil]
119
570
  # @return [Array<Pin::Base>, nil]
120
- def deserialize_rbs_collection_gem(gemspec, hash)
571
+ def deserialize_rbs_collection_gem gemspec, hash
121
572
  load(rbs_collection_path(gemspec, hash))
122
573
  end
123
574
 
@@ -125,20 +576,20 @@ module Solargraph
125
576
  # @param hash [String, nil]
126
577
  # @param pins [Array<Pin::Base>]n
127
578
  # @return [void]
128
- def serialize_rbs_collection_gem(gemspec, hash, pins)
579
+ def serialize_rbs_collection_gem gemspec, hash, pins
129
580
  save(rbs_collection_path(gemspec, hash), pins)
130
581
  end
131
582
 
132
583
  # @param gemspec [Gem::Specification]
133
584
  # @param hash [String, nil]
134
585
  # @return [String]
135
- def combined_path(gemspec, hash)
586
+ def combined_path gemspec, hash
136
587
  File.join(work_dir, 'combined', "#{gemspec.name}-#{gemspec.version}-#{hash || 0}.ser")
137
588
  end
138
589
 
139
590
  # @param gemspec [Gem::Specification]
140
591
  # @return [String]
141
- def combined_path_prefix(gemspec)
592
+ def combined_path_prefix gemspec
142
593
  File.join(work_dir, 'combined', "#{gemspec.name}-#{gemspec.version}-")
143
594
  end
144
595
 
@@ -146,7 +597,7 @@ module Solargraph
146
597
  # @param hash [String, nil]
147
598
  # @param pins [Array<Pin::Base>]
148
599
  # @return [void]
149
- def serialize_combined_gem(gemspec, hash, pins)
600
+ def serialize_combined_gem gemspec, hash, pins
150
601
  save(combined_path(gemspec, hash), pins)
151
602
  end
152
603
 
@@ -160,38 +611,17 @@ module Solargraph
160
611
  # @param gemspec [Gem::Specification]
161
612
  # @param hash [String, nil]
162
613
  # @return [Boolean]
163
- def has_rbs_collection?(gemspec, hash)
614
+ def has_rbs_collection? gemspec, hash
164
615
  exist?(rbs_collection_path(gemspec, hash))
165
616
  end
166
617
 
167
- # @return [void]
168
- def uncache_core
169
- uncache(core_path)
170
- end
171
-
172
- # @return [void]
173
- def uncache_stdlib
174
- uncache(stdlib_path)
175
- end
176
-
177
- # @param gemspec [Gem::Specification]
178
- # @param out [IO, nil]
179
- # @return [void]
180
- def uncache_gem(gemspec, out: nil)
181
- uncache(yardoc_path(gemspec), out: out)
182
- uncache_by_prefix(rbs_collection_path_prefix(gemspec), out: out)
183
- uncache(yard_gem_path(gemspec), out: out)
184
- uncache_by_prefix(combined_path_prefix(gemspec), out: out)
185
- end
186
-
187
618
  # @return [void]
188
619
  def clear
189
620
  FileUtils.rm_rf base_dir, secure: true
190
621
  end
191
622
 
192
- private
193
-
194
623
  # @param file [String]
624
+ # @sg-ignore Marshal.load evaluates to boolean here which is wrong
195
625
  # @return [Array<Solargraph::Pin::Base>, nil]
196
626
  def load file
197
627
  return nil unless File.file?(file)
@@ -202,11 +632,6 @@ module Solargraph
202
632
  nil
203
633
  end
204
634
 
205
- # @param path [String]
206
- def exist? *path
207
- File.file? File.join(*path)
208
- end
209
-
210
635
  # @param file [String]
211
636
  # @param pins [Array<Pin::Base>]
212
637
  # @return [void]
@@ -218,27 +643,19 @@ module Solargraph
218
643
  logger.debug { "Cache#save: Saved #{pins.length} pins to #{file}" }
219
644
  end
220
645
 
221
- # @param path_segments [Array<String>]
222
- # @return [void]
223
- def uncache *path_segments, out: nil
224
- path = File.join(*path_segments)
225
- if File.exist?(path)
226
- FileUtils.rm_rf path, secure: true
227
- out.puts "Clearing pin cache in #{path}" unless out.nil?
228
- end
646
+ def core?
647
+ File.file?(core_path)
229
648
  end
230
649
 
231
- # @return [void]
232
- # @param path_segments [Array<String>]
233
- def uncache_by_prefix *path_segments, out: nil
234
- path = File.join(*path_segments)
235
- glob = "#{path}*"
236
- out.puts "Clearing pin cache in #{glob}" unless out.nil?
237
- Dir.glob(glob).each do |file|
238
- next unless File.file?(file)
239
- FileUtils.rm_rf file, secure: true
240
- out.puts "Clearing pin cache in #{file}" unless out.nil?
241
- end
650
+ # @param out [StringIO, IO, nil]
651
+ # @return [Array<Pin::Base>]
652
+ def cache_core out: $stderr
653
+ RbsMap::CoreMap.new.cache_core(out: out)
654
+ end
655
+
656
+ # @param path [String]
657
+ def exist? *path
658
+ File.file? File.join(*path)
242
659
  end
243
660
  end
244
661
  end