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,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+
5
+ module Solargraph
6
+ # A container of source maps and workspace data to be cataloged in an ApiMap.
7
+ #
8
+ class Bench
9
+ # @return [Set<SourceMap>]
10
+ attr_reader :source_maps
11
+
12
+ # @return [Workspace]
13
+ attr_reader :workspace
14
+
15
+ # @return [Set<String>]
16
+ attr_reader :external_requires
17
+
18
+ # @param source_maps [Array<SourceMap>, Set<SourceMap>]
19
+ # @param workspace [Workspace]
20
+ # @param external_requires [Array<String>, Set<String>]
21
+ def initialize source_maps: [], workspace: Workspace.new, external_requires: []
22
+ @source_maps = source_maps.to_set
23
+ @workspace = workspace
24
+ @external_requires = external_requires.to_set
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,51 @@
1
+ require 'fileutils'
2
+
3
+ module Solargraph
4
+ module Cache
5
+ class << self
6
+ # The base directory where cached documentation is installed.
7
+ #
8
+ # @return [String]
9
+ def base_dir
10
+ # The directory is not stored in a variable so it can be overridden
11
+ # in specs.
12
+ ENV['SOLARGRAPH_CACHE'] || File.join(Dir.home, '.solargraph', 'cache')
13
+ end
14
+
15
+ # The working directory for the current Ruby and Solargraph versions.
16
+ #
17
+ # @return [String]
18
+ def work_dir
19
+ # The directory is not stored in a variable so it can be overridden
20
+ # in specs.
21
+ File.join(base_dir, "ruby-#{RUBY_VERSION}", "rbs-#{RBS::VERSION}", "solargraph-#{Solargraph::VERSION}")
22
+ end
23
+
24
+ # @return [Array<Solargraph::Pin::Base>, nil]
25
+ def load *path
26
+ file = File.join(work_dir, *path)
27
+ return nil unless File.file?(file)
28
+ Marshal.load(File.read(file, mode: 'rb'))
29
+ rescue StandardError => e
30
+ Solargraph.logger.warn "Failed to load cached file #{file}: [#{e.class}] #{e.message}"
31
+ FileUtils.rm_f file
32
+ nil
33
+ end
34
+
35
+ # @return [Boolean]
36
+ def save *path, pins
37
+ return false if pins.empty?
38
+ file = File.join(work_dir, *path)
39
+ base = File.dirname(file)
40
+ FileUtils.mkdir_p base unless File.directory?(base)
41
+ ser = Marshal.dump(pins)
42
+ File.write file, ser, mode: 'wb'
43
+ true
44
+ end
45
+
46
+ def clear
47
+ FileUtils.rm_rf base_dir, secure: true
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class ComplexType
5
+ # Methods for accessing type data.
6
+ #
7
+ module TypeMethods
8
+ # @return [String]
9
+ attr_reader :name
10
+
11
+ # @return [String]
12
+ attr_reader :substring
13
+
14
+ # @return [String]
15
+ attr_reader :tag
16
+
17
+ # @return [Array<ComplexType>]
18
+ attr_reader :subtypes
19
+
20
+ # @return [Boolean]
21
+ def duck_type?
22
+ @duck_type ||= name.start_with?('#')
23
+ end
24
+
25
+ # @return [Boolean]
26
+ def nil_type?
27
+ @nil_type = (name.casecmp('nil') == 0) if @nil_type.nil?
28
+ @nil_type
29
+ end
30
+
31
+ # @return [Boolean]
32
+ def parameters?
33
+ !substring.empty?
34
+ end
35
+
36
+ def void?
37
+ name == 'void'
38
+ end
39
+
40
+ def defined?
41
+ !undefined?
42
+ end
43
+
44
+ def undefined?
45
+ name == 'undefined'
46
+ end
47
+
48
+ # @return [Boolean]
49
+ def list_parameters?
50
+ substring.start_with?('<')
51
+ end
52
+
53
+ # @return [Boolean]
54
+ def fixed_parameters?
55
+ substring.start_with?('(')
56
+ end
57
+
58
+ # @return [Boolean]
59
+ def hash_parameters?
60
+ substring.start_with?('{')
61
+ end
62
+
63
+ # @return [Array<ComplexType>]
64
+ def value_types
65
+ @subtypes
66
+ end
67
+
68
+ # @return [Array<ComplexType>]
69
+ def key_types
70
+ @key_types
71
+ end
72
+
73
+ # @return [String]
74
+ def namespace
75
+ # if priority higher than ||=, old implements cause unnecessary check
76
+ @namespace ||= lambda do
77
+ return 'Object' if duck_type?
78
+ return 'NilClass' if nil_type?
79
+ return (name == 'Class' || name == 'Module') && !subtypes.empty? ? subtypes.first.name : name
80
+ end.call
81
+ end
82
+
83
+ # @return [Symbol] :class or :instance
84
+ def scope
85
+ @scope ||= :instance if duck_type? || nil_type?
86
+ @scope ||= (name == 'Class' || name == 'Module') && !subtypes.empty? ? :class : :instance
87
+ end
88
+
89
+ def == other
90
+ return false unless self.class == other.class
91
+ tag == other.tag
92
+ end
93
+
94
+ def rooted?
95
+ @rooted
96
+ end
97
+
98
+ # Generate a ComplexType that fully qualifies this type's namespaces.
99
+ #
100
+ # @param api_map [ApiMap] The ApiMap that performs qualification
101
+ # @param context [String] The namespace from which to resolve names
102
+ # @return [ComplexType] The generated ComplexType
103
+ def qualify api_map, context = ''
104
+ return self if name == 'param'
105
+ return ComplexType.new([self]) if duck_type? || void? || undefined?
106
+ recon = (rooted? ? '' : context)
107
+ fqns = api_map.qualify(name, recon)
108
+ if fqns.nil?
109
+ return UniqueType::BOOLEAN if tag == 'Boolean'
110
+ return UniqueType::UNDEFINED
111
+ end
112
+ fqns = "::#{fqns}" # Ensure the resulting complex type is rooted
113
+ ltypes = key_types.map { |t| t.qualify api_map, context }.uniq
114
+ rtypes = value_types.map { |t| t.qualify api_map, context }.uniq
115
+ if list_parameters?
116
+ Solargraph::ComplexType.parse("#{fqns}<#{rtypes.map(&:tag).join(', ')}>")
117
+ elsif fixed_parameters?
118
+ Solargraph::ComplexType.parse("#{fqns}(#{rtypes.map(&:tag).join(', ')})")
119
+ elsif hash_parameters?
120
+ Solargraph::ComplexType.parse("#{fqns}{#{ltypes.map(&:tag).join(', ')} => #{rtypes.map(&:tag).join(', ')}}")
121
+ else
122
+ Solargraph::ComplexType.parse(fqns)
123
+ end
124
+ end
125
+
126
+ # @yieldparam [UniqueType]
127
+ # @return [Enumerator<UniqueType>]
128
+ def each_unique_type &block
129
+ return enum_for(__method__) unless block_given?
130
+ yield self
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class ComplexType
5
+ # An individual type signature. A complex type can consist of multiple
6
+ # unique types.
7
+ #
8
+ class UniqueType
9
+ include TypeMethods
10
+
11
+ attr_reader :all_params
12
+
13
+ # Create a UniqueType with the specified name and an optional substring.
14
+ # The substring is the parameter section of a parametrized type, e.g.,
15
+ # for the type `Array<String>`, the name is `Array` and the substring is
16
+ # `<String>`.
17
+ #
18
+ # @param name [String] The name of the type
19
+ # @param substring [String] The substring of the type
20
+ def initialize name, substring = ''
21
+ if name.start_with?('::')
22
+ @name = name[2..-1]
23
+ @rooted = true
24
+ else
25
+ @name = name
26
+ @rooted = false
27
+ end
28
+ @substring = substring
29
+ @tag = @name + substring
30
+ @key_types = []
31
+ @subtypes = []
32
+ @all_params = []
33
+ return unless parameters?
34
+ if @substring.start_with?('<(') && @substring.end_with?(')>')
35
+ subs = ComplexType.parse(substring[2..-3], partial: true)
36
+ else
37
+ subs = ComplexType.parse(substring[1..-2], partial: true)
38
+ end
39
+ if hash_parameters?
40
+ raise ComplexTypeError, "Bad hash type" unless !subs.is_a?(ComplexType) and subs.length == 2 and !subs[0].is_a?(UniqueType) and !subs[1].is_a?(UniqueType)
41
+ @key_types.concat subs[0].map { |u| ComplexType.new([u]) }
42
+ @subtypes.concat subs[1].map { |u| ComplexType.new([u]) }
43
+ else
44
+ @subtypes.concat subs
45
+ end
46
+ @all_params.concat @key_types
47
+ @all_params.concat @subtypes
48
+ end
49
+
50
+ def to_s
51
+ tag
52
+ end
53
+
54
+ def to_rbs
55
+ "#{namespace}#{parameters? ? "[#{subtypes.map { |s| s.to_rbs }.join(', ')}]" : ''}"
56
+ end
57
+
58
+ def parameterized?
59
+ name == 'param' || all_params.any?(&:parameterized?)
60
+ end
61
+
62
+ def resolve_parameters definitions, context
63
+ new_name = if name == 'param'
64
+ idx = definitions.parameters.index(subtypes.first.name)
65
+ return ComplexType::UNDEFINED if idx.nil?
66
+ param_type = context.return_type.all_params[idx]
67
+ return ComplexType::UNDEFINED unless param_type
68
+ param_type.to_s
69
+ else
70
+ name
71
+ end
72
+ new_key_types = if name != 'param'
73
+ @key_types.map { |t| t.resolve_parameters(definitions, context) }.select(&:defined?)
74
+ else
75
+ []
76
+ end
77
+ new_subtypes = if name != 'param'
78
+ @subtypes.map { |t| t.resolve_parameters(definitions, context) }.select(&:defined?)
79
+ else
80
+ []
81
+ end
82
+ if name != 'param' && !(new_key_types.empty? && new_subtypes.empty?)
83
+ if hash_parameters?
84
+ UniqueType.new(new_name, "{#{new_key_types.join(', ')} => #{new_subtypes.join(', ')}}")
85
+ elsif parameters?
86
+ if @substring.start_with?'<('
87
+ UniqueType.new(new_name, "<(#{new_subtypes.join(', ')})>")
88
+ else
89
+ UniqueType.new(new_name, "<#{new_subtypes.join(', ')}>")
90
+ end
91
+ else
92
+ UniqueType.new(new_name)
93
+ end
94
+ else
95
+ UniqueType.new(new_name)
96
+ end
97
+
98
+ # idx = definitions.parameters.index(subtypes.first.name)
99
+ # STDERR.puts "Index: #{idx}"
100
+ # return ComplexType::UNDEFINED if idx.nil?
101
+ # param_type = context.return_type.all_params[idx]
102
+ # return ComplexType::UNDEFINED unless param_type
103
+ # ComplexType.try_parse(param_type.to_s)
104
+ end
105
+
106
+ def self_to dst
107
+ return self unless selfy?
108
+ new_name = (@name == 'self' ? dst : @name)
109
+ new_key_types = @key_types.map { |t| t.self_to dst }
110
+ new_subtypes = @subtypes.map { |t| t.self_to dst }
111
+ if hash_parameters?
112
+ UniqueType.new(new_name, "{#{new_key_types.join(', ')} => #{new_subtypes.join(', ')}}")
113
+ elsif parameters?
114
+ if @substring.start_with?'<('
115
+ UniqueType.new(new_name, "<(#{new_subtypes.join(', ')})>")
116
+ else
117
+ UniqueType.new(new_name, "<#{new_subtypes.join(', ')}>")
118
+ end
119
+ else
120
+ UniqueType.new(new_name)
121
+ end
122
+ end
123
+
124
+ def selfy?
125
+ @name == 'self' || @key_types.any?(&:selfy?) || @subtypes.any?(&:selfy?)
126
+ end
127
+
128
+ UNDEFINED = UniqueType.new('undefined')
129
+ BOOLEAN = UniqueType.new('Boolean')
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,254 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ # A container for type data based on YARD type tags.
5
+ #
6
+ class ComplexType
7
+ # @!parse
8
+ # include TypeMethods
9
+
10
+ autoload :TypeMethods, 'solargraph/complex_type/type_methods'
11
+ autoload :UniqueType, 'solargraph/complex_type/unique_type'
12
+
13
+ # @param types [Array<UniqueType>]
14
+ def initialize types = [UniqueType::UNDEFINED]
15
+ @items = types.uniq(&:to_s)
16
+ end
17
+
18
+ # @param api_map [ApiMap]
19
+ # @param context [String]
20
+ # @return [ComplexType]
21
+ def qualify api_map, context = ''
22
+ types = @items.map do |t|
23
+ next t if ['Boolean', 'nil', 'void', 'undefined'].include?(t.name)
24
+ t.qualify api_map, context
25
+ end
26
+ ComplexType.new(types)
27
+ end
28
+
29
+ def first
30
+ @items.first
31
+ end
32
+
33
+ def to_rbs
34
+ ((@items.length > 1 ? '(' : '') + @items.map do |item|
35
+ "#{item.namespace}#{item.parameters? ? "[#{item.subtypes.map { |s| s.to_rbs }.join(', ')}]" : ''}"
36
+ end.join(' | ') + (@items.length > 1 ? ')' : '')).gsub(/undefined/, 'untyped')
37
+ end
38
+
39
+ def map &block
40
+ @items.map &block
41
+ end
42
+
43
+ # @yieldparam [UniqueType]
44
+ # @return [Array]
45
+ def each &block
46
+ @items.each &block
47
+ end
48
+
49
+ # @yieldparam [UniqueType]
50
+ # @return [Enumerator<UniqueType>]
51
+ def each_unique_type &block
52
+ return enum_for(__method__) unless block_given?
53
+
54
+ @items.each do |item|
55
+ item.each_unique_type &block
56
+ end
57
+ end
58
+
59
+ def length
60
+ @items.length
61
+ end
62
+
63
+ def [](index)
64
+ @items[index]
65
+ end
66
+
67
+ def select &block
68
+ @items.select &block
69
+ end
70
+ def namespace
71
+ # cache this attr for high frequency call
72
+ @namespace ||= method_missing(:namespace).to_s
73
+ end
74
+
75
+ def method_missing name, *args, &block
76
+ return if @items.first.nil?
77
+ return @items.first.send(name, *args, &block) if respond_to_missing?(name)
78
+ super
79
+ end
80
+
81
+ def respond_to_missing?(name, include_private = false)
82
+ TypeMethods.public_instance_methods.include?(name) || super
83
+ end
84
+
85
+ def to_s
86
+ map(&:tag).join(', ')
87
+ end
88
+
89
+ def all? &block
90
+ @items.all? &block
91
+ end
92
+
93
+ def any? &block
94
+ @items.compact.any? &block
95
+ end
96
+
97
+ def selfy?
98
+ @items.any?(&:selfy?)
99
+ end
100
+
101
+ def parameterized?
102
+ any?(&:parameterized?)
103
+ end
104
+
105
+ def resolve_parameters definitions, context
106
+ result = @items.map { |i| i.resolve_parameters(definitions, context) }
107
+ ComplexType.parse(*result.map(&:tag))
108
+ end
109
+
110
+ # @param dst [String]
111
+ # @return [ComplexType]
112
+ def self_to dst
113
+ return self unless selfy?
114
+ red = reduce_class(dst)
115
+ result = @items.map { |i| i.self_to red }
116
+ ComplexType.parse(*result.map(&:tag))
117
+ end
118
+
119
+ def nullable?
120
+ @items.any?(&:nil_type?)
121
+ end
122
+
123
+ def all_params
124
+ @items.first.all_params || []
125
+ end
126
+
127
+ private
128
+
129
+ # @todo This is a quick and dirty hack that forces `self` keywords
130
+ # to reference an instance of their class and never the class itself.
131
+ # This behavior may change depending on which result is expected
132
+ # from YARD conventions. See https://github.com/lsegal/yard/issues/1257
133
+ # @param dst [String]
134
+ # @return [String]
135
+ def reduce_class dst
136
+ while dst =~ /^(Class|Module)\<(.*?)\>$/
137
+ dst = dst.sub(/^(Class|Module)\</, '').sub(/\>$/, '')
138
+ end
139
+ dst
140
+ end
141
+
142
+ class << self
143
+ # Parse type strings into a ComplexType.
144
+ #
145
+ # @example
146
+ # ComplexType.parse 'String', 'Foo', 'nil' #=> [String, Foo, nil]
147
+ #
148
+ # @note
149
+ # The `partial` parameter is used to indicate that the method is
150
+ # receiving a string that will be used inside another ComplexType.
151
+ # It returns arrays of ComplexTypes instead of a single cohesive one.
152
+ # Consumers should not need to use this parameter; it should only be
153
+ # used internally.
154
+ #
155
+ # @param *strings [Array<String>] The type definitions to parse
156
+ # @param partial [Boolean] True if the string is part of a another type
157
+ # @return [ComplexType, Array, nil]
158
+ def parse *strings, partial: false
159
+ @cache ||= {}
160
+ unless partial
161
+ cached = @cache[strings]
162
+ return cached unless cached.nil?
163
+ end
164
+ types = []
165
+ key_types = nil
166
+ strings.each do |type_string|
167
+ point_stack = 0
168
+ curly_stack = 0
169
+ paren_stack = 0
170
+ base = String.new
171
+ subtype_string = String.new
172
+ type_string.each_char do |char|
173
+ if char == '='
174
+ #raise ComplexTypeError, "Invalid = in type #{type_string}" unless curly_stack > 0
175
+ elsif char == '<'
176
+ point_stack += 1
177
+ elsif char == '>'
178
+ if subtype_string.end_with?('=') && curly_stack > 0
179
+ subtype_string += char
180
+ elsif base.end_with?('=')
181
+ raise ComplexTypeError, "Invalid hash thing" unless key_types.nil?
182
+ # types.push ComplexType.new([UniqueType.new(base[0..-2].strip)])
183
+ types.push UniqueType.new(base[0..-2].strip)
184
+ key_types = types
185
+ types = []
186
+ base.clear
187
+ subtype_string.clear
188
+ next
189
+ else
190
+ raise ComplexTypeError, "Invalid close in type #{type_string}" if point_stack == 0
191
+ point_stack -= 1
192
+ subtype_string += char
193
+ end
194
+ next
195
+ elsif char == '{'
196
+ curly_stack += 1
197
+ elsif char == '}'
198
+ curly_stack -= 1
199
+ subtype_string += char
200
+ raise ComplexTypeError, "Invalid close in type #{type_string}" if curly_stack < 0
201
+ next
202
+ elsif char == '('
203
+ paren_stack += 1
204
+ elsif char == ')'
205
+ paren_stack -= 1
206
+ subtype_string += char if paren_stack == 0
207
+ raise ComplexTypeError, "Invalid close in type #{type_string}" if paren_stack < 0
208
+ next
209
+ elsif char == ',' && point_stack == 0 && curly_stack == 0 && paren_stack == 0
210
+ # types.push ComplexType.new([UniqueType.new(base.strip, subtype_string.strip)])
211
+ types.push UniqueType.new(base.strip, subtype_string.strip)
212
+ base.clear
213
+ subtype_string.clear
214
+ next
215
+ end
216
+ if point_stack == 0 && curly_stack == 0 && paren_stack == 0
217
+ base.concat char
218
+ else
219
+ subtype_string.concat char
220
+ end
221
+ end
222
+ raise ComplexTypeError, "Unclosed subtype in #{type_string}" if point_stack != 0 || curly_stack != 0 || paren_stack != 0
223
+ # types.push ComplexType.new([UniqueType.new(base, subtype_string)])
224
+ types.push UniqueType.new(base.strip, subtype_string.strip)
225
+ end
226
+ unless key_types.nil?
227
+ raise ComplexTypeError, "Invalid use of key/value parameters" unless partial
228
+ return key_types if types.empty?
229
+ return [key_types, types]
230
+ end
231
+ result = partial ? types : ComplexType.new(types)
232
+ @cache[strings] = result unless partial
233
+ result
234
+ end
235
+
236
+ # @param strings [Array<String>]
237
+ # @return [ComplexType]
238
+ def try_parse *strings
239
+ parse *strings
240
+ rescue ComplexTypeError => e
241
+ Solargraph.logger.info "Error parsing complex type: #{e.message}"
242
+ ComplexType::UNDEFINED
243
+ end
244
+ end
245
+
246
+ VOID = ComplexType.parse('void')
247
+ UNDEFINED = ComplexType.parse('undefined')
248
+ SYMBOL = ComplexType.parse('Symbol')
249
+ ROOT = ComplexType.parse('Class<>')
250
+ NIL = ComplexType.parse('nil')
251
+ SELF = ComplexType.parse('self')
252
+ BOOLEAN = ComplexType.parse('Boolean')
253
+ end
254
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Convention
5
+ # The base class for Conventions.
6
+ #
7
+ # A Convention provides Environs that customize ApiMaps with additional
8
+ # pins and other information. Subclasses should implement the `local` and
9
+ # `global` methods as necessary.
10
+ #
11
+ class Base
12
+ EMPTY_ENVIRON = Environ.new
13
+
14
+ # The Environ for a source map.
15
+ # Subclasses can override this method.
16
+ #
17
+ # @param source_map [SourceMap]
18
+ # @return [Environ]
19
+ def local source_map
20
+ EMPTY_ENVIRON
21
+ end
22
+
23
+ # The Environ for a YARD map.
24
+ # Subclasses can override this method.
25
+ #
26
+ # @param yard_map [YardMap]
27
+ # @return [Environ]
28
+ def global yard_map
29
+ EMPTY_ENVIRON
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Convention
5
+ class Gemfile < Base
6
+ def local source_map
7
+ return EMPTY_ENVIRON unless File.basename(source_map.filename) == 'Gemfile'
8
+ @environ ||= Environ.new(
9
+ requires: ['bundler'],
10
+ domains: ['Bundler::Dsl']
11
+ )
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Convention
5
+ class Gemspec < Base
6
+ def local source_map
7
+ return EMPTY_ENVIRON unless File.basename(source_map.filename).end_with?('.gemspec')
8
+ @environ ||= Environ.new(
9
+ requires: ['rubygems'],
10
+ pins: [
11
+ Solargraph::Pin::Reference::Override.from_comment(
12
+ 'Gem::Specification.new',
13
+ %(
14
+ @yieldparam [self]
15
+ )
16
+ )
17
+ ]
18
+ )
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Convention
5
+ class Rakefile < Base
6
+ def local source_map
7
+ basename = File.basename(source_map.filename)
8
+ return EMPTY_ENVIRON unless basename.end_with?('.rake') || basename == 'Rakefile'
9
+
10
+ @environ ||= Environ.new(
11
+ requires: ['rake'],
12
+ domains: ['Rake::DSL']
13
+ )
14
+ end
15
+ end
16
+ end
17
+ end