cosmicgraph 0.49.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 (259) hide show
  1. checksums.yaml +7 -0
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/rspec.yml +41 -0
  4. data/.gitignore +9 -0
  5. data/.rspec +2 -0
  6. data/.yardopts +2 -0
  7. data/CHANGELOG.md +1150 -0
  8. data/Gemfile +7 -0
  9. data/LICENSE +21 -0
  10. data/README.md +136 -0
  11. data/Rakefile +25 -0
  12. data/SPONSORS.md +15 -0
  13. data/bin/solargraph +5 -0
  14. data/cosmicgraph.gemspec +44 -0
  15. data/lib/.rubocop.yml +22 -0
  16. data/lib/solargraph/api_map/bundler_methods.rb +22 -0
  17. data/lib/solargraph/api_map/cache.rb +70 -0
  18. data/lib/solargraph/api_map/source_to_yard.rb +81 -0
  19. data/lib/solargraph/api_map/store.rb +268 -0
  20. data/lib/solargraph/api_map.rb +704 -0
  21. data/lib/solargraph/bench.rb +27 -0
  22. data/lib/solargraph/cache.rb +51 -0
  23. data/lib/solargraph/complex_type/type_methods.rb +134 -0
  24. data/lib/solargraph/complex_type/unique_type.rb +132 -0
  25. data/lib/solargraph/complex_type.rb +254 -0
  26. data/lib/solargraph/convention/base.rb +33 -0
  27. data/lib/solargraph/convention/gemfile.rb +15 -0
  28. data/lib/solargraph/convention/gemspec.rb +22 -0
  29. data/lib/solargraph/convention/rakefile.rb +17 -0
  30. data/lib/solargraph/convention/rspec.rb +30 -0
  31. data/lib/solargraph/convention.rb +49 -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/base.rb +29 -0
  37. data/lib/solargraph/diagnostics/require_not_found.rb +53 -0
  38. data/lib/solargraph/diagnostics/rubocop.rb +112 -0
  39. data/lib/solargraph/diagnostics/rubocop_helpers.rb +65 -0
  40. data/lib/solargraph/diagnostics/severities.rb +15 -0
  41. data/lib/solargraph/diagnostics/type_check.rb +54 -0
  42. data/lib/solargraph/diagnostics/update_errors.rb +41 -0
  43. data/lib/solargraph/diagnostics.rb +55 -0
  44. data/lib/solargraph/documentor.rb +76 -0
  45. data/lib/solargraph/environ.rb +45 -0
  46. data/lib/solargraph/language_server/completion_item_kinds.rb +35 -0
  47. data/lib/solargraph/language_server/error_codes.rb +20 -0
  48. data/lib/solargraph/language_server/host/cataloger.rb +56 -0
  49. data/lib/solargraph/language_server/host/diagnoser.rb +89 -0
  50. data/lib/solargraph/language_server/host/dispatch.rb +111 -0
  51. data/lib/solargraph/language_server/host/message_worker.rb +59 -0
  52. data/lib/solargraph/language_server/host/sources.rb +156 -0
  53. data/lib/solargraph/language_server/host.rb +869 -0
  54. data/lib/solargraph/language_server/message/base.rb +89 -0
  55. data/lib/solargraph/language_server/message/cancel_request.rb +13 -0
  56. data/lib/solargraph/language_server/message/client/register_capability.rb +15 -0
  57. data/lib/solargraph/language_server/message/client.rb +11 -0
  58. data/lib/solargraph/language_server/message/completion_item/resolve.rb +58 -0
  59. data/lib/solargraph/language_server/message/completion_item.rb +11 -0
  60. data/lib/solargraph/language_server/message/exit_notification.rb +13 -0
  61. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +100 -0
  62. data/lib/solargraph/language_server/message/extended/document.rb +20 -0
  63. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -0
  64. data/lib/solargraph/language_server/message/extended/download_core.rb +19 -0
  65. data/lib/solargraph/language_server/message/extended/environment.rb +25 -0
  66. data/lib/solargraph/language_server/message/extended/search.rb +20 -0
  67. data/lib/solargraph/language_server/message/extended.rb +21 -0
  68. data/lib/solargraph/language_server/message/initialize.rb +164 -0
  69. data/lib/solargraph/language_server/message/initialized.rb +27 -0
  70. data/lib/solargraph/language_server/message/method_not_found.rb +16 -0
  71. data/lib/solargraph/language_server/message/method_not_implemented.rb +14 -0
  72. data/lib/solargraph/language_server/message/shutdown.rb +13 -0
  73. data/lib/solargraph/language_server/message/text_document/base.rb +19 -0
  74. data/lib/solargraph/language_server/message/text_document/code_action.rb +17 -0
  75. data/lib/solargraph/language_server/message/text_document/completion.rb +59 -0
  76. data/lib/solargraph/language_server/message/text_document/definition.rb +38 -0
  77. data/lib/solargraph/language_server/message/text_document/did_change.rb +15 -0
  78. data/lib/solargraph/language_server/message/text_document/did_close.rb +15 -0
  79. data/lib/solargraph/language_server/message/text_document/did_open.rb +15 -0
  80. data/lib/solargraph/language_server/message/text_document/did_save.rb +17 -0
  81. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +16 -0
  82. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +23 -0
  83. data/lib/solargraph/language_server/message/text_document/folding_range.rb +26 -0
  84. data/lib/solargraph/language_server/message/text_document/formatting.rb +126 -0
  85. data/lib/solargraph/language_server/message/text_document/hover.rb +56 -0
  86. data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +34 -0
  87. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -0
  88. data/lib/solargraph/language_server/message/text_document/references.rb +16 -0
  89. data/lib/solargraph/language_server/message/text_document/rename.rb +19 -0
  90. data/lib/solargraph/language_server/message/text_document/signature_help.rb +24 -0
  91. data/lib/solargraph/language_server/message/text_document.rb +28 -0
  92. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +30 -0
  93. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +40 -0
  94. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -0
  95. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -0
  96. data/lib/solargraph/language_server/message/workspace.rb +14 -0
  97. data/lib/solargraph/language_server/message.rb +93 -0
  98. data/lib/solargraph/language_server/message_types.rb +14 -0
  99. data/lib/solargraph/language_server/request.rb +24 -0
  100. data/lib/solargraph/language_server/symbol_kinds.rb +36 -0
  101. data/lib/solargraph/language_server/transport/adapter.rb +53 -0
  102. data/lib/solargraph/language_server/transport/data_reader.rb +72 -0
  103. data/lib/solargraph/language_server/transport.rb +13 -0
  104. data/lib/solargraph/language_server/uri_helpers.rb +49 -0
  105. data/lib/solargraph/language_server.rb +19 -0
  106. data/lib/solargraph/library.rb +547 -0
  107. data/lib/solargraph/location.rb +37 -0
  108. data/lib/solargraph/logging.rb +27 -0
  109. data/lib/solargraph/page.rb +83 -0
  110. data/lib/solargraph/parser/comment_ripper.rb +52 -0
  111. data/lib/solargraph/parser/legacy/class_methods.rb +135 -0
  112. data/lib/solargraph/parser/legacy/flawed_builder.rb +16 -0
  113. data/lib/solargraph/parser/legacy/node_chainer.rb +148 -0
  114. data/lib/solargraph/parser/legacy/node_methods.rb +325 -0
  115. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +23 -0
  116. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +35 -0
  117. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +15 -0
  118. data/lib/solargraph/parser/legacy/node_processors/block_node.rb +42 -0
  119. data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +35 -0
  120. data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +23 -0
  121. data/lib/solargraph/parser/legacy/node_processors/def_node.rb +63 -0
  122. data/lib/solargraph/parser/legacy/node_processors/defs_node.rb +36 -0
  123. data/lib/solargraph/parser/legacy/node_processors/gvasgn_node.rb +23 -0
  124. data/lib/solargraph/parser/legacy/node_processors/ivasgn_node.rb +38 -0
  125. data/lib/solargraph/parser/legacy/node_processors/lvasgn_node.rb +28 -0
  126. data/lib/solargraph/parser/legacy/node_processors/namespace_node.rb +39 -0
  127. data/lib/solargraph/parser/legacy/node_processors/orasgn_node.rb +16 -0
  128. data/lib/solargraph/parser/legacy/node_processors/resbody_node.rb +36 -0
  129. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +42 -0
  130. data/lib/solargraph/parser/legacy/node_processors/send_node.rb +257 -0
  131. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +18 -0
  132. data/lib/solargraph/parser/legacy/node_processors.rb +54 -0
  133. data/lib/solargraph/parser/legacy.rb +12 -0
  134. data/lib/solargraph/parser/node_methods.rb +43 -0
  135. data/lib/solargraph/parser/node_processor/base.rb +77 -0
  136. data/lib/solargraph/parser/node_processor.rb +43 -0
  137. data/lib/solargraph/parser/region.rb +66 -0
  138. data/lib/solargraph/parser/rubyvm/class_methods.rb +149 -0
  139. data/lib/solargraph/parser/rubyvm/node_chainer.rb +160 -0
  140. data/lib/solargraph/parser/rubyvm/node_methods.rb +315 -0
  141. data/lib/solargraph/parser/rubyvm/node_processors/alias_node.rb +23 -0
  142. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +85 -0
  143. data/lib/solargraph/parser/rubyvm/node_processors/begin_node.rb +15 -0
  144. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +42 -0
  145. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +33 -0
  146. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +23 -0
  147. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +75 -0
  148. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +68 -0
  149. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +23 -0
  150. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +38 -0
  151. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +39 -0
  152. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +20 -0
  153. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +27 -0
  154. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +39 -0
  155. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +26 -0
  156. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +15 -0
  157. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +45 -0
  158. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +32 -0
  159. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +15 -0
  160. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +279 -0
  161. data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +18 -0
  162. data/lib/solargraph/parser/rubyvm/node_processors.rb +63 -0
  163. data/lib/solargraph/parser/rubyvm/node_wrapper.rb +47 -0
  164. data/lib/solargraph/parser/rubyvm.rb +40 -0
  165. data/lib/solargraph/parser/snippet.rb +13 -0
  166. data/lib/solargraph/parser.rb +26 -0
  167. data/lib/solargraph/pin/base.rb +299 -0
  168. data/lib/solargraph/pin/base_variable.rb +84 -0
  169. data/lib/solargraph/pin/block.rb +73 -0
  170. data/lib/solargraph/pin/class_variable.rb +8 -0
  171. data/lib/solargraph/pin/closure.rb +37 -0
  172. data/lib/solargraph/pin/common.rb +70 -0
  173. data/lib/solargraph/pin/constant.rb +43 -0
  174. data/lib/solargraph/pin/conversions.rb +92 -0
  175. data/lib/solargraph/pin/documenting.rb +105 -0
  176. data/lib/solargraph/pin/duck_method.rb +16 -0
  177. data/lib/solargraph/pin/global_variable.rb +8 -0
  178. data/lib/solargraph/pin/instance_variable.rb +30 -0
  179. data/lib/solargraph/pin/keyword.rb +15 -0
  180. data/lib/solargraph/pin/keyword_param.rb +8 -0
  181. data/lib/solargraph/pin/local_variable.rb +55 -0
  182. data/lib/solargraph/pin/method.rb +335 -0
  183. data/lib/solargraph/pin/method_alias.rb +31 -0
  184. data/lib/solargraph/pin/namespace.rb +94 -0
  185. data/lib/solargraph/pin/parameter.rb +206 -0
  186. data/lib/solargraph/pin/proxy_type.rb +29 -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/reference.rb +14 -0
  194. data/lib/solargraph/pin/search.rb +56 -0
  195. data/lib/solargraph/pin/signature.rb +23 -0
  196. data/lib/solargraph/pin/singleton.rb +11 -0
  197. data/lib/solargraph/pin/symbol.rb +47 -0
  198. data/lib/solargraph/pin.rb +38 -0
  199. data/lib/solargraph/position.rb +100 -0
  200. data/lib/solargraph/range.rb +95 -0
  201. data/lib/solargraph/rbs_map/conversions.rb +394 -0
  202. data/lib/solargraph/rbs_map/core_fills.rb +61 -0
  203. data/lib/solargraph/rbs_map/core_map.rb +38 -0
  204. data/lib/solargraph/rbs_map/core_signs.rb +33 -0
  205. data/lib/solargraph/rbs_map/stdlib_map.rb +36 -0
  206. data/lib/solargraph/rbs_map.rb +73 -0
  207. data/lib/solargraph/server_methods.rb +16 -0
  208. data/lib/solargraph/shell.rb +234 -0
  209. data/lib/solargraph/source/chain/block_variable.rb +13 -0
  210. data/lib/solargraph/source/chain/call.rb +215 -0
  211. data/lib/solargraph/source/chain/class_variable.rb +13 -0
  212. data/lib/solargraph/source/chain/constant.rb +75 -0
  213. data/lib/solargraph/source/chain/global_variable.rb +13 -0
  214. data/lib/solargraph/source/chain/hash.rb +28 -0
  215. data/lib/solargraph/source/chain/head.rb +19 -0
  216. data/lib/solargraph/source/chain/instance_variable.rb +13 -0
  217. data/lib/solargraph/source/chain/link.rb +71 -0
  218. data/lib/solargraph/source/chain/literal.rb +23 -0
  219. data/lib/solargraph/source/chain/or.rb +23 -0
  220. data/lib/solargraph/source/chain/q_call.rb +11 -0
  221. data/lib/solargraph/source/chain/variable.rb +13 -0
  222. data/lib/solargraph/source/chain/z_super.rb +30 -0
  223. data/lib/solargraph/source/chain.rb +179 -0
  224. data/lib/solargraph/source/change.rb +79 -0
  225. data/lib/solargraph/source/cursor.rb +164 -0
  226. data/lib/solargraph/source/encoding_fixes.rb +23 -0
  227. data/lib/solargraph/source/source_chainer.rb +191 -0
  228. data/lib/solargraph/source/updater.rb +54 -0
  229. data/lib/solargraph/source.rb +522 -0
  230. data/lib/solargraph/source_map/clip.rb +229 -0
  231. data/lib/solargraph/source_map/completion.rb +23 -0
  232. data/lib/solargraph/source_map/mapper.rb +241 -0
  233. data/lib/solargraph/source_map.rb +180 -0
  234. data/lib/solargraph/type_checker/checks.rb +112 -0
  235. data/lib/solargraph/type_checker/param_def.rb +35 -0
  236. data/lib/solargraph/type_checker/problem.rb +32 -0
  237. data/lib/solargraph/type_checker/rules.rb +57 -0
  238. data/lib/solargraph/type_checker.rb +549 -0
  239. data/lib/solargraph/version.rb +5 -0
  240. data/lib/solargraph/views/_method.erb +62 -0
  241. data/lib/solargraph/views/_name_type_tag.erb +10 -0
  242. data/lib/solargraph/views/_namespace.erb +24 -0
  243. data/lib/solargraph/views/document.erb +23 -0
  244. data/lib/solargraph/views/environment.erb +58 -0
  245. data/lib/solargraph/views/layout.erb +44 -0
  246. data/lib/solargraph/views/search.erb +11 -0
  247. data/lib/solargraph/workspace/config.rb +231 -0
  248. data/lib/solargraph/workspace.rb +212 -0
  249. data/lib/solargraph/yard_map/cache.rb +19 -0
  250. data/lib/solargraph/yard_map/helpers.rb +16 -0
  251. data/lib/solargraph/yard_map/mapper/to_constant.rb +25 -0
  252. data/lib/solargraph/yard_map/mapper/to_method.rb +81 -0
  253. data/lib/solargraph/yard_map/mapper/to_namespace.rb +27 -0
  254. data/lib/solargraph/yard_map/mapper.rb +77 -0
  255. data/lib/solargraph/yard_map/to_method.rb +79 -0
  256. data/lib/solargraph/yard_map.rb +301 -0
  257. data/lib/solargraph.rb +69 -0
  258. data/lib/yard-solargraph.rb +33 -0
  259. metadata +587 -0
@@ -0,0 +1,704 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubygems'
4
+ require 'set'
5
+ require 'pathname'
6
+ require 'yard'
7
+ require 'yard-solargraph'
8
+
9
+ module Solargraph
10
+ # An aggregate provider for information about workspaces, sources, gems, and
11
+ # the Ruby core.
12
+ #
13
+ class ApiMap
14
+ autoload :Cache, 'solargraph/api_map/cache'
15
+ autoload :SourceToYard, 'solargraph/api_map/source_to_yard'
16
+ autoload :Store, 'solargraph/api_map/store'
17
+ autoload :BundlerMethods, 'solargraph/api_map/bundler_methods'
18
+
19
+ include SourceToYard
20
+
21
+ # @return [Array<String>]
22
+ attr_reader :unresolved_requires
23
+
24
+ @@core_map = RbsMap::CoreMap.new
25
+
26
+ # @return [Array<String>]
27
+ attr_reader :missing_docs
28
+
29
+ # @param pins [Array<Solargraph::Pin::Base>]
30
+ def initialize pins: []
31
+ @source_map_hash = {}
32
+ @cache = Cache.new
33
+ @method_alias_stack = []
34
+ index pins
35
+ end
36
+
37
+ # @param pins [Array<Pin::Base>]
38
+ # @return [self]
39
+ def index pins
40
+ # @todo This implementation is incomplete. It should probably create a
41
+ # Bench.
42
+ @source_map_hash = {}
43
+ implicit.clear
44
+ cache.clear
45
+ @store = Store.new(@@core_map.pins + pins)
46
+ self
47
+ end
48
+
49
+ # Map a single source.
50
+ #
51
+ # @param source [Source]
52
+ # @return [self]
53
+ def map source
54
+ map = Solargraph::SourceMap.map(source)
55
+ catalog Bench.new(source_maps: [map])
56
+ self
57
+ end
58
+
59
+ # Catalog a bench.
60
+ #
61
+ # @param bench [Bench]
62
+ def catalog bench
63
+ implicit.clear
64
+ @cache.clear
65
+ @source_map_hash = bench.source_maps.map { |s| [s.filename, s] }.to_h
66
+ pins = bench.source_maps.map(&:pins).flatten
67
+ external_requires = bench.external_requires
68
+ source_map_hash.each_value do |map|
69
+ implicit.merge map.environ
70
+ end
71
+ external_requires.merge implicit.requires
72
+ external_requires.merge bench.workspace.config.required
73
+ @rbs_maps = external_requires.map { |r| load_rbs_map(r) }
74
+ unresolved_requires = @rbs_maps.reject(&:resolved?).map(&:library)
75
+ yard_map.change(unresolved_requires, bench.workspace.directory, bench.workspace.source_gems)
76
+ @store = Store.new(@@core_map.pins + @rbs_maps.flat_map(&:pins) + yard_map.pins + implicit.pins + pins)
77
+ @unresolved_requires = yard_map.unresolved_requires
78
+ @missing_docs = yard_map.missing_docs
79
+ @rebindable_method_names = nil
80
+ store.block_pins.each { |blk| blk.rebind(self) }
81
+ self
82
+ end
83
+
84
+ def core_pins
85
+ @@core_map.pins
86
+ end
87
+
88
+ def yard_map
89
+ @yard_map ||= YardMap.new
90
+ end
91
+
92
+ # @param name [String]
93
+ # @return [YARD::Tags::MacroDirective, nil]
94
+ def named_macro name
95
+ store.named_macros[name]
96
+ end
97
+
98
+ def required
99
+ @required ||= Set.new
100
+ end
101
+
102
+ # @return [Environ]
103
+ def implicit
104
+ @implicit ||= Environ.new
105
+ end
106
+
107
+ # @param filename [String]
108
+ # @param position [Position, Array(Integer, Integer)]
109
+ # @return [Source::Cursor]
110
+ def cursor_at filename, position
111
+ position = Position.normalize(position)
112
+ raise FileNotFoundError, "File not found: #{filename}" unless source_map_hash.key?(filename)
113
+ source_map_hash[filename].cursor_at(position)
114
+ end
115
+
116
+ # Get a clip by filename and position.
117
+ #
118
+ # @param filename [String]
119
+ # @param position [Position, Array(Integer, Integer)]
120
+ # @return [SourceMap::Clip]
121
+ def clip_at filename, position
122
+ position = Position.normalize(position)
123
+ SourceMap::Clip.new(self, cursor_at(filename, position))
124
+ end
125
+
126
+ # Create an ApiMap with a workspace in the specified directory.
127
+ #
128
+ # @param directory [String]
129
+ # @return [ApiMap]
130
+ def self.load directory
131
+ api_map = new
132
+ workspace = Solargraph::Workspace.new(directory)
133
+ # api_map.catalog Bench.new(workspace: workspace)
134
+ library = Library.new(workspace)
135
+ library.map!
136
+ api_map.catalog library.bench
137
+ api_map
138
+ end
139
+
140
+ # @return [Array<Solargraph::Pin::Base>]
141
+ def pins
142
+ store.pins
143
+ end
144
+
145
+ def rebindable_method_names
146
+ @rebindable_method_names ||= begin
147
+ # result = yard_map.rebindable_method_names
148
+ result = ['instance_eval', 'instance_exec', 'class_eval', 'class_exec', 'module_eval', 'module_exec', 'define_method'].to_set
149
+ source_maps.each do |map|
150
+ result.merge map.rebindable_method_names
151
+ end
152
+ result
153
+ end
154
+ end
155
+
156
+ # An array of pins based on Ruby keywords (`if`, `end`, etc.).
157
+ #
158
+ # @return [Enumerable<Solargraph::Pin::Keyword>]
159
+ def keyword_pins
160
+ store.pins_by_class(Pin::Keyword)
161
+ end
162
+
163
+ # An array of namespace names defined in the ApiMap.
164
+ #
165
+ # @return [Set<String>]
166
+ def namespaces
167
+ store.namespaces
168
+ end
169
+
170
+ # True if the namespace exists.
171
+ #
172
+ # @param name [String] The namespace to match
173
+ # @param context [String] The context to search
174
+ # @return [Boolean]
175
+ def namespace_exists? name, context = ''
176
+ !qualify(name, context).nil?
177
+ end
178
+
179
+ # Get suggestions for constants in the specified namespace. The result
180
+ # may contain both constant and namespace pins.
181
+ #
182
+ # @param namespace [String] The namespace
183
+ # @param contexts [Array<String>] The contexts
184
+ # @return [Array<Solargraph::Pin::Base>]
185
+ def get_constants namespace, *contexts
186
+ namespace ||= ''
187
+ contexts.push '' if contexts.empty?
188
+ cached = cache.get_constants(namespace, contexts)
189
+ return cached.clone unless cached.nil?
190
+ skip = Set.new
191
+ result = []
192
+ contexts.each do |context|
193
+ fqns = qualify(namespace, context)
194
+ visibility = [:public]
195
+ visibility.push :private if fqns == context
196
+ result.concat inner_get_constants(fqns, visibility, skip)
197
+ end
198
+ cache.set_constants(namespace, contexts, result)
199
+ result
200
+ end
201
+
202
+ # Get a fully qualified namespace name. This method will start the search
203
+ # in the specified context until it finds a match for the name.
204
+ #
205
+ # @param namespace [String, nil] The namespace to match
206
+ # @param context [String] The context to search
207
+ # @return [String, nil]
208
+ def qualify namespace, context = ''
209
+ return namespace if ['self', nil].include?(namespace)
210
+ cached = cache.get_qualified_namespace(namespace, context)
211
+ return cached.clone unless cached.nil?
212
+ result = if namespace.start_with?('::')
213
+ inner_qualify(namespace[2..-1], '', Set.new)
214
+ else
215
+ inner_qualify(namespace, context, Set.new)
216
+ end
217
+ cache.set_qualified_namespace(namespace, context, result)
218
+ result
219
+ end
220
+
221
+ # Get an array of instance variable pins defined in specified namespace
222
+ # and scope.
223
+ #
224
+ # @param namespace [String] A fully qualified namespace
225
+ # @param scope [Symbol] :instance or :class
226
+ # @return [Array<Solargraph::Pin::InstanceVariable>]
227
+ def get_instance_variable_pins(namespace, scope = :instance)
228
+ result = []
229
+ used = [namespace]
230
+ result.concat store.get_instance_variables(namespace, scope)
231
+ sc = qualify_lower(store.get_superclass(namespace), namespace)
232
+ until sc.nil? || used.include?(sc)
233
+ used.push sc
234
+ result.concat store.get_instance_variables(sc, scope)
235
+ sc = qualify_lower(store.get_superclass(sc), sc)
236
+ end
237
+ result
238
+ end
239
+
240
+ # Get an array of class variable pins for a namespace.
241
+ #
242
+ # @param namespace [String] A fully qualified namespace
243
+ # @return [Array<Solargraph::Pin::ClassVariable>]
244
+ def get_class_variable_pins(namespace)
245
+ prefer_non_nil_variables(store.get_class_variables(namespace))
246
+ end
247
+
248
+ # @return [Array<Solargraph::Pin::Base>]
249
+ def get_symbols
250
+ store.get_symbols
251
+ end
252
+
253
+ # @return [Array<Solargraph::Pin::GlobalVariable>]
254
+ def get_global_variable_pins
255
+ store.pins_by_class(Pin::GlobalVariable)
256
+ end
257
+
258
+ # Get an array of methods available in a particular context.
259
+ #
260
+ # @param fqns [String] The fully qualified namespace to search for methods
261
+ # @param scope [Symbol] :class or :instance
262
+ # @param visibility [Array<Symbol>] :public, :protected, and/or :private
263
+ # @param deep [Boolean] True to include superclasses, mixins, etc.
264
+ # @return [Array<Solargraph::Pin::Method>]
265
+ def get_methods fqns, scope: :instance, visibility: [:public], deep: true
266
+ cached = cache.get_methods(fqns, scope, visibility, deep)
267
+ return cached.clone unless cached.nil?
268
+ result = []
269
+ skip = Set.new
270
+ if fqns == ''
271
+ # @todo Implement domains
272
+ implicit.domains.each do |domain|
273
+ type = ComplexType.try_parse(domain)
274
+ next if type.undefined?
275
+ result.concat inner_get_methods(type.name, type.scope, visibility, deep, skip)
276
+ end
277
+ result.concat inner_get_methods(fqns, :class, visibility, deep, skip)
278
+ result.concat inner_get_methods(fqns, :instance, visibility, deep, skip)
279
+ result.concat inner_get_methods('Kernel', :instance, visibility, deep, skip)
280
+ else
281
+ result.concat inner_get_methods(fqns, scope, visibility, deep, skip)
282
+ result.concat inner_get_methods('Kernel', :instance, [:public], deep, skip) if visibility.include?(:private)
283
+ end
284
+ resolved = resolve_method_aliases(result, visibility)
285
+ cache.set_methods(fqns, scope, visibility, deep, resolved)
286
+ resolved
287
+ end
288
+
289
+ # Get an array of method pins for a complex type.
290
+ #
291
+ # The type's namespace and the context should be fully qualified. If the
292
+ # context matches the namespace type or is a subclass of the type,
293
+ # protected methods are included in the results. If protected methods are
294
+ # included and internal is true, private methods are also included.
295
+ #
296
+ # @example
297
+ # api_map = Solargraph::ApiMap.new
298
+ # type = Solargraph::ComplexType.parse('String')
299
+ # api_map.get_complex_type_methods(type)
300
+ #
301
+ # @param complex_type [Solargraph::ComplexType] The complex type of the namespace
302
+ # @param context [String] The context from which the type is referenced
303
+ # @param internal [Boolean] True to include private methods
304
+ # @return [Array<Solargraph::Pin::Base>]
305
+ def get_complex_type_methods complex_type, context = '', internal = false
306
+ # This method does not qualify the complex type's namespace because
307
+ # it can cause conflicts between similar names, e.g., `Foo` vs.
308
+ # `Other::Foo`. It still takes a context argument to determine whether
309
+ # protected and private methods are visible.
310
+ return [] if complex_type.undefined? || complex_type.void?
311
+ result = Set.new
312
+ complex_type.each do |type|
313
+ if type.duck_type?
314
+ result.add Pin::DuckMethod.new(name: type.to_s[1..-1])
315
+ result.merge get_methods('Object')
316
+ else
317
+ unless type.nil? || type.name == 'void'
318
+ visibility = [:public]
319
+ if type.namespace == context || super_and_sub?(type.namespace, context)
320
+ visibility.push :protected
321
+ visibility.push :private if internal
322
+ end
323
+ result.merge get_methods(type.namespace, scope: type.scope, visibility: visibility)
324
+ end
325
+ end
326
+ end
327
+ result.to_a
328
+ end
329
+
330
+ # Get a stack of method pins for a method name in a namespace. The order
331
+ # of the pins corresponds to the ancestry chain, with highest precedence
332
+ # first.
333
+ #
334
+ # @example
335
+ # api_map.get_method_stack('Subclass', 'method_name')
336
+ # #=> [ <Subclass#method_name pin>, <Superclass#method_name pin> ]
337
+ #
338
+ # @param fqns [String]
339
+ # @param name [String]
340
+ # @param scope [Symbol] :instance or :class
341
+ # @return [Array<Solargraph::Pin::Method>]
342
+ def get_method_stack fqns, name, scope: :instance
343
+ get_methods(fqns, scope: scope, visibility: [:private, :protected, :public]).select { |p| p.name == name }
344
+ end
345
+
346
+ # Get an array of all suggestions that match the specified path.
347
+ #
348
+ # @deprecated Use #get_path_pins instead.
349
+ #
350
+ # @param path [String] The path to find
351
+ # @return [Array<Solargraph::Pin::Base>]
352
+ def get_path_suggestions path
353
+ return [] if path.nil?
354
+ resolve_method_aliases store.get_path_pins(path)
355
+ end
356
+
357
+ # Get an array of pins that match the specified path.
358
+ #
359
+ # @param path [String]
360
+ # @return [Array<Pin::Base>]
361
+ def get_path_pins path
362
+ get_path_suggestions(path)
363
+ end
364
+
365
+ # Get a list of documented paths that match the query.
366
+ #
367
+ # @example
368
+ # api_map.query('str') # Results will include `String` and `Struct`
369
+ #
370
+ # @param query [String] The text to match
371
+ # @return [Array<String>]
372
+ def search query
373
+ rake_yard(store)
374
+ found = []
375
+ code_object_paths.each do |k|
376
+ if (found.empty? || (query.include?('.') || query.include?('#')) || !(k.include?('.') || k.include?('#'))) &&
377
+ k.downcase.include?(query.downcase)
378
+ found.push k
379
+ end
380
+ end
381
+ found
382
+ end
383
+
384
+ # Get YARD documentation for the specified path.
385
+ #
386
+ # @example
387
+ # api_map.document('String#split')
388
+ #
389
+ # @param path [String] The path to find
390
+ # @return [Array<YARD::CodeObjects::Base>]
391
+ def document path
392
+ rake_yard(store)
393
+ docs = []
394
+ docs.push code_object_at(path) unless code_object_at(path).nil?
395
+ docs
396
+ end
397
+
398
+ # Get an array of all symbols in the workspace that match the query.
399
+ #
400
+ # @param query [String]
401
+ # @return [Array<Pin::Base>]
402
+ def query_symbols query
403
+ Pin::Search.new(
404
+ source_map_hash.values.flat_map(&:document_symbols),
405
+ query
406
+ ).results
407
+ end
408
+
409
+ # @param location [Solargraph::Location]
410
+ # @return [Array<Solargraph::Pin::Base>]
411
+ def locate_pins location
412
+ return [] if location.nil? || !source_map_hash.key?(location.filename)
413
+ resolve_method_aliases source_map_hash[location.filename].locate_pins(location)
414
+ end
415
+
416
+ # @raise [FileNotFoundError] if the cursor's file is not in the ApiMap
417
+ # @param cursor [Source::Cursor]
418
+ # @return [SourceMap::Clip]
419
+ def clip cursor
420
+ raise FileNotFoundError, "ApiMap did not catalog #{cursor.filename}" unless source_map_hash.key?(cursor.filename)
421
+ SourceMap::Clip.new(self, cursor)
422
+ end
423
+
424
+ # Get an array of document symbols from a file.
425
+ #
426
+ # @param filename [String]
427
+ # @return [Array<Pin::Symbol>]
428
+ def document_symbols filename
429
+ return [] unless source_map_hash.key?(filename) # @todo Raise error?
430
+ resolve_method_aliases source_map_hash[filename].document_symbols
431
+ end
432
+
433
+ # @return [Array<SourceMap>]
434
+ def source_maps
435
+ source_map_hash.values
436
+ end
437
+
438
+ # Get a source map by filename.
439
+ #
440
+ # @param filename [String]
441
+ # @return [SourceMap]
442
+ def source_map filename
443
+ raise FileNotFoundError, "Source map for `#{filename}` not found" unless source_map_hash.key?(filename)
444
+ source_map_hash[filename]
445
+ end
446
+
447
+ # True if the specified file was included in a bundle, i.e., it's either
448
+ # included in a workspace or open in a library.
449
+ #
450
+ # @param filename [String]
451
+ def bundled? filename
452
+ source_map_hash.keys.include?(filename)
453
+ end
454
+
455
+ # Check if a class is a superclass of another class.
456
+ #
457
+ # @param sup [String] The superclass
458
+ # @param sub [String] The subclass
459
+ # @return [Boolean]
460
+ def super_and_sub?(sup, sub)
461
+ fqsup = qualify(sup)
462
+ cls = qualify(sub)
463
+ tested = []
464
+ until fqsup.nil? || cls.nil? || tested.include?(cls)
465
+ return true if cls == fqsup
466
+ tested.push cls
467
+ cls = qualify_superclass(cls)
468
+ end
469
+ false
470
+ end
471
+
472
+ # Check if the host class includes the specified module.
473
+ #
474
+ # @param host [String] The class
475
+ # @param mod [String] The module
476
+ # @return [Boolean]
477
+ def type_include?(host, mod)
478
+ store.get_includes(host).include?(mod)
479
+ end
480
+
481
+ private
482
+
483
+ # A hash of source maps with filename keys.
484
+ #
485
+ # @return [Hash{String => SourceMap}]
486
+ attr_reader :source_map_hash
487
+
488
+ # @param library [String]
489
+ # @return [RbsMap]
490
+ def load_rbs_map library
491
+ # map = RbsMap.load(library)
492
+ # return map if map.resolved?
493
+ RbsMap::StdlibMap.load(library)
494
+ end
495
+
496
+ # @return [ApiMap::Store]
497
+ def store
498
+ @store ||= Store.new
499
+ end
500
+
501
+ # @return [Solargraph::ApiMap::Cache]
502
+ attr_reader :cache
503
+
504
+ # @param fqns [String] A fully qualified namespace
505
+ # @param scope [Symbol] :class or :instance
506
+ # @param visibility [Array<Symbol>] :public, :protected, and/or :private
507
+ # @param deep [Boolean]
508
+ # @param skip [Set<String>]
509
+ # @param no_core [Boolean] Skip core classes if true
510
+ # @return [Array<Pin::Base>]
511
+ def inner_get_methods fqns, scope, visibility, deep, skip, no_core = false
512
+ return [] if no_core && fqns =~ /^(Object|BasicObject|Class|Module|Kernel)$/
513
+ reqstr = "#{fqns}|#{scope}|#{visibility.sort}|#{deep}"
514
+ return [] if skip.include?(reqstr)
515
+ skip.add reqstr
516
+ result = []
517
+ if deep && scope == :instance
518
+ store.get_prepends(fqns).reverse.each do |im|
519
+ fqim = qualify(im, fqns)
520
+ result.concat inner_get_methods(fqim, scope, visibility, deep, skip, true) unless fqim.nil?
521
+ end
522
+ end
523
+ result.concat store.get_methods(fqns, scope: scope, visibility: visibility).sort{ |a, b| a.name <=> b.name }
524
+ if deep
525
+ if scope == :instance
526
+ store.get_includes(fqns).reverse.each do |im|
527
+ fqim = qualify(im, fqns)
528
+ result.concat inner_get_methods(fqim, scope, visibility, deep, skip, true) unless fqim.nil?
529
+ end
530
+ fqsc = qualify_superclass(fqns)
531
+ unless fqsc.nil?
532
+ result.concat inner_get_methods(fqsc, scope, visibility, true, skip, no_core) unless fqsc.nil?
533
+ end
534
+ else
535
+ store.get_extends(fqns).reverse.each do |em|
536
+ fqem = qualify(em, fqns)
537
+ result.concat inner_get_methods(fqem, :instance, visibility, deep, skip, true) unless fqem.nil?
538
+ end
539
+ fqsc = qualify_superclass(fqns)
540
+ unless fqsc.nil?
541
+ result.concat inner_get_methods(fqsc, scope, visibility, true, skip, true) unless fqsc.nil?
542
+ end
543
+ unless no_core || fqns.empty?
544
+ type = get_namespace_type(fqns)
545
+ result.concat inner_get_methods('Class', :instance, visibility, deep, skip, no_core) if type == :class
546
+ result.concat inner_get_methods('Module', :instance, visibility, deep, skip, no_core)
547
+ end
548
+ end
549
+ store.domains(fqns).each do |d|
550
+ dt = ComplexType.try_parse(d)
551
+ result.concat inner_get_methods(dt.namespace, dt.scope, visibility, deep, skip)
552
+ end
553
+ end
554
+ result
555
+ end
556
+
557
+ # @param fqns [String]
558
+ # @param visibility [Array<Symbol>]
559
+ # @param skip [Set<String>]
560
+ # @return [Array<Pin::Base>]
561
+ def inner_get_constants fqns, visibility, skip
562
+ return [] if fqns.nil? || skip.include?(fqns)
563
+ skip.add fqns
564
+ result = []
565
+ store.get_prepends(fqns).each do |is|
566
+ result.concat inner_get_constants(qualify(is, fqns), [:public], skip)
567
+ end
568
+ result.concat store.get_constants(fqns, visibility)
569
+ .sort { |a, b| a.name <=> b.name }
570
+ store.get_includes(fqns).each do |is|
571
+ result.concat inner_get_constants(qualify(is, fqns), [:public], skip)
572
+ end
573
+ fqsc = qualify_superclass(fqns)
574
+ unless %w[Object BasicObject].include?(fqsc)
575
+ result.concat inner_get_constants(fqsc, [:public], skip)
576
+ end
577
+ result
578
+ end
579
+
580
+ # @return [Hash]
581
+ def path_macros
582
+ @path_macros ||= {}
583
+ end
584
+
585
+ # @param namespace [String]
586
+ # @param context [String]
587
+ # @return [String]
588
+ def qualify_lower namespace, context
589
+ qualify namespace, context.split('::')[0..-2].join('::')
590
+ end
591
+
592
+ def qualify_superclass fqsub
593
+ sup = store.get_superclass(fqsub)
594
+ return nil if sup.nil?
595
+ parts = fqsub.split('::')
596
+ last = parts.pop
597
+ parts.pop if last == sup
598
+ qualify(sup, parts.join('::'))
599
+ end
600
+
601
+ # @param name [String]
602
+ # @param root [String]
603
+ # @param skip [Set<String>]
604
+ # @return [String, nil]
605
+ def inner_qualify name, root, skip
606
+ return nil if name.nil?
607
+ return nil if skip.include?(root)
608
+ skip.add root
609
+ possibles = []
610
+ if name == ''
611
+ if root == ''
612
+ return ''
613
+ else
614
+ return inner_qualify(root, '', skip)
615
+ end
616
+ else
617
+ return name if root == '' && store.namespace_exists?(name)
618
+ roots = root.to_s.split('::')
619
+ while roots.length > 0
620
+ fqns = roots.join('::') + '::' + name
621
+ return fqns if store.namespace_exists?(fqns)
622
+ incs = store.get_includes(roots.join('::'))
623
+ incs.each do |inc|
624
+ foundinc = inner_qualify(name, inc, skip)
625
+ possibles.push foundinc unless foundinc.nil?
626
+ end
627
+ roots.pop
628
+ end
629
+ if possibles.empty?
630
+ incs = store.get_includes('')
631
+ incs.each do |inc|
632
+ foundinc = inner_qualify(name, inc, skip)
633
+ possibles.push foundinc unless foundinc.nil?
634
+ end
635
+ end
636
+ return name if store.namespace_exists?(name)
637
+ return possibles.last
638
+ end
639
+ end
640
+
641
+ # Get the namespace's type (Class or Module).
642
+ #
643
+ # @param fqns [String] A fully qualified namespace
644
+ # @return [Symbol, nil] :class, :module, or nil
645
+ def get_namespace_type fqns
646
+ return nil if fqns.nil?
647
+ # @type [Pin::Namespace, nil]
648
+ pin = store.get_path_pins(fqns).select{|p| p.is_a?(Pin::Namespace)}.first
649
+ return nil if pin.nil?
650
+ pin.type
651
+ end
652
+
653
+ # Sort an array of pins to put nil or undefined variables last.
654
+ #
655
+ # @param pins [Array<Solargraph::Pin::Base>]
656
+ # @return [Array<Solargraph::Pin::Base>]
657
+ def prefer_non_nil_variables pins
658
+ result = []
659
+ nil_pins = []
660
+ pins.each do |pin|
661
+ if pin.variable? && pin.nil_assignment?
662
+ nil_pins.push pin
663
+ else
664
+ result.push pin
665
+ end
666
+ end
667
+ result + nil_pins
668
+ end
669
+
670
+ # @param pins [Array<Pin::Base>]
671
+ # @param visibility [Array<Symbol>]
672
+ # @return [Array<Pin::Base>]
673
+ def resolve_method_aliases pins, visibility = [:public, :private, :protected]
674
+ result = []
675
+ pins.each do |pin|
676
+ resolved = resolve_method_alias(pin)
677
+ next if resolved.respond_to?(:visibility) && !visibility.include?(resolved.visibility)
678
+ result.push resolved
679
+ end
680
+ result
681
+ end
682
+
683
+ # @param pin [Pin::MethodAlias, Pin::Base]
684
+ # @return [Pin::Method]
685
+ def resolve_method_alias pin
686
+ return pin if !pin.is_a?(Pin::MethodAlias) || @method_alias_stack.include?(pin.path)
687
+ @method_alias_stack.push pin.path
688
+ origin = get_method_stack(pin.full_context.namespace, pin.original, scope: pin.scope).first
689
+ @method_alias_stack.pop
690
+ return pin if origin.nil?
691
+ args = {
692
+ location: pin.location,
693
+ closure: pin.closure,
694
+ name: pin.name,
695
+ comments: origin.comments,
696
+ scope: origin.scope,
697
+ visibility: origin.visibility,
698
+ signatures: origin.signatures,
699
+ attribute: origin.attribute?
700
+ }
701
+ Pin::Method.new **args
702
+ end
703
+ end
704
+ end