solargraph 0.44.2 → 0.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec.yml +41 -0
  3. data/.gitignore +9 -9
  4. data/.rspec +2 -2
  5. data/.travis.yml +19 -19
  6. data/CHANGELOG.md +1115 -1088
  7. data/Gemfile +0 -0
  8. data/LICENSE +0 -0
  9. data/README.md +128 -120
  10. data/Rakefile +0 -0
  11. data/SPONSORS.md +18 -15
  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 -681
  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 -21
  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 -37
  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 +54 -44
  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 -140
  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 -155
  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 -64
  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 -62
  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 +72 -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 -206
  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 -0
  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 -36
  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 +226 -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 +522 -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 +212 -212
  220. data/lib/solargraph/source_map.rb +180 -189
  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 -510
  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 -214
  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 -203
  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 -443
  243. data/lib/solargraph.rb +69 -69
  244. data/lib/yard-solargraph.rb +33 -33
  245. data/solargraph.gemspec +0 -0
  246. metadata +14 -12
@@ -1,443 +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
- # @param y [String]
111
- # @return [YARD::Registry]
112
- def load_yardoc y
113
- if y.is_a?(Array)
114
- YARD::Registry.load y, true
115
- else
116
- YARD::Registry.load! y
117
- end
118
- rescue StandardError => e
119
- Solargraph::Logging.logger.warn "Error loading yardoc '#{y}' #{e.class} #{e.message}"
120
- yardocs.delete y
121
- nil
122
- end
123
-
124
- # @return [Array<Solargraph::Pin::Base>]
125
- def core_pins
126
- # Using a class variable to reduce loads
127
- @@core_pins ||= load_core_pins
128
- end
129
-
130
- # @param path [String]
131
- # @return [Pin::Base]
132
- def path_pin path
133
- pins.select { |p| p.path == path }.first
134
- end
135
-
136
- # Get the location of a file referenced by a require path.
137
- #
138
- # @param path [String]
139
- # @return [Location]
140
- def require_reference path
141
- # @type [Gem::Specification]
142
- spec = spec_for_require(path)
143
- spec.full_require_paths.each do |rp|
144
- file = File.join(rp, "#{path}.rb")
145
- next unless File.file?(file)
146
- return Solargraph::Location.new(file, Solargraph::Range.from_to(0, 0, 0, 0))
147
- end
148
- nil
149
- rescue Gem::LoadError
150
- nil
151
- end
152
-
153
- def stdlib_pins
154
- @stdlib_pins ||= []
155
- end
156
-
157
- def base_required
158
- @base_required ||= Set.new
159
- end
160
-
161
- def directory
162
- @directory ||= ''
163
- end
164
-
165
- private
166
-
167
- # @return [YardMap::Cache]
168
- def cache
169
- @cache ||= YardMap::Cache.new
170
- end
171
-
172
- # @return [Hash]
173
- def pin_class_hash
174
- @pin_class_hash ||= pins.to_set.classify(&:class).transform_values(&:to_a)
175
- end
176
-
177
- # @return [Array<Pin::Base>]
178
- def pins_by_class klass
179
- @pin_select_cache[klass] ||= pin_class_hash.select { |key, _| key <= klass }.values.flatten
180
- end
181
-
182
- # @param ns [YARD::CodeObjects::NamespaceObject]
183
- # @return [Array<YARD::CodeObjects::Base>]
184
- def recurse_namespace_object ns
185
- result = []
186
- ns.children.each do |c|
187
- result.push c
188
- result.concat recurse_namespace_object(c) if c.respond_to?(:children)
189
- end
190
- result
191
- end
192
-
193
- # @return [void]
194
- def process_requires
195
- @gemset = process_gemsets
196
- required.merge @gemset.keys if required.include?('bundler/require')
197
- pins.replace core_pins
198
- unresolved_requires.clear
199
- stdlib_pins.clear
200
- environ = Convention.for_global(self)
201
- done = []
202
- from_std = []
203
- (required + environ.requires).each do |r|
204
- next if r.nil? || r.empty? || done.include?(r)
205
- done.push r
206
- cached = cache.get_path_pins(r)
207
- unless cached.nil?
208
- pins.concat cached
209
- next
210
- end
211
- result = []
212
- begin
213
- spec = spec_for_require(r)
214
- if @source_gems.include?(spec.name)
215
- next
216
- end
217
- next if @gem_paths.key?(spec.name)
218
- yd = yardoc_file_for_spec(spec)
219
- # YARD detects gems for certain libraries that do not have a yardoc
220
- # but exist in the stdlib. `fileutils` is an example. Treat those
221
- # cases as errors and check the stdlib yardoc.
222
- raise Gem::LoadError if yd.nil?
223
- @gem_paths[spec.name] = spec.full_gem_path
224
- unless yardocs.include?(yd)
225
- yardocs.unshift yd
226
- result.concat process_yardoc yd, spec
227
- result.concat add_gem_dependencies(spec) if with_dependencies?
228
- end
229
- rescue Gem::LoadError, NoYardocError => e
230
- base = r.split('/').first
231
- next if from_std.include?(base)
232
- from_std.push base
233
- stdtmp = load_stdlib_pins(base)
234
- if stdtmp.empty?
235
- unresolved_requires.push r
236
- else
237
- stdlib_pins.concat stdtmp
238
- result.concat stdtmp
239
- end
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_gemsets
257
- return {} if directory.empty? || !File.file?(File.join(directory, 'Gemfile'))
258
- require_from_bundle(directory)
259
- end
260
-
261
- # @param spec [Gem::Specification]
262
- # @return [void]
263
- def add_gem_dependencies spec
264
- result = []
265
- (spec.dependencies - spec.development_dependencies).each do |dep|
266
- begin
267
- next if @source_gems.include?(dep.name) || @gem_paths.key?(dep.name)
268
- depspec = Gem::Specification.find_by_name(dep.name)
269
- next if depspec.nil?
270
- @gem_paths[depspec.name] = depspec.full_gem_path
271
- gy = yardoc_file_for_spec(depspec)
272
- if gy.nil?
273
- unresolved_requires.push dep.name
274
- else
275
- next if yardocs.include?(gy)
276
- yardocs.unshift gy
277
- result.concat process_yardoc gy, depspec
278
- result.concat add_gem_dependencies(depspec)
279
- end
280
- rescue Gem::LoadError
281
- # This error probably indicates a bug in an installed gem
282
- Solargraph::Logging.logger.warn "Failed to resolve #{dep.name} gem dependency for #{spec.name}"
283
- end
284
- end
285
- result
286
- end
287
-
288
- # @param y [String, nil]
289
- # @param spec [Gem::Specification, nil]
290
- # @return [Array<Pin::Base>]
291
- def process_yardoc y, spec = nil
292
- return [] if y.nil?
293
- if spec
294
- ser = File.join(CoreDocs.cache_dir, 'gems', "#{spec.name}-#{spec.version}.ser")
295
- if File.file?(ser)
296
- Solargraph.logger.info "Loading #{spec.name} #{spec.version} from cache"
297
- file = File.open(ser, 'rb')
298
- dump = file.read
299
- file.close
300
- begin
301
- result = Marshal.load(dump)
302
- return result unless result.nil? || result.empty?
303
- Solargraph.logger.warn "Empty cache for #{spec.name} #{spec.version}. Reloading"
304
- File.unlink ser
305
- rescue StandardError => e
306
- Solargraph.logger.warn "Error loading pin cache: [#{e.class}] #{e.message}"
307
- File.unlink ser
308
- end
309
- end
310
- end
311
- size = Dir.glob(File.join(y, '**', '*'))
312
- .map{ |f| File.size(f) }
313
- .inject(:+)
314
- if !size.nil? && size > 20_000_000
315
- Solargraph::Logging.logger.warn "Yardoc at #{y} is too large to process (#{size} bytes)"
316
- return []
317
- end
318
- Solargraph.logger.info "Loading #{spec.name} #{spec.version} from #{y}"
319
- load_yardoc y
320
- result = Mapper.new(YARD::Registry.all, spec).map
321
- raise NoYardocError, "Yardoc at #{y} is empty" if result.empty?
322
- if spec
323
- ser = File.join(CoreDocs.cache_dir, 'gems', "#{spec.name}-#{spec.version}.ser")
324
- file = File.open(ser, 'wb')
325
- file.write Marshal.dump(result)
326
- file.close
327
- end
328
- result
329
- end
330
-
331
- # @param spec [Gem::Specification]
332
- # @return [String]
333
- def yardoc_file_for_spec spec
334
- cache_dir = File.join(Solargraph::YardMap::CoreDocs.cache_dir, 'gems', "#{spec.name}-#{spec.version}", 'yardoc')
335
- if File.exist?(cache_dir)
336
- Solargraph.logger.info "Using cached documentation for #{spec.name} at #{cache_dir}"
337
- cache_dir
338
- else
339
- YARD::Registry.yardoc_file_for_gem(spec.name, "= #{spec.version}")
340
- end
341
- end
342
-
343
- # @param path [String]
344
- # @return [Gem::Specification]
345
- def spec_for_require path
346
- spec = Gem::Specification.find_by_path(path) || Gem::Specification.find_by_name(path.split('/').first)
347
- # Avoid loading the spec again if it's going to be skipped anyway
348
- return spec if @source_gems.include?(spec.name)
349
- # Avoid loading the spec again if it's already the correct version
350
- if @gemset[spec.name] && @gemset[spec.name] != spec.version
351
- begin
352
- return Gem::Specification.find_by_name(spec.name, "= #{@gemset[spec.name]}")
353
- rescue Gem::LoadError
354
- Solargraph.logger.warn "Unable to load #{spec.name} #{@gemset[spec.name]} specified by workspace, using #{spec.version} instead"
355
- end
356
- end
357
- spec
358
- end
359
-
360
- def load_core_pins
361
- yd = CoreDocs.yardoc_file
362
- ser = File.join(File.dirname(yd), 'core.ser')
363
- result = if File.file?(ser)
364
- file = File.open(ser, 'rb')
365
- dump = file.read
366
- file.close
367
- begin
368
- Marshal.load(dump)
369
- rescue StandardError => e
370
- Solargraph.logger.warn "Error loading core pin cache: [#{e.class}] #{e.message}"
371
- File.unlink ser
372
- read_core_and_save_cache(yd, ser)
373
- end
374
- else
375
- read_core_and_save_cache(yd, ser)
376
- end
377
- ApiMap::Store.new(result + CoreFills::ALL).pins.reject { |pin| pin.is_a?(Pin::Reference::Override) }
378
- end
379
-
380
- def read_core_and_save_cache yd, ser
381
- result = []
382
- load_yardoc yd
383
- result.concat Mapper.new(YARD::Registry.all).map
384
- # HACK: Assume core methods with a single `args` parameter accept restarg
385
- result.select { |pin| pin.is_a?(Solargraph::Pin::Method )}.each do |pin|
386
- if pin.parameters.length == 1 && pin.parameters.first.name == 'args' && pin.parameters.first.decl == :arg
387
- # @todo Smelly instance variable access
388
- pin.parameters.first.instance_variable_set(:@decl, :restarg)
389
- end
390
- end
391
- # HACK: Set missing parameters on `==` methods, e.g., `Symbol#==`
392
- result.select { |pin| pin.name == '==' && pin.parameters.empty? }.each do |pin|
393
- pin.parameters.push Pin::Parameter.new(decl: :arg, name: 'obj2')
394
- end
395
- dump = Marshal.dump(result)
396
- file = File.open(ser, 'wb')
397
- file.write dump
398
- file.close
399
- result
400
- end
401
-
402
- def load_stdlib_pins base
403
- ser = File.join(File.dirname(CoreDocs.yardoc_stdlib_file), "#{base}.ser")
404
- result = if File.file?(ser)
405
- Solargraph.logger.info "Loading #{base} stdlib from cache"
406
- file = File.open(ser, 'rb')
407
- dump = file.read
408
- file.close
409
- begin
410
- Marshal.load(dump)
411
- rescue StandardError => e
412
- Solargraph.logger.warn "Error loading #{base} stdlib pin cache: [#{e.class}] #{e.message}"
413
- File.unlink ser
414
- read_stdlib_and_save_cache(base, ser)
415
- end
416
- else
417
- read_stdlib_and_save_cache(base, ser)
418
- end
419
- fills = StdlibFills.get(base)
420
- unless fills.empty?
421
- result = ApiMap::Store.new(result + fills).pins.reject { |pin| pin.is_a?(Pin::Reference::Override) }
422
- end
423
- result
424
- end
425
-
426
- def read_stdlib_and_save_cache base, ser
427
- result = []
428
- if stdlib_paths[base]
429
- Solargraph.logger.info "Loading #{base} stdlib from yardoc"
430
- result.concat Mapper.new(stdlib_paths[base]).map
431
- unless result.empty?
432
- dump = Marshal.dump(result)
433
- file = File.open(ser, 'wb')
434
- file.write dump
435
- file.close
436
- end
437
- end
438
- result
439
- end
440
- end
441
- end
442
-
443
- 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