solargraph 0.46.0 → 0.47.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (246) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec.yml +41 -41
  3. data/.gitignore +9 -9
  4. data/.rspec +2 -2
  5. data/.travis.yml +19 -19
  6. data/CHANGELOG.md +1123 -1115
  7. data/Gemfile +0 -0
  8. data/LICENSE +0 -0
  9. data/README.md +128 -128
  10. data/Rakefile +0 -0
  11. data/SPONSORS.md +17 -18
  12. data/bin/solargraph +0 -0
  13. data/lib/solargraph/api_map/bundler_methods.rb +22 -22
  14. data/lib/solargraph/api_map/cache.rb +70 -70
  15. data/lib/solargraph/api_map/source_to_yard.rb +81 -81
  16. data/lib/solargraph/api_map/store.rb +256 -256
  17. data/lib/solargraph/api_map.rb +686 -686
  18. data/lib/solargraph/bench.rb +27 -27
  19. data/lib/solargraph/compat.rb +37 -37
  20. data/lib/solargraph/complex_type/type_methods.rb +130 -130
  21. data/lib/solargraph/complex_type/unique_type.rb +75 -75
  22. data/lib/solargraph/complex_type.rb +221 -221
  23. data/lib/solargraph/convention/base.rb +33 -33
  24. data/lib/solargraph/convention/gemfile.rb +15 -15
  25. data/lib/solargraph/convention/gemspec.rb +22 -22
  26. data/lib/solargraph/convention/rspec.rb +30 -30
  27. data/lib/solargraph/convention.rb +47 -47
  28. data/lib/solargraph/converters/dd.rb +12 -12
  29. data/lib/solargraph/converters/dl.rb +12 -12
  30. data/lib/solargraph/converters/dt.rb +12 -12
  31. data/lib/solargraph/converters/misc.rb +1 -1
  32. data/lib/solargraph/diagnostics/base.rb +29 -29
  33. data/lib/solargraph/diagnostics/require_not_found.rb +53 -53
  34. data/lib/solargraph/diagnostics/rubocop.rb +98 -98
  35. data/lib/solargraph/diagnostics/rubocop_helpers.rb +63 -63
  36. data/lib/solargraph/diagnostics/severities.rb +15 -15
  37. data/lib/solargraph/diagnostics/type_check.rb +54 -54
  38. data/lib/solargraph/diagnostics/update_errors.rb +41 -41
  39. data/lib/solargraph/diagnostics.rb +55 -55
  40. data/lib/solargraph/documentor.rb +76 -76
  41. data/lib/solargraph/environ.rb +45 -45
  42. data/lib/solargraph/language_server/completion_item_kinds.rb +35 -35
  43. data/lib/solargraph/language_server/error_codes.rb +20 -20
  44. data/lib/solargraph/language_server/host/cataloger.rb +56 -56
  45. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  46. data/lib/solargraph/language_server/host/dispatch.rb +111 -111
  47. data/lib/solargraph/language_server/host/message_worker.rb +59 -59
  48. data/lib/solargraph/language_server/host/sources.rb +156 -156
  49. data/lib/solargraph/language_server/host.rb +865 -865
  50. data/lib/solargraph/language_server/message/base.rb +89 -89
  51. data/lib/solargraph/language_server/message/cancel_request.rb +13 -13
  52. data/lib/solargraph/language_server/message/client/register_capability.rb +15 -15
  53. data/lib/solargraph/language_server/message/client.rb +11 -11
  54. data/lib/solargraph/language_server/message/completion_item/resolve.rb +58 -58
  55. data/lib/solargraph/language_server/message/completion_item.rb +11 -11
  56. data/lib/solargraph/language_server/message/exit_notification.rb +13 -13
  57. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +100 -100
  58. data/lib/solargraph/language_server/message/extended/document.rb +20 -20
  59. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
  60. data/lib/solargraph/language_server/message/extended/download_core.rb +23 -23
  61. data/lib/solargraph/language_server/message/extended/environment.rb +25 -25
  62. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  63. data/lib/solargraph/language_server/message/extended.rb +21 -21
  64. data/lib/solargraph/language_server/message/initialize.rb +162 -162
  65. data/lib/solargraph/language_server/message/initialized.rb +27 -27
  66. data/lib/solargraph/language_server/message/method_not_found.rb +16 -16
  67. data/lib/solargraph/language_server/message/method_not_implemented.rb +14 -14
  68. data/lib/solargraph/language_server/message/shutdown.rb +13 -13
  69. data/lib/solargraph/language_server/message/text_document/base.rb +19 -19
  70. data/lib/solargraph/language_server/message/text_document/code_action.rb +17 -17
  71. data/lib/solargraph/language_server/message/text_document/completion.rb +59 -59
  72. data/lib/solargraph/language_server/message/text_document/definition.rb +38 -38
  73. data/lib/solargraph/language_server/message/text_document/did_change.rb +15 -15
  74. data/lib/solargraph/language_server/message/text_document/did_close.rb +15 -15
  75. data/lib/solargraph/language_server/message/text_document/did_open.rb +15 -15
  76. data/lib/solargraph/language_server/message/text_document/did_save.rb +17 -17
  77. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +16 -16
  78. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +23 -23
  79. data/lib/solargraph/language_server/message/text_document/folding_range.rb +26 -26
  80. data/lib/solargraph/language_server/message/text_document/formatting.rb +126 -126
  81. data/lib/solargraph/language_server/message/text_document/hover.rb +56 -54
  82. data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +34 -34
  83. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -11
  84. data/lib/solargraph/language_server/message/text_document/references.rb +16 -16
  85. data/lib/solargraph/language_server/message/text_document/rename.rb +19 -19
  86. data/lib/solargraph/language_server/message/text_document/signature_help.rb +29 -29
  87. data/lib/solargraph/language_server/message/text_document.rb +28 -28
  88. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +30 -30
  89. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +33 -33
  90. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -24
  91. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -23
  92. data/lib/solargraph/language_server/message/workspace.rb +14 -14
  93. data/lib/solargraph/language_server/message.rb +93 -93
  94. data/lib/solargraph/language_server/message_types.rb +14 -14
  95. data/lib/solargraph/language_server/request.rb +24 -24
  96. data/lib/solargraph/language_server/symbol_kinds.rb +36 -36
  97. data/lib/solargraph/language_server/transport/adapter.rb +53 -53
  98. data/lib/solargraph/language_server/transport/data_reader.rb +72 -72
  99. data/lib/solargraph/language_server/transport.rb +13 -13
  100. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  101. data/lib/solargraph/language_server.rb +19 -19
  102. data/lib/solargraph/library.rb +546 -546
  103. data/lib/solargraph/location.rb +37 -37
  104. data/lib/solargraph/logging.rb +27 -27
  105. data/lib/solargraph/page.rb +83 -83
  106. data/lib/solargraph/parser/comment_ripper.rb +52 -52
  107. data/lib/solargraph/parser/legacy/class_methods.rb +135 -135
  108. data/lib/solargraph/parser/legacy/flawed_builder.rb +16 -16
  109. data/lib/solargraph/parser/legacy/node_chainer.rb +148 -148
  110. data/lib/solargraph/parser/legacy/node_methods.rb +325 -325
  111. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +23 -23
  112. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +35 -35
  113. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +15 -15
  114. data/lib/solargraph/parser/legacy/node_processors/block_node.rb +42 -42
  115. data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +25 -25
  116. data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +23 -23
  117. data/lib/solargraph/parser/legacy/node_processors/def_node.rb +63 -63
  118. data/lib/solargraph/parser/legacy/node_processors/defs_node.rb +36 -36
  119. data/lib/solargraph/parser/legacy/node_processors/gvasgn_node.rb +23 -23
  120. data/lib/solargraph/parser/legacy/node_processors/ivasgn_node.rb +38 -38
  121. data/lib/solargraph/parser/legacy/node_processors/lvasgn_node.rb +28 -28
  122. data/lib/solargraph/parser/legacy/node_processors/namespace_node.rb +39 -39
  123. data/lib/solargraph/parser/legacy/node_processors/orasgn_node.rb +16 -16
  124. data/lib/solargraph/parser/legacy/node_processors/resbody_node.rb +36 -36
  125. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +21 -21
  126. data/lib/solargraph/parser/legacy/node_processors/send_node.rb +257 -257
  127. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +18 -18
  128. data/lib/solargraph/parser/legacy/node_processors.rb +54 -54
  129. data/lib/solargraph/parser/legacy.rb +12 -12
  130. data/lib/solargraph/parser/node_methods.rb +43 -43
  131. data/lib/solargraph/parser/node_processor/base.rb +77 -77
  132. data/lib/solargraph/parser/node_processor.rb +43 -43
  133. data/lib/solargraph/parser/region.rb +66 -66
  134. data/lib/solargraph/parser/rubyvm/class_methods.rb +144 -144
  135. data/lib/solargraph/parser/rubyvm/node_chainer.rb +160 -160
  136. data/lib/solargraph/parser/rubyvm/node_methods.rb +315 -315
  137. data/lib/solargraph/parser/rubyvm/node_processors/alias_node.rb +23 -23
  138. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +85 -85
  139. data/lib/solargraph/parser/rubyvm/node_processors/begin_node.rb +15 -15
  140. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +42 -42
  141. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +22 -22
  142. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +23 -23
  143. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +63 -63
  144. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +57 -57
  145. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +23 -23
  146. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +38 -38
  147. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +39 -39
  148. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +20 -20
  149. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +27 -27
  150. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +39 -39
  151. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +26 -26
  152. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +15 -15
  153. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +45 -45
  154. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +21 -21
  155. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +15 -15
  156. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +277 -277
  157. data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +18 -18
  158. data/lib/solargraph/parser/rubyvm/node_processors.rb +63 -63
  159. data/lib/solargraph/parser/rubyvm.rb +40 -40
  160. data/lib/solargraph/parser/snippet.rb +13 -13
  161. data/lib/solargraph/parser.rb +26 -26
  162. data/lib/solargraph/pin/base.rb +296 -296
  163. data/lib/solargraph/pin/base_variable.rb +84 -84
  164. data/lib/solargraph/pin/block.rb +73 -72
  165. data/lib/solargraph/pin/class_variable.rb +8 -8
  166. data/lib/solargraph/pin/closure.rb +37 -37
  167. data/lib/solargraph/pin/common.rb +70 -70
  168. data/lib/solargraph/pin/constant.rb +43 -43
  169. data/lib/solargraph/pin/conversions.rb +96 -96
  170. data/lib/solargraph/pin/documenting.rb +105 -105
  171. data/lib/solargraph/pin/duck_method.rb +16 -16
  172. data/lib/solargraph/pin/global_variable.rb +8 -8
  173. data/lib/solargraph/pin/instance_variable.rb +30 -30
  174. data/lib/solargraph/pin/keyword.rb +15 -15
  175. data/lib/solargraph/pin/keyword_param.rb +8 -8
  176. data/lib/solargraph/pin/local_variable.rb +55 -55
  177. data/lib/solargraph/pin/method.rb +245 -245
  178. data/lib/solargraph/pin/method_alias.rb +31 -31
  179. data/lib/solargraph/pin/namespace.rb +91 -91
  180. data/lib/solargraph/pin/parameter.rb +201 -201
  181. data/lib/solargraph/pin/proxy_type.rb +29 -29
  182. data/lib/solargraph/pin/reference/extend.rb +10 -10
  183. data/lib/solargraph/pin/reference/include.rb +10 -10
  184. data/lib/solargraph/pin/reference/override.rb +29 -29
  185. data/lib/solargraph/pin/reference/prepend.rb +10 -10
  186. data/lib/solargraph/pin/reference/require.rb +14 -14
  187. data/lib/solargraph/pin/reference/superclass.rb +10 -10
  188. data/lib/solargraph/pin/reference.rb +14 -14
  189. data/lib/solargraph/pin/search.rb +56 -56
  190. data/lib/solargraph/pin/singleton.rb +11 -11
  191. data/lib/solargraph/pin/symbol.rb +47 -47
  192. data/lib/solargraph/pin.rb +37 -37
  193. data/lib/solargraph/position.rb +100 -100
  194. data/lib/solargraph/range.rb +95 -95
  195. data/lib/solargraph/server_methods.rb +16 -16
  196. data/lib/solargraph/shell.rb +230 -226
  197. data/lib/solargraph/source/chain/block_variable.rb +13 -13
  198. data/lib/solargraph/source/chain/call.rb +204 -204
  199. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  200. data/lib/solargraph/source/chain/constant.rb +75 -75
  201. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  202. data/lib/solargraph/source/chain/hash.rb +28 -28
  203. data/lib/solargraph/source/chain/head.rb +19 -19
  204. data/lib/solargraph/source/chain/instance_variable.rb +13 -13
  205. data/lib/solargraph/source/chain/link.rb +71 -71
  206. data/lib/solargraph/source/chain/literal.rb +23 -23
  207. data/lib/solargraph/source/chain/or.rb +23 -23
  208. data/lib/solargraph/source/chain/q_call.rb +11 -11
  209. data/lib/solargraph/source/chain/variable.rb +13 -13
  210. data/lib/solargraph/source/chain/z_super.rb +30 -30
  211. data/lib/solargraph/source/chain.rb +164 -164
  212. data/lib/solargraph/source/change.rb +79 -79
  213. data/lib/solargraph/source/cursor.rb +164 -164
  214. data/lib/solargraph/source/source_chainer.rb +191 -191
  215. data/lib/solargraph/source/updater.rb +54 -54
  216. data/lib/solargraph/source.rb +524 -522
  217. data/lib/solargraph/source_map/clip.rb +224 -224
  218. data/lib/solargraph/source_map/completion.rb +23 -23
  219. data/lib/solargraph/source_map/mapper.rb +239 -212
  220. data/lib/solargraph/source_map.rb +180 -180
  221. data/lib/solargraph/type_checker/checks.rb +99 -99
  222. data/lib/solargraph/type_checker/param_def.rb +35 -35
  223. data/lib/solargraph/type_checker/problem.rb +32 -32
  224. data/lib/solargraph/type_checker/rules.rb +57 -57
  225. data/lib/solargraph/type_checker.rb +543 -543
  226. data/lib/solargraph/version.rb +5 -5
  227. data/lib/solargraph/views/environment.erb +58 -58
  228. data/lib/solargraph/workspace/config.rb +231 -231
  229. data/lib/solargraph/workspace.rb +215 -215
  230. data/lib/solargraph/yard_map/cache.rb +19 -19
  231. data/lib/solargraph/yard_map/core_docs.rb +170 -170
  232. data/lib/solargraph/yard_map/core_fills.rb +208 -208
  233. data/lib/solargraph/yard_map/core_gen.rb +76 -76
  234. data/lib/solargraph/yard_map/helpers.rb +16 -16
  235. data/lib/solargraph/yard_map/mapper/to_constant.rb +25 -25
  236. data/lib/solargraph/yard_map/mapper/to_method.rb +78 -78
  237. data/lib/solargraph/yard_map/mapper/to_namespace.rb +27 -27
  238. data/lib/solargraph/yard_map/mapper.rb +77 -77
  239. data/lib/solargraph/yard_map/rdoc_to_yard.rb +140 -140
  240. data/lib/solargraph/yard_map/stdlib_fills.rb +43 -43
  241. data/lib/solargraph/yard_map/to_method.rb +79 -79
  242. data/lib/solargraph/yard_map.rb +460 -460
  243. data/lib/solargraph.rb +69 -69
  244. data/lib/yard-solargraph.rb +33 -33
  245. data/solargraph.gemspec +0 -0
  246. metadata +12 -12
@@ -1,460 +1,460 @@
1
- # frozen_string_literal: true
2
-
3
- require 'yard'
4
- require 'yard-solargraph'
5
- require 'rubygems/package'
6
- require 'set'
7
-
8
- module Solargraph
9
- # The YardMap provides access to YARD documentation for the Ruby core, the
10
- # stdlib, and gems.
11
- #
12
- class YardMap
13
- class NoYardocError < StandardError; end
14
-
15
- autoload :Cache, 'solargraph/yard_map/cache'
16
- autoload :CoreDocs, 'solargraph/yard_map/core_docs'
17
- autoload :CoreGen, 'solargraph/yard_map/core_gen'
18
- autoload :Mapper, 'solargraph/yard_map/mapper'
19
- autoload :RdocToYard, 'solargraph/yard_map/rdoc_to_yard'
20
- autoload :CoreFills, 'solargraph/yard_map/core_fills'
21
- autoload :StdlibFills, 'solargraph/yard_map/stdlib_fills'
22
- autoload :Helpers, 'solargraph/yard_map/helpers'
23
- autoload :ToMethod, 'solargraph/yard_map/to_method'
24
-
25
- include ApiMap::BundlerMethods
26
-
27
- CoreDocs.require_minimum
28
-
29
- def stdlib_paths
30
- @@stdlib_paths ||= begin
31
- result = {}
32
- YARD::Registry.load! CoreDocs.yardoc_stdlib_file
33
- YARD::Registry.all.each do |co|
34
- next if co.file.nil?
35
- path = co.file.sub(/^(ext|lib)\//, '').sub(/\.(rb|c)$/, '')
36
- base = path.split('/').first
37
- result[base] ||= []
38
- result[base].push co
39
- end
40
- result
41
- end
42
- end
43
-
44
- # @return [Boolean]
45
- attr_writer :with_dependencies
46
-
47
- # @param required [Array<String>, Set<String>]
48
- # @param directory [String]
49
- # @param source_gems [Array<String>, Set<String>]
50
- # @param with_dependencies [Boolean]
51
- def initialize(required: [], directory: '', source_gems: [], with_dependencies: true)
52
- @with_dependencies = with_dependencies
53
- change required.to_set, directory, source_gems.to_set
54
- end
55
-
56
- # @return [Array<Solargraph::Pin::Base>]
57
- def pins
58
- @pins ||= []
59
- end
60
-
61
- def with_dependencies?
62
- @with_dependencies ||= true unless @with_dependencies == false
63
- @with_dependencies
64
- end
65
-
66
- # @param new_requires [Set<String>] Required paths to use for loading gems
67
- # @param new_directory [String] The workspace directory
68
- # @param new_source_gems [Set<String>] Gems under local development (i.e., part of the workspace)
69
- # @return [Boolean]
70
- def change new_requires, new_directory, new_source_gems
71
- return false if new_requires == base_required && new_directory == @directory && new_source_gems == @source_gems
72
- @gem_paths = {}
73
- base_required.replace new_requires
74
- required.replace new_requires
75
- # HACK: Hardcoded YAML handling
76
- required.add 'psych' if new_requires.include?('yaml')
77
- @source_gems = new_source_gems
78
- @directory = new_directory
79
- process_requires
80
- @rebindable_method_names = nil
81
- @pin_class_hash = nil
82
- @pin_select_cache = {}
83
- true
84
- end
85
-
86
- # @return [Set<String>]
87
- def rebindable_method_names
88
- @rebindable_method_names ||= pins_by_class(Pin::Method)
89
- .select { |pin| pin.comments && pin.comments.include?('@yieldself') }
90
- .map(&:name)
91
- .concat(['instance_eval', 'instance_exec', 'class_eval', 'class_exec', 'module_eval', 'module_exec', 'define_method'])
92
- .to_set
93
- end
94
-
95
- # @return [Array<String>]
96
- def yardocs
97
- @yardocs ||= []
98
- end
99
-
100
- # @return [Set<String>]
101
- def required
102
- @required ||= Set.new
103
- end
104
-
105
- # @return [Array<String>]
106
- def unresolved_requires
107
- @unresolved_requires ||= []
108
- end
109
-
110
- # @return [Array<String>]
111
- def missing_docs
112
- @missing_docs ||= []
113
- end
114
-
115
- # @param y [String]
116
- # @return [YARD::Registry]
117
- def load_yardoc y
118
- if y.is_a?(Array)
119
- YARD::Registry.load y, true
120
- else
121
- YARD::Registry.load! y
122
- end
123
- rescue StandardError => e
124
- Solargraph::Logging.logger.warn "Error loading yardoc '#{y}' #{e.class} #{e.message}"
125
- yardocs.delete y
126
- nil
127
- end
128
-
129
- # @return [Array<Solargraph::Pin::Base>]
130
- def core_pins
131
- # Using a class variable to reduce loads
132
- @@core_pins ||= load_core_pins
133
- end
134
-
135
- # @param path [String]
136
- # @return [Pin::Base]
137
- def path_pin path
138
- pins.select { |p| p.path == path }.first
139
- end
140
-
141
- # Get the location of a file referenced by a require path.
142
- #
143
- # @param path [String]
144
- # @return [Location]
145
- def require_reference path
146
- # @type [Gem::Specification]
147
- spec = spec_for_require(path)
148
- spec.full_require_paths.each do |rp|
149
- file = File.join(rp, "#{path}.rb")
150
- next unless File.file?(file)
151
- return Solargraph::Location.new(file, Solargraph::Range.from_to(0, 0, 0, 0))
152
- end
153
- nil
154
- rescue Gem::LoadError
155
- nil
156
- end
157
-
158
- def stdlib_pins
159
- @stdlib_pins ||= []
160
- end
161
-
162
- def base_required
163
- @base_required ||= Set.new
164
- end
165
-
166
- def directory
167
- @directory ||= ''
168
- end
169
-
170
- private
171
-
172
- # @return [YardMap::Cache]
173
- def cache
174
- @cache ||= YardMap::Cache.new
175
- end
176
-
177
- # @return [Hash]
178
- def pin_class_hash
179
- @pin_class_hash ||= pins.to_set.classify(&:class).transform_values(&:to_a)
180
- end
181
-
182
- # @return [Array<Pin::Base>]
183
- def pins_by_class klass
184
- @pin_select_cache[klass] ||= pin_class_hash.select { |key, _| key <= klass }.values.flatten
185
- end
186
-
187
- # @param ns [YARD::CodeObjects::NamespaceObject]
188
- # @return [Array<YARD::CodeObjects::Base>]
189
- def recurse_namespace_object ns
190
- result = []
191
- ns.children.each do |c|
192
- result.push c
193
- result.concat recurse_namespace_object(c) if c.respond_to?(:children)
194
- end
195
- result
196
- end
197
-
198
- # @return [void]
199
- def process_requires
200
- @gemset = process_gemsets
201
- required.merge @gemset.keys if required.include?('bundler/require')
202
- pins.replace core_pins
203
- unresolved_requires.clear
204
- missing_docs.clear
205
- stdlib_pins.clear
206
- environ = Convention.for_global(self)
207
- done = []
208
- already_errored = []
209
- (required + environ.requires).each do |r|
210
- next if r.nil? || r.empty? || done.include?(r)
211
- done.push r
212
- cached = cache.get_path_pins(r)
213
- unless cached.nil?
214
- pins.concat cached
215
- next
216
- end
217
- result = []
218
- begin
219
- spec = spec_for_require(r)
220
- if @source_gems.include?(spec.name)
221
- next
222
- end
223
- next if @gem_paths.key?(spec.name)
224
- yd = yardoc_file_for_spec(spec)
225
- # YARD detects gems for certain libraries that do not have a yardoc
226
- # but exist in the stdlib. `fileutils` is an example. Treat those
227
- # cases as errors and check the stdlib yardoc.
228
- if yd.nil?
229
- process_error(r, result, already_errored, nil)
230
- next
231
- end
232
- @gem_paths[spec.name] = spec.full_gem_path
233
- unless yardocs.include?(yd)
234
- yardocs.unshift yd
235
- result.concat process_yardoc yd, spec
236
- result.concat add_gem_dependencies(spec) if with_dependencies?
237
- end
238
- rescue Gem::LoadError, NoYardocError
239
- process_error(r, result, already_errored)
240
- end
241
- result.delete_if(&:nil?)
242
- unless result.empty?
243
- cache.set_path_pins r, result
244
- pins.concat result
245
- end
246
- end
247
- if required.include?('yaml') && required.include?('psych')
248
- # HACK: Hardcoded YAML handling
249
- # @todo Why can't this be handled with an override or a virtual pin?
250
- pin = path_pin('YAML')
251
- pin.instance_variable_set(:@return_type, ComplexType.parse('Module<Psych>')) unless pin.nil?
252
- end
253
- pins.concat environ.pins
254
- end
255
-
256
- def process_error(req, result, already_errored, yd = 1)
257
- base = req.split('/').first
258
- return if already_errored.include?(base)
259
- already_errored.push base
260
- stdtmp = load_stdlib_pins(base)
261
- if yd.nil?
262
- missing_docs.push req
263
- elsif stdtmp.empty?
264
- unresolved_requires.push req
265
- else
266
- stdlib_pins.concat stdtmp
267
- result.concat stdtmp
268
- end
269
- end
270
-
271
- def process_gemsets
272
- return {} if directory.empty? || !File.file?(File.join(directory, 'Gemfile'))
273
- require_from_bundle(directory)
274
- end
275
-
276
- # @param spec [Gem::Specification]
277
- # @return [void]
278
- def add_gem_dependencies spec
279
- result = []
280
- (spec.dependencies - spec.development_dependencies).each do |dep|
281
- begin
282
- next if @source_gems.include?(dep.name) || @gem_paths.key?(dep.name)
283
- depspec = Gem::Specification.find_by_name(dep.name)
284
- next if depspec.nil?
285
- @gem_paths[depspec.name] = depspec.full_gem_path
286
- gy = yardoc_file_for_spec(depspec)
287
- if gy.nil?
288
- missing_docs.push dep.name
289
- else
290
- next if yardocs.include?(gy)
291
- yardocs.unshift gy
292
- result.concat process_yardoc gy, depspec
293
- result.concat add_gem_dependencies(depspec)
294
- end
295
- rescue Gem::LoadError
296
- # This error probably indicates a bug in an installed gem
297
- Solargraph::Logging.logger.warn "Failed to resolve #{dep.name} gem dependency for #{spec.name}"
298
- end
299
- end
300
- result
301
- end
302
-
303
- # @param y [String, nil]
304
- # @param spec [Gem::Specification, nil]
305
- # @return [Array<Pin::Base>]
306
- def process_yardoc y, spec = nil
307
- return [] if y.nil?
308
- if spec
309
- ser = File.join(CoreDocs.cache_dir, 'gems', "#{spec.name}-#{spec.version}.ser")
310
- if File.file?(ser)
311
- Solargraph.logger.info "Loading #{spec.name} #{spec.version} from cache"
312
- file = File.open(ser, 'rb')
313
- dump = file.read
314
- file.close
315
- begin
316
- result = Marshal.load(dump)
317
- return result unless result.nil? || result.empty?
318
- Solargraph.logger.warn "Empty cache for #{spec.name} #{spec.version}. Reloading"
319
- File.unlink ser
320
- rescue StandardError => e
321
- Solargraph.logger.warn "Error loading pin cache: [#{e.class}] #{e.message}"
322
- File.unlink ser
323
- end
324
- end
325
- end
326
- size = Dir.glob(File.join(y, '**', '*'))
327
- .map{ |f| File.size(f) }
328
- .inject(:+)
329
- if !size.nil? && size > 20_000_000
330
- Solargraph::Logging.logger.warn "Yardoc at #{y} is too large to process (#{size} bytes)"
331
- return []
332
- end
333
- Solargraph.logger.info "Loading #{spec.name} #{spec.version} from #{y}"
334
- load_yardoc y
335
- result = Mapper.new(YARD::Registry.all, spec).map
336
- raise NoYardocError, "Yardoc at #{y} is empty" if result.empty?
337
- if spec
338
- ser = File.join(CoreDocs.cache_dir, 'gems', "#{spec.name}-#{spec.version}.ser")
339
- file = File.open(ser, 'wb')
340
- file.write Marshal.dump(result)
341
- file.close
342
- end
343
- result
344
- end
345
-
346
- # @param spec [Gem::Specification]
347
- # @return [String]
348
- def yardoc_file_for_spec spec
349
- cache_dir = File.join(Solargraph::YardMap::CoreDocs.cache_dir, 'gems', "#{spec.name}-#{spec.version}", 'yardoc')
350
- if File.exist?(cache_dir)
351
- Solargraph.logger.info "Using cached documentation for #{spec.name} at #{cache_dir}"
352
- cache_dir
353
- else
354
- YARD::Registry.yardoc_file_for_gem(spec.name, "= #{spec.version}")
355
- end
356
- end
357
-
358
- # @param path [String]
359
- # @return [Gem::Specification]
360
- def spec_for_require path
361
- name = path.split('/').first
362
- spec = Gem::Specification.find_by_name(name, @gemset[name])
363
-
364
- # Avoid loading the spec again if it's going to be skipped anyway
365
- return spec if @source_gems.include?(spec.name)
366
- # Avoid loading the spec again if it's already the correct version
367
- if @gemset[spec.name] && @gemset[spec.name] != spec.version
368
- begin
369
- return Gem::Specification.find_by_name(spec.name, "= #{@gemset[spec.name]}")
370
- rescue Gem::LoadError
371
- Solargraph.logger.warn "Unable to load #{spec.name} #{@gemset[spec.name]} specified by workspace, using #{spec.version} instead"
372
- end
373
- end
374
- spec
375
- end
376
-
377
- def load_core_pins
378
- yd = CoreDocs.yardoc_file
379
- ser = File.join(File.dirname(yd), 'core.ser')
380
- result = if File.file?(ser)
381
- file = File.open(ser, 'rb')
382
- dump = file.read
383
- file.close
384
- begin
385
- Marshal.load(dump)
386
- rescue StandardError => e
387
- Solargraph.logger.warn "Error loading core pin cache: [#{e.class}] #{e.message}"
388
- File.unlink ser
389
- read_core_and_save_cache(yd, ser)
390
- end
391
- else
392
- read_core_and_save_cache(yd, ser)
393
- end
394
- ApiMap::Store.new(result + CoreFills::ALL).pins.reject { |pin| pin.is_a?(Pin::Reference::Override) }
395
- end
396
-
397
- def read_core_and_save_cache yd, ser
398
- result = []
399
- load_yardoc yd
400
- result.concat Mapper.new(YARD::Registry.all).map
401
- # HACK: Assume core methods with a single `args` parameter accept restarg
402
- result.select { |pin| pin.is_a?(Solargraph::Pin::Method )}.each do |pin|
403
- if pin.parameters.length == 1 && pin.parameters.first.name == 'args' && pin.parameters.first.decl == :arg
404
- # @todo Smelly instance variable access
405
- pin.parameters.first.instance_variable_set(:@decl, :restarg)
406
- end
407
- end
408
- # HACK: Set missing parameters on `==` methods, e.g., `Symbol#==`
409
- result.select { |pin| pin.name == '==' && pin.parameters.empty? }.each do |pin|
410
- pin.parameters.push Pin::Parameter.new(decl: :arg, name: 'obj2')
411
- end
412
- dump = Marshal.dump(result)
413
- file = File.open(ser, 'wb')
414
- file.write dump
415
- file.close
416
- result
417
- end
418
-
419
- def load_stdlib_pins base
420
- ser = File.join(File.dirname(CoreDocs.yardoc_stdlib_file), "#{base}.ser")
421
- result = if File.file?(ser)
422
- Solargraph.logger.info "Loading #{base} stdlib from cache"
423
- file = File.open(ser, 'rb')
424
- dump = file.read
425
- file.close
426
- begin
427
- Marshal.load(dump)
428
- rescue StandardError => e
429
- Solargraph.logger.warn "Error loading #{base} stdlib pin cache: [#{e.class}] #{e.message}"
430
- File.unlink ser
431
- read_stdlib_and_save_cache(base, ser)
432
- end
433
- else
434
- read_stdlib_and_save_cache(base, ser)
435
- end
436
- fills = StdlibFills.get(base)
437
- unless fills.empty?
438
- result = ApiMap::Store.new(result + fills).pins.reject { |pin| pin.is_a?(Pin::Reference::Override) }
439
- end
440
- result
441
- end
442
-
443
- def read_stdlib_and_save_cache base, ser
444
- result = []
445
- if stdlib_paths[base]
446
- Solargraph.logger.info "Loading #{base} stdlib from yardoc"
447
- result.concat Mapper.new(stdlib_paths[base]).map
448
- unless result.empty?
449
- dump = Marshal.dump(result)
450
- file = File.open(ser, 'wb')
451
- file.write dump
452
- file.close
453
- end
454
- end
455
- result
456
- end
457
- end
458
- end
459
-
460
- Solargraph::YardMap::CoreDocs.require_minimum
1
+ # frozen_string_literal: true
2
+
3
+ require 'yard'
4
+ require 'yard-solargraph'
5
+ require 'rubygems/package'
6
+ require 'set'
7
+
8
+ module Solargraph
9
+ # The YardMap provides access to YARD documentation for the Ruby core, the
10
+ # stdlib, and gems.
11
+ #
12
+ class YardMap
13
+ class NoYardocError < StandardError; end
14
+
15
+ autoload :Cache, 'solargraph/yard_map/cache'
16
+ autoload :CoreDocs, 'solargraph/yard_map/core_docs'
17
+ autoload :CoreGen, 'solargraph/yard_map/core_gen'
18
+ autoload :Mapper, 'solargraph/yard_map/mapper'
19
+ autoload :RdocToYard, 'solargraph/yard_map/rdoc_to_yard'
20
+ autoload :CoreFills, 'solargraph/yard_map/core_fills'
21
+ autoload :StdlibFills, 'solargraph/yard_map/stdlib_fills'
22
+ autoload :Helpers, 'solargraph/yard_map/helpers'
23
+ autoload :ToMethod, 'solargraph/yard_map/to_method'
24
+
25
+ include ApiMap::BundlerMethods
26
+
27
+ CoreDocs.require_minimum
28
+
29
+ def stdlib_paths
30
+ @@stdlib_paths ||= begin
31
+ result = {}
32
+ YARD::Registry.load! CoreDocs.yardoc_stdlib_file
33
+ YARD::Registry.all.each do |co|
34
+ next if co.file.nil?
35
+ path = co.file.sub(/^(ext|lib)\//, '').sub(/\.(rb|c)$/, '')
36
+ base = path.split('/').first
37
+ result[base] ||= []
38
+ result[base].push co
39
+ end
40
+ result
41
+ end
42
+ end
43
+
44
+ # @return [Boolean]
45
+ attr_writer :with_dependencies
46
+
47
+ # @param required [Array<String>, Set<String>]
48
+ # @param directory [String]
49
+ # @param source_gems [Array<String>, Set<String>]
50
+ # @param with_dependencies [Boolean]
51
+ def initialize(required: [], directory: '', source_gems: [], with_dependencies: true)
52
+ @with_dependencies = with_dependencies
53
+ change required.to_set, directory, source_gems.to_set
54
+ end
55
+
56
+ # @return [Array<Solargraph::Pin::Base>]
57
+ def pins
58
+ @pins ||= []
59
+ end
60
+
61
+ def with_dependencies?
62
+ @with_dependencies ||= true unless @with_dependencies == false
63
+ @with_dependencies
64
+ end
65
+
66
+ # @param new_requires [Set<String>] Required paths to use for loading gems
67
+ # @param new_directory [String] The workspace directory
68
+ # @param new_source_gems [Set<String>] Gems under local development (i.e., part of the workspace)
69
+ # @return [Boolean]
70
+ def change new_requires, new_directory, new_source_gems
71
+ return false if new_requires == base_required && new_directory == @directory && new_source_gems == @source_gems
72
+ @gem_paths = {}
73
+ base_required.replace new_requires
74
+ required.replace new_requires
75
+ # HACK: Hardcoded YAML handling
76
+ required.add 'psych' if new_requires.include?('yaml')
77
+ @source_gems = new_source_gems
78
+ @directory = new_directory
79
+ process_requires
80
+ @rebindable_method_names = nil
81
+ @pin_class_hash = nil
82
+ @pin_select_cache = {}
83
+ true
84
+ end
85
+
86
+ # @return [Set<String>]
87
+ def rebindable_method_names
88
+ @rebindable_method_names ||= pins_by_class(Pin::Method)
89
+ .select { |pin| pin.comments && pin.comments.include?('@yieldself') }
90
+ .map(&:name)
91
+ .concat(['instance_eval', 'instance_exec', 'class_eval', 'class_exec', 'module_eval', 'module_exec', 'define_method'])
92
+ .to_set
93
+ end
94
+
95
+ # @return [Array<String>]
96
+ def yardocs
97
+ @yardocs ||= []
98
+ end
99
+
100
+ # @return [Set<String>]
101
+ def required
102
+ @required ||= Set.new
103
+ end
104
+
105
+ # @return [Array<String>]
106
+ def unresolved_requires
107
+ @unresolved_requires ||= []
108
+ end
109
+
110
+ # @return [Array<String>]
111
+ def missing_docs
112
+ @missing_docs ||= []
113
+ end
114
+
115
+ # @param y [String]
116
+ # @return [YARD::Registry]
117
+ def load_yardoc y
118
+ if y.is_a?(Array)
119
+ YARD::Registry.load y, true
120
+ else
121
+ YARD::Registry.load! y
122
+ end
123
+ rescue StandardError => e
124
+ Solargraph::Logging.logger.warn "Error loading yardoc '#{y}' #{e.class} #{e.message}"
125
+ yardocs.delete y
126
+ nil
127
+ end
128
+
129
+ # @return [Array<Solargraph::Pin::Base>]
130
+ def core_pins
131
+ # Using a class variable to reduce loads
132
+ @@core_pins ||= load_core_pins
133
+ end
134
+
135
+ # @param path [String]
136
+ # @return [Pin::Base]
137
+ def path_pin path
138
+ pins.select { |p| p.path == path }.first
139
+ end
140
+
141
+ # Get the location of a file referenced by a require path.
142
+ #
143
+ # @param path [String]
144
+ # @return [Location]
145
+ def require_reference path
146
+ # @type [Gem::Specification]
147
+ spec = spec_for_require(path)
148
+ spec.full_require_paths.each do |rp|
149
+ file = File.join(rp, "#{path}.rb")
150
+ next unless File.file?(file)
151
+ return Solargraph::Location.new(file, Solargraph::Range.from_to(0, 0, 0, 0))
152
+ end
153
+ nil
154
+ rescue Gem::LoadError
155
+ nil
156
+ end
157
+
158
+ def stdlib_pins
159
+ @stdlib_pins ||= []
160
+ end
161
+
162
+ def base_required
163
+ @base_required ||= Set.new
164
+ end
165
+
166
+ def directory
167
+ @directory ||= ''
168
+ end
169
+
170
+ private
171
+
172
+ # @return [YardMap::Cache]
173
+ def cache
174
+ @cache ||= YardMap::Cache.new
175
+ end
176
+
177
+ # @return [Hash]
178
+ def pin_class_hash
179
+ @pin_class_hash ||= pins.to_set.classify(&:class).transform_values(&:to_a)
180
+ end
181
+
182
+ # @return [Array<Pin::Base>]
183
+ def pins_by_class klass
184
+ @pin_select_cache[klass] ||= pin_class_hash.select { |key, _| key <= klass }.values.flatten
185
+ end
186
+
187
+ # @param ns [YARD::CodeObjects::NamespaceObject]
188
+ # @return [Array<YARD::CodeObjects::Base>]
189
+ def recurse_namespace_object ns
190
+ result = []
191
+ ns.children.each do |c|
192
+ result.push c
193
+ result.concat recurse_namespace_object(c) if c.respond_to?(:children)
194
+ end
195
+ result
196
+ end
197
+
198
+ # @return [void]
199
+ def process_requires
200
+ @gemset = process_gemsets
201
+ required.merge @gemset.keys if required.include?('bundler/require')
202
+ pins.replace core_pins
203
+ unresolved_requires.clear
204
+ missing_docs.clear
205
+ stdlib_pins.clear
206
+ environ = Convention.for_global(self)
207
+ done = []
208
+ already_errored = []
209
+ (required + environ.requires).each do |r|
210
+ next if r.nil? || r.empty? || done.include?(r)
211
+ done.push r
212
+ cached = cache.get_path_pins(r)
213
+ unless cached.nil?
214
+ pins.concat cached
215
+ next
216
+ end
217
+ result = []
218
+ begin
219
+ spec = spec_for_require(r)
220
+ if @source_gems.include?(spec.name)
221
+ next
222
+ end
223
+ next if @gem_paths.key?(spec.name)
224
+ yd = yardoc_file_for_spec(spec)
225
+ # YARD detects gems for certain libraries that do not have a yardoc
226
+ # but exist in the stdlib. `fileutils` is an example. Treat those
227
+ # cases as errors and check the stdlib yardoc.
228
+ if yd.nil?
229
+ process_error(r, result, already_errored, nil)
230
+ next
231
+ end
232
+ @gem_paths[spec.name] = spec.full_gem_path
233
+ unless yardocs.include?(yd)
234
+ yardocs.unshift yd
235
+ result.concat process_yardoc yd, spec
236
+ result.concat add_gem_dependencies(spec) if with_dependencies?
237
+ end
238
+ rescue Gem::LoadError, NoYardocError
239
+ process_error(r, result, already_errored)
240
+ end
241
+ result.delete_if(&:nil?)
242
+ unless result.empty?
243
+ cache.set_path_pins r, result
244
+ pins.concat result
245
+ end
246
+ end
247
+ if required.include?('yaml') && required.include?('psych')
248
+ # HACK: Hardcoded YAML handling
249
+ # @todo Why can't this be handled with an override or a virtual pin?
250
+ pin = path_pin('YAML')
251
+ pin.instance_variable_set(:@return_type, ComplexType.parse('Module<Psych>')) unless pin.nil?
252
+ end
253
+ pins.concat environ.pins
254
+ end
255
+
256
+ def process_error(req, result, already_errored, yd = 1)
257
+ base = req.split('/').first
258
+ return if already_errored.include?(base)
259
+ already_errored.push base
260
+ stdtmp = load_stdlib_pins(base)
261
+ if yd.nil?
262
+ missing_docs.push req
263
+ elsif stdtmp.empty?
264
+ unresolved_requires.push req
265
+ else
266
+ stdlib_pins.concat stdtmp
267
+ result.concat stdtmp
268
+ end
269
+ end
270
+
271
+ def process_gemsets
272
+ return {} if directory.empty? || !File.file?(File.join(directory, 'Gemfile'))
273
+ require_from_bundle(directory)
274
+ end
275
+
276
+ # @param spec [Gem::Specification]
277
+ # @return [void]
278
+ def add_gem_dependencies spec
279
+ result = []
280
+ (spec.dependencies - spec.development_dependencies).each do |dep|
281
+ begin
282
+ next if @source_gems.include?(dep.name) || @gem_paths.key?(dep.name)
283
+ depspec = Gem::Specification.find_by_name(dep.name)
284
+ next if depspec.nil?
285
+ @gem_paths[depspec.name] = depspec.full_gem_path
286
+ gy = yardoc_file_for_spec(depspec)
287
+ if gy.nil?
288
+ missing_docs.push dep.name
289
+ else
290
+ next if yardocs.include?(gy)
291
+ yardocs.unshift gy
292
+ result.concat process_yardoc gy, depspec
293
+ result.concat add_gem_dependencies(depspec)
294
+ end
295
+ rescue Gem::LoadError
296
+ # This error probably indicates a bug in an installed gem
297
+ Solargraph::Logging.logger.warn "Failed to resolve #{dep.name} gem dependency for #{spec.name}"
298
+ end
299
+ end
300
+ result
301
+ end
302
+
303
+ # @param y [String, nil]
304
+ # @param spec [Gem::Specification, nil]
305
+ # @return [Array<Pin::Base>]
306
+ def process_yardoc y, spec = nil
307
+ return [] if y.nil?
308
+ if spec
309
+ ser = File.join(CoreDocs.cache_dir, 'gems', "#{spec.name}-#{spec.version}.ser")
310
+ if File.file?(ser)
311
+ Solargraph.logger.info "Loading #{spec.name} #{spec.version} from cache"
312
+ file = File.open(ser, 'rb')
313
+ dump = file.read
314
+ file.close
315
+ begin
316
+ result = Marshal.load(dump)
317
+ return result unless result.nil? || result.empty?
318
+ Solargraph.logger.warn "Empty cache for #{spec.name} #{spec.version}. Reloading"
319
+ File.unlink ser
320
+ rescue StandardError => e
321
+ Solargraph.logger.warn "Error loading pin cache: [#{e.class}] #{e.message}"
322
+ File.unlink ser
323
+ end
324
+ end
325
+ end
326
+ size = Dir.glob(File.join(y, '**', '*'))
327
+ .map{ |f| File.size(f) }
328
+ .inject(:+)
329
+ if !size.nil? && size > 20_000_000
330
+ Solargraph::Logging.logger.warn "Yardoc at #{y} is too large to process (#{size} bytes)"
331
+ return []
332
+ end
333
+ Solargraph.logger.info "Loading #{spec.name} #{spec.version} from #{y}"
334
+ load_yardoc y
335
+ result = Mapper.new(YARD::Registry.all, spec).map
336
+ raise NoYardocError, "Yardoc at #{y} is empty" if result.empty?
337
+ if spec
338
+ ser = File.join(CoreDocs.cache_dir, 'gems', "#{spec.name}-#{spec.version}.ser")
339
+ file = File.open(ser, 'wb')
340
+ file.write Marshal.dump(result)
341
+ file.close
342
+ end
343
+ result
344
+ end
345
+
346
+ # @param spec [Gem::Specification]
347
+ # @return [String]
348
+ def yardoc_file_for_spec spec
349
+ cache_dir = File.join(Solargraph::YardMap::CoreDocs.cache_dir, 'gems', "#{spec.name}-#{spec.version}", 'yardoc')
350
+ if File.exist?(cache_dir)
351
+ Solargraph.logger.info "Using cached documentation for #{spec.name} at #{cache_dir}"
352
+ cache_dir
353
+ else
354
+ YARD::Registry.yardoc_file_for_gem(spec.name, "= #{spec.version}")
355
+ end
356
+ end
357
+
358
+ # @param path [String]
359
+ # @return [Gem::Specification]
360
+ def spec_for_require path
361
+ name = path.split('/').first
362
+ spec = Gem::Specification.find_by_name(name, @gemset[name])
363
+
364
+ # Avoid loading the spec again if it's going to be skipped anyway
365
+ return spec if @source_gems.include?(spec.name)
366
+ # Avoid loading the spec again if it's already the correct version
367
+ if @gemset[spec.name] && @gemset[spec.name] != spec.version
368
+ begin
369
+ return Gem::Specification.find_by_name(spec.name, "= #{@gemset[spec.name]}")
370
+ rescue Gem::LoadError
371
+ Solargraph.logger.warn "Unable to load #{spec.name} #{@gemset[spec.name]} specified by workspace, using #{spec.version} instead"
372
+ end
373
+ end
374
+ spec
375
+ end
376
+
377
+ def load_core_pins
378
+ yd = CoreDocs.yardoc_file
379
+ ser = File.join(File.dirname(yd), 'core.ser')
380
+ result = if File.file?(ser)
381
+ file = File.open(ser, 'rb')
382
+ dump = file.read
383
+ file.close
384
+ begin
385
+ Marshal.load(dump)
386
+ rescue StandardError => e
387
+ Solargraph.logger.warn "Error loading core pin cache: [#{e.class}] #{e.message}"
388
+ File.unlink ser
389
+ read_core_and_save_cache(yd, ser)
390
+ end
391
+ else
392
+ read_core_and_save_cache(yd, ser)
393
+ end
394
+ ApiMap::Store.new(result + CoreFills::ALL).pins.reject { |pin| pin.is_a?(Pin::Reference::Override) }
395
+ end
396
+
397
+ def read_core_and_save_cache yd, ser
398
+ result = []
399
+ load_yardoc yd
400
+ result.concat Mapper.new(YARD::Registry.all).map
401
+ # HACK: Assume core methods with a single `args` parameter accept restarg
402
+ result.select { |pin| pin.is_a?(Solargraph::Pin::Method )}.each do |pin|
403
+ if pin.parameters.length == 1 && pin.parameters.first.name == 'args' && pin.parameters.first.decl == :arg
404
+ # @todo Smelly instance variable access
405
+ pin.parameters.first.instance_variable_set(:@decl, :restarg)
406
+ end
407
+ end
408
+ # HACK: Set missing parameters on `==` methods, e.g., `Symbol#==`
409
+ result.select { |pin| pin.name == '==' && pin.parameters.empty? }.each do |pin|
410
+ pin.parameters.push Pin::Parameter.new(decl: :arg, name: 'obj2')
411
+ end
412
+ dump = Marshal.dump(result)
413
+ file = File.open(ser, 'wb')
414
+ file.write dump
415
+ file.close
416
+ result
417
+ end
418
+
419
+ def load_stdlib_pins base
420
+ ser = File.join(File.dirname(CoreDocs.yardoc_stdlib_file), "#{base}.ser")
421
+ result = if File.file?(ser)
422
+ Solargraph.logger.info "Loading #{base} stdlib from cache"
423
+ file = File.open(ser, 'rb')
424
+ dump = file.read
425
+ file.close
426
+ begin
427
+ Marshal.load(dump)
428
+ rescue StandardError => e
429
+ Solargraph.logger.warn "Error loading #{base} stdlib pin cache: [#{e.class}] #{e.message}"
430
+ File.unlink ser
431
+ read_stdlib_and_save_cache(base, ser)
432
+ end
433
+ else
434
+ read_stdlib_and_save_cache(base, ser)
435
+ end
436
+ fills = StdlibFills.get(base)
437
+ unless fills.empty?
438
+ result = ApiMap::Store.new(result + fills).pins.reject { |pin| pin.is_a?(Pin::Reference::Override) }
439
+ end
440
+ result
441
+ end
442
+
443
+ def read_stdlib_and_save_cache base, ser
444
+ result = []
445
+ if stdlib_paths[base]
446
+ Solargraph.logger.info "Loading #{base} stdlib from yardoc"
447
+ result.concat Mapper.new(stdlib_paths[base]).map
448
+ unless result.empty?
449
+ dump = Marshal.dump(result)
450
+ file = File.open(ser, 'wb')
451
+ file.write dump
452
+ file.close
453
+ end
454
+ end
455
+ result
456
+ end
457
+ end
458
+ end
459
+
460
+ Solargraph::YardMap::CoreDocs.require_minimum