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