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,149 @@
1
+ require 'solargraph/parser/rubyvm/node_processors'
2
+ require 'solargraph/parser/rubyvm/node_wrapper'
3
+
4
+ module Solargraph
5
+ module Parser
6
+ module Rubyvm
7
+ module ClassMethods
8
+ # @param code [String]
9
+ # @param filename [String]
10
+ # @return [Array(Parser::AST::Node, Array<Parser::Source::Comment>)]
11
+ # @sg-ignore
12
+ def parse_with_comments code, filename = nil
13
+ node = RubyVM::AbstractSyntaxTree.parse(code).children[2]
14
+ node &&= RubyVM::AbstractSyntaxTree::NodeWrapper.from(node, code.lines)
15
+ comments = CommentRipper.new(code).parse
16
+ [node, comments]
17
+ rescue ::SyntaxError => e
18
+ raise Parser::SyntaxError, e.message
19
+ end
20
+
21
+ # @param code [String]
22
+ # @param filename [String, nil]
23
+ # @param line [Integer]
24
+ # @return [Parser::AST::Node]
25
+ # @sg-ignore
26
+ def parse code, filename = nil, line = 0
27
+ node = RubyVM::AbstractSyntaxTree.parse(code).children[2]
28
+ node and RubyVM::AbstractSyntaxTree::NodeWrapper.from(node, code.lines)
29
+ rescue ::SyntaxError => e
30
+ raise Parser::SyntaxError, e.message
31
+ end
32
+
33
+ def map source
34
+ NodeProcessor.process(source.node, Region.new(source: source))
35
+ end
36
+
37
+ def references source, name
38
+ if name.end_with?("=")
39
+ reg = /#{Regexp.escape name[0..-2]}\s*=/
40
+ extract_offset = ->(code, offset) { reg.match(code, offset).offset(0) }
41
+ else
42
+ extract_offset = ->(code, offset) { [soff = code.index(name, offset), soff + name.length] }
43
+ end
44
+ inner_node_references(name, source.node).map do |n|
45
+ rng = Range.from_node(n)
46
+ offset = Position.to_offset(source.code, rng.start)
47
+ soff, eoff = extract_offset[source.code, offset]
48
+ Location.new(
49
+ source.filename,
50
+ Range.new(
51
+ Position.from_offset(source.code, soff),
52
+ Position.from_offset(source.code, eoff)
53
+ )
54
+ )
55
+ end
56
+ end
57
+
58
+ # @param name [String]
59
+ # @param top [AST::Node]
60
+ # @return [Array<AST::Node>]
61
+ def inner_node_references name, top
62
+ result = []
63
+ if Parser.rubyvm?
64
+ if Parser.is_ast_node?(top)
65
+ result.push top if match_rubyvm_node_to_ref(top, name)
66
+ top.children.each { |c| result.concat inner_node_references(name, c) }
67
+ end
68
+ else
69
+ if Parser.is_ast_node?(top) && top.to_s.include?(":#{name}")
70
+ result.push top if top.children.any? { |c| c.to_s == name }
71
+ top.children.each { |c| result.concat inner_node_references(name, c) }
72
+ end
73
+ end
74
+ result
75
+ end
76
+
77
+ def match_rubyvm_node_to_ref(top, name)
78
+ top.children.select { |c| c.is_a?(Symbol) }.any? { |c| c.to_s == name } ||
79
+ top.children.select { |c| c.is_a?(Array) }.any? { |c| c.include?(name.to_sym) }
80
+ end
81
+
82
+ def chain *args
83
+ NodeChainer.chain *args
84
+ end
85
+
86
+ def chain_string *args
87
+ NodeChainer.load_string *args
88
+ end
89
+
90
+ def process_node *args
91
+ Solargraph::Parser::NodeProcessor.process *args
92
+ end
93
+
94
+ def infer_literal_node_type node
95
+ NodeMethods.infer_literal_node_type node
96
+ end
97
+
98
+ def version
99
+ Ruby::VERSION
100
+ end
101
+
102
+ def is_ast_node? node
103
+ if Parser.rubyvm?
104
+ node.is_a?(RubyVM::AbstractSyntaxTree::Node)
105
+ else
106
+ node.is_a?(::Parser::AST::Node)
107
+ end
108
+ end
109
+
110
+ def node_range node
111
+ st = Position.new(node.first_lineno - 1, node.first_column)
112
+ en = Position.new(node.last_lineno - 1, node.last_column)
113
+ Range.new(st, en)
114
+ end
115
+
116
+ def recipient_node tree
117
+ tree.each_with_index do |node, idx|
118
+ return tree[idx + 1] if [:ARRAY, :ZARRAY, :LIST].include?(node.type) && tree[idx + 1] && [:FCALL, :VCALL, :CALL].include?(tree[idx + 1].type)
119
+ end
120
+ nil
121
+ end
122
+
123
+ def string_ranges node
124
+ return [] unless is_ast_node?(node)
125
+ result = []
126
+ if node.type == :STR
127
+ result.push Range.from_node(node)
128
+ elsif node.type == :DSTR
129
+ here = Range.from_node(node)
130
+ there = Range.from_node(node.children[1])
131
+ result.push Range.new(here.start, there&.start || here.ending)
132
+ end
133
+ node.children.each do |child|
134
+ result.concat string_ranges(child)
135
+ end
136
+ if node.type == :DSTR && node.children.last.nil?
137
+ last = node.children[-2]
138
+ unless last.nil?
139
+ rng = Range.from_node(last)
140
+ pos = Position.new(rng.ending.line, rng.ending.column - 1)
141
+ result.push Range.new(pos, pos)
142
+ end
143
+ end
144
+ result
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,160 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Parser
5
+ module Rubyvm
6
+ # A factory for generating chains from nodes.
7
+ #
8
+ class NodeChainer
9
+ include Rubyvm::NodeMethods
10
+
11
+ Chain = Source::Chain
12
+
13
+ # @param node [Parser::AST::Node]
14
+ # @param filename [String]
15
+ def initialize node, filename = nil, in_block = false
16
+ @node = node
17
+ @filename = filename
18
+ @in_block = in_block ? 1 : 0
19
+ end
20
+
21
+ # @return [Source::Chain]
22
+ def chain
23
+ links = generate_links(@node)
24
+ Chain.new(links, @node, (Parser.is_ast_node?(@node) && @node.type == :SPLAT))
25
+ end
26
+
27
+ class << self
28
+ # @param node [Parser::AST::Node]
29
+ # @param filename [String]
30
+ # @return [Source::Chain]
31
+ def chain node, filename = nil, in_block = false
32
+ NodeChainer.new(node, filename, in_block).chain
33
+ end
34
+
35
+ # @param code [String]
36
+ # @return [Source::Chain]
37
+ def load_string(code)
38
+ node = Parser.parse(code.sub(/\.$/, ''))
39
+ chain = NodeChainer.new(node).chain
40
+ chain.links.push(Chain::Link.new) if code.end_with?('.')
41
+ chain
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ # @param n [Parser::AST::Node]
48
+ # @return [Array<Chain::Link>]
49
+ def generate_links n
50
+ return [] unless Parser.is_ast_node?(n)
51
+ return generate_links(n.children[2]) if n.type == :SCOPE
52
+ return generate_links(n.children[0]) if n.type == :SPLAT
53
+ result = []
54
+ if n.type == :ITER
55
+ @in_block += 1
56
+ result.concat generate_links(n.children[0])
57
+ @in_block -= 1
58
+ elsif n.type == :CALL || n.type == :OPCALL
59
+ n.children[0..-3].each do |c|
60
+ result.concat generate_links(c)
61
+ end
62
+ result.push Chain::Call.new(n.children[-2].to_s, node_to_argchains(n.children.last), @in_block > 0 || block_passed?(n))
63
+ elsif n.type == :QCALL
64
+ n.children[0..-3].each do |c|
65
+ result.concat generate_links(c)
66
+ end
67
+ result.push Chain::QCall.new(n.children[-2].to_s, node_to_argchains(n.children.last), @in_block > 0 || block_passed?(n))
68
+ elsif n.type == :ATTRASGN
69
+ result.concat generate_links(n.children[0])
70
+ result.push Chain::Call.new(n.children[1].to_s, node_to_argchains(n.children[2]), @in_block > 0 || block_passed?(n))
71
+ elsif n.type == :VCALL
72
+ result.push Chain::Call.new(n.children[0].to_s, [], @in_block > 0 || block_passed?(n))
73
+ elsif n.type == :FCALL
74
+ result.push Chain::Call.new(n.children[0].to_s, node_to_argchains(n.children[1]), @in_block > 0 || block_passed?(n))
75
+ elsif n.type == :SELF
76
+ result.push Chain::Head.new('self')
77
+ elsif n.type == :ZSUPER
78
+ result.push Chain::ZSuper.new('super', @in_block > 0 || block_passed?(n))
79
+ elsif n.type == :SUPER
80
+ result.push Chain::Call.new('super', node_to_argchains(n.children.last), @in_block > 0 || block_passed?(n))
81
+ elsif [:COLON2, :COLON3, :CONST].include?(n.type)
82
+ const = unpack_name(n)
83
+ result.push Chain::Constant.new(const)
84
+ elsif [:LVAR, :LASGN, :DVAR].include?(n.type)
85
+ result.push Chain::Call.new(n.children[0].to_s)
86
+ elsif [:IVAR, :IASGN].include?(n.type)
87
+ result.push Chain::InstanceVariable.new(n.children[0].to_s)
88
+ elsif [:CVAR, :CVASGN].include?(n.type)
89
+ result.push Chain::ClassVariable.new(n.children[0].to_s)
90
+ elsif [:GVAR, :GASGN].include?(n.type)
91
+ result.push Chain::GlobalVariable.new(n.children[0].to_s)
92
+ elsif n.type == :OP_ASGN_OR
93
+ result.concat generate_links n.children[2]
94
+ elsif [:class, :module, :def, :defs].include?(n.type)
95
+ # @todo Undefined or what?
96
+ result.push Chain::UNDEFINED_CALL
97
+ elsif n.type == :AND
98
+ result.concat generate_links(n.children.last)
99
+ elsif n.type == :OR
100
+ result.push Chain::Or.new([NodeChainer.chain(n.children[0], @filename), NodeChainer.chain(n.children[1], @filename)])
101
+ elsif n.type == :begin
102
+ result.concat generate_links(n.children[0])
103
+ elsif n.type == :BLOCK_PASS
104
+ result.push Chain::BlockVariable.new("&#{n.children[1].children[0].to_s}")
105
+ elsif n.type == :HASH
106
+ result.push Chain::Hash.new('::Hash', hash_is_splatted?(n))
107
+ else
108
+ lit = infer_literal_node_type(n)
109
+ if lit
110
+ if lit == '::Hash'
111
+ result.push Chain::Hash.new(lit, hash_is_splatted?(n))
112
+ else
113
+ result.push Chain::Literal.new(lit)
114
+ end
115
+ else
116
+ result.push Chain::Link.new
117
+ end
118
+ # result.push (lit ? Chain::Literal.new(lit) : Chain::Link.new)
119
+ end
120
+ result
121
+ end
122
+
123
+ def hash_is_splatted? node
124
+ return false unless Parser.is_ast_node?(node.children[0]) && node.children[0].type == :LIST
125
+ list = node.children[0].children
126
+ eol = list.rindex(&:nil?)
127
+ eol && Parser.is_ast_node?(list[eol + 1])
128
+ end
129
+
130
+ def block_passed? node
131
+ node.children.last.is_a?(RubyVM::AbstractSyntaxTree::Node) && node.children.last.type == :BLOCK_PASS
132
+ end
133
+
134
+ def node_to_argchains node
135
+ return [] unless Parser.is_ast_node?(node)
136
+ if [:ZARRAY, :ARRAY, :LIST].include?(node.type)
137
+ node.children[0..-2].map { |c| NodeChainer.chain(c) }
138
+ elsif node.type == :SPLAT
139
+ [NodeChainer.chain(node)]
140
+ elsif node.type == :ARGSPUSH
141
+ result = node_to_argchains(node.children[0])
142
+ result.push NodeChainer.chain(node.children[1]) if Parser.is_ast_node?(node.children[1])
143
+ elsif node.type == :ARGSCAT
144
+ result = node.children[0].children[0..-2].map { |c| NodeChainer.chain(c) }
145
+ result.push NodeChainer.chain(node.children[1])
146
+ # @todo Smelly instance variable access
147
+ result.last.instance_variable_set(:@splat, true)
148
+ result
149
+ elsif node.type == :BLOCK_PASS
150
+ result = node_to_argchains(node.children[0])
151
+ result.push Chain.new([Chain::BlockVariable.new("&#{node.children[1].children[0].to_s}")])
152
+ result
153
+ else
154
+ []
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,315 @@
1
+ module Solargraph
2
+ module Parser
3
+ module Rubyvm
4
+ module NodeMethods
5
+ module_function
6
+
7
+ # @param node [RubyVM::AbstractSyntaxTree::Node]
8
+ # @return [String]
9
+ def unpack_name node
10
+ pack_name(node).join('::')
11
+ end
12
+
13
+ # @param node [RubyVM::AbstractSyntaxTree::Node]
14
+ # @return [Array<String>]
15
+ def pack_name(node)
16
+ parts = []
17
+ if node.is_a?(RubyVM::AbstractSyntaxTree::Node)
18
+ parts.push '' if node.type == :COLON3
19
+ node.children.each { |n|
20
+ if n.is_a?(RubyVM::AbstractSyntaxTree::Node)
21
+ parts += pack_name(n)
22
+ else
23
+ parts.push n unless n.nil?
24
+ end
25
+ }
26
+ end
27
+ parts
28
+ end
29
+
30
+ # @param node [RubyVM::AbstractSyntaxTree::Node]
31
+ # @return [String, nil]
32
+ def infer_literal_node_type node
33
+ return nil unless Parser.is_ast_node?(node)
34
+ case node.type
35
+ when :LIT, :STR
36
+ "::#{node.children.first.class.to_s}"
37
+ when :DSTR
38
+ "::String"
39
+ when :ARRAY, :ZARRAY, :LIST, :ZLIST
40
+ '::Array'
41
+ when :HASH
42
+ '::Hash'
43
+ when :DOT2, :DOT3
44
+ '::Range'
45
+ when :TRUE, :FALSE
46
+ '::Boolean'
47
+ when :SCOPE
48
+ infer_literal_node_type(node.children[2])
49
+ end
50
+ end
51
+
52
+ def returns_from node
53
+ return [] unless Parser.is_ast_node?(node)
54
+ if node.type == :SCOPE
55
+ # node.children.select { |n| n.is_a?(RubyVM::AbstractSyntaxTree::Node) }.map { |n| DeepInference.get_return_nodes(n) }.flatten
56
+ DeepInference.get_return_nodes(node.children[2])
57
+ else
58
+ DeepInference.get_return_nodes(node)
59
+ end
60
+ end
61
+
62
+ def const_nodes_from node
63
+ return [] unless Parser.is_ast_node?(node)
64
+ result = []
65
+ if [:CONST, :COLON2, :COLON3].include?(node.type)
66
+ result.push node
67
+ else
68
+ node.children.each { |child| result.concat const_nodes_from(child) }
69
+ end
70
+ result
71
+ end
72
+
73
+ def call_nodes_from node
74
+ return [] unless Parser.is_ast_node?(node)
75
+ result = []
76
+ if node.type == :ITER
77
+ result.push node.children[0]
78
+ node.children[1..-1].each { |child| result.concat call_nodes_from(child) }
79
+ elsif node.type == :MASGN
80
+ # @todo We're treating a mass assignment as a call node, but the
81
+ # type checker still needs the logic to handle it.
82
+ result.push node
83
+ elsif [:CALL, :VCALL, :FCALL, :ATTRASGN, :OPCALL].include?(node.type)
84
+ result.push node
85
+ node.children.each { |child| result.concat call_nodes_from(child) }
86
+ else
87
+ node.children.each { |child| result.concat call_nodes_from(child) }
88
+ end
89
+ result
90
+ end
91
+
92
+ def convert_hash node
93
+ return {} unless node?(node) && node.type == :HASH
94
+ return convert_hash(node.children[0].children[1]) if splatted_hash?(node)
95
+ return {} unless node?(node.children[0])
96
+ result = {}
97
+ index = 0
98
+ until index > node.children[0].children.length - 2
99
+ k = node.children[0].children[index]
100
+ return {} unless node?(k)
101
+ v = node.children[0].children[index + 1]
102
+ result[k.children[0]] = Solargraph::Parser.chain(v)
103
+ index += 2
104
+ end
105
+ result
106
+ end
107
+
108
+ def splatted_hash? node
109
+ splatted_node?(node) && node.children[0].children[1].type == :HASH
110
+ end
111
+
112
+ def splatted_node? node
113
+ node?(node.children[0]) &&
114
+ [:ARRAY, :LIST].include?(node.children[0].type) &&
115
+ node.children[0].children[0].nil? &&
116
+ node?(node.children[0].children[1])
117
+ end
118
+
119
+ def splatted_call? node
120
+ return false unless Parser.is_ast_node?(node)
121
+ splatted_node?(node) && node.children[0].children[1].type != :HASH
122
+ end
123
+
124
+ def any_splatted_call?(nodes)
125
+ nodes.any? { |n| splatted_call?(n) }
126
+ end
127
+
128
+ def node? node
129
+ node.is_a?(RubyVM::AbstractSyntaxTree::Node)
130
+ end
131
+
132
+ # @param cursor [Solargraph::Source::Cursor]
133
+ def find_recipient_node cursor
134
+ if cursor.source.synchronized?
135
+ NodeMethods.synchronized_find_recipient_node cursor
136
+ else
137
+ NodeMethods.unsynchronized_find_recipient_node cursor
138
+ end
139
+ end
140
+
141
+ class << self
142
+ protected
143
+
144
+ # @param cursor [Source::Cursor]
145
+ # @return [RubyVM::AbstractSyntaxTree::Node, nil]
146
+ def synchronized_find_recipient_node cursor
147
+ cursor = maybe_adjust_cursor(cursor)
148
+ source = cursor.source
149
+ position = cursor.position
150
+ offset = cursor.offset
151
+ tree = source.tree_at(position.line, position.column)
152
+ .select { |n| [:FCALL, :VCALL, :CALL].include?(n.type) }
153
+ unless source.repaired?
154
+ tree.shift while tree.first && !source.code_for(tree.first).strip.end_with?(')')
155
+ end
156
+ return tree.first if source.repaired? || source.code[0..offset-1] =~ /\(\s*$/
157
+ tree.each do |node|
158
+ args = node.children.find { |c| Parser.is_ast_node?(c) && [:ARRAY, :ZARRAY, :LIST].include?(c.type) }
159
+ if args
160
+ match = source.code[0..offset-1].match(/,[^\)]*\z/)
161
+ rng = Solargraph::Range.from_node(args)
162
+ if match
163
+ rng = Solargraph::Range.new(rng.start, position)
164
+ end
165
+ return node if rng.contain?(position)
166
+ end
167
+ end
168
+ nil
169
+ end
170
+
171
+ # @param cursor [Source::Cursor]
172
+ # @return [Source::Cursor]
173
+ def maybe_adjust_cursor cursor
174
+ return cursor unless (cursor.source.repaired? && cursor.source.code[cursor.offset - 1] == '(') || [',', ' '].include?(cursor.source.code[cursor.offset - 1])
175
+ cursor.source.cursor_at([cursor.position.line, cursor.position.column - 1])
176
+ end
177
+
178
+ def unsynchronized_find_recipient_node cursor
179
+ source = cursor.source
180
+ position = cursor.position
181
+ offset = cursor.offset
182
+ if source.code[0..offset-1] =~ /\([A-Zaz0-9_\s]*\z$/
183
+ tree = source.tree_at(position.line, position.column - 1)
184
+ if tree.first && [:FCALL, :VCALL, :CALL].include?(tree.first.type)
185
+ return tree.first
186
+ else
187
+ return nil
188
+ end
189
+ else
190
+ match = source.code[0..offset-1].match(/[\(,][A-Zaz0-9_\s]*\z/)
191
+ if match
192
+ moved = Position.from_offset(source.code, offset - match[0].length)
193
+ tree = source.tree_at(moved.line, moved.column)
194
+ tree.shift if match[0].start_with?(',')
195
+ tree.shift while tree.first && ![:FCALL, :VCALL, :CALL].include?(tree.first.type)
196
+ if tree.first && [:FCALL, :VCALL, :CALL].include?(tree.first.type)
197
+ return tree.first
198
+ end
199
+ end
200
+ return nil
201
+ end
202
+ end
203
+ end
204
+
205
+ module DeepInference
206
+ class << self
207
+ CONDITIONAL = [:IF, :UNLESS]
208
+ REDUCEABLE = [:BLOCK]
209
+ SKIPPABLE = [:DEFN, :DEFS, :CLASS, :SCLASS, :MODULE]
210
+
211
+ # @param node [Parser::AST::Node]
212
+ # @return [Array<Parser::AST::Node>]
213
+ def get_return_nodes node
214
+ return [] unless node.is_a?(RubyVM::AbstractSyntaxTree::Node)
215
+ result = []
216
+ if REDUCEABLE.include?(node.type)
217
+ result.concat get_return_nodes_from_children(node)
218
+ elsif CONDITIONAL.include?(node.type)
219
+ result.concat reduce_to_value_nodes(node.children[1..-1])
220
+ elsif node.type == :RESCUE
221
+ result.concat reduce_to_value_nodes([node.children[0]])
222
+ result.concat reduce_to_value_nodes(node.children[1..-2])
223
+ elsif node.type == :OR
224
+ result.concat reduce_to_value_nodes(node.children)
225
+ elsif node.type == :RETURN
226
+ result.concat reduce_to_value_nodes([node.children[0]])
227
+ elsif node.type == :ITER
228
+ result.push node
229
+ result.concat get_return_nodes_only(node.children[1])
230
+ elsif node.type == :CASE
231
+ node.children[1..-1].each do |cc|
232
+ result.concat reduce_to_value_nodes(cc.children[1..-1])
233
+ end
234
+ else
235
+ result.push node
236
+ end
237
+ result
238
+ end
239
+
240
+ private
241
+
242
+ def get_return_nodes_from_children parent
243
+ result = []
244
+ nodes = parent.children.select{|n| n.is_a?(RubyVM::AbstractSyntaxTree::Node)}
245
+ nodes.each_with_index do |node, idx|
246
+ if node.type == :BLOCK
247
+ result.concat get_return_nodes_only(node.children[2])
248
+ elsif SKIPPABLE.include?(node.type)
249
+ next
250
+ elsif CONDITIONAL.include?(node.type)
251
+ result.concat get_return_nodes_only(node)
252
+ elsif node.type == :RETURN
253
+ result.concat reduce_to_value_nodes([node.children[0]])
254
+ # Return the result here because the rest of the code is
255
+ # unreachable
256
+ return result
257
+ else
258
+ result.concat get_return_nodes_only(node)
259
+ end
260
+ result.concat reduce_to_value_nodes([nodes.last]) if idx == nodes.length - 1
261
+ end
262
+ result
263
+ end
264
+
265
+ def get_return_nodes_only parent
266
+ return [] unless parent.is_a?(RubyVM::AbstractSyntaxTree::Node)
267
+ result = []
268
+ nodes = parent.children.select{|n| n.is_a?(RubyVM::AbstractSyntaxTree::Node)}
269
+ nodes.each do |node|
270
+ next if SKIPPABLE.include?(node.type)
271
+ if node.type == :RETURN
272
+ result.concat reduce_to_value_nodes([node.children[0]])
273
+ # Return the result here because the rest of the code is
274
+ # unreachable
275
+ return result
276
+ else
277
+ result.concat get_return_nodes_only(node)
278
+ end
279
+ end
280
+ result
281
+ end
282
+
283
+ def reduce_to_value_nodes nodes
284
+ result = []
285
+ nodes.each do |node|
286
+ if !node.is_a?(RubyVM::AbstractSyntaxTree::Node)
287
+ result.push nil
288
+ elsif REDUCEABLE.include?(node.type)
289
+ result.concat get_return_nodes_from_children(node)
290
+ elsif CONDITIONAL.include?(node.type)
291
+ result.concat reduce_to_value_nodes(node.children[1..-1])
292
+ elsif node.type == :RETURN
293
+ if node.children[0].nil?
294
+ result.push nil
295
+ else
296
+ result.concat get_return_nodes(node.children[0])
297
+ end
298
+ elsif node.type == :OR
299
+ result.concat reduce_to_value_nodes(node.children)
300
+ elsif node.type == :BLOCK
301
+ result.concat get_return_nodes_only(node.children[2])
302
+ elsif node.type == :RESBODY
303
+ result.concat reduce_to_value_nodes([node.children[1]])
304
+ else
305
+ result.push node
306
+ end
307
+ end
308
+ result
309
+ end
310
+ end
311
+ end
312
+ end
313
+ end
314
+ end
315
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Parser
5
+ module Rubyvm
6
+ module NodeProcessors
7
+ class AliasNode < Parser::NodeProcessor::Base
8
+ def process
9
+ loc = get_node_location(node)
10
+ pins.push Solargraph::Pin::MethodAlias.new(
11
+ location: loc,
12
+ closure: region.closure,
13
+ name: node.children[0].children[0].to_s,
14
+ original: node.children[1].children[0].to_s,
15
+ scope: region.scope || :instance
16
+ )
17
+ process_children
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end