solargraph 0.58.0 → 0.59.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 (219) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.gitattributes +2 -0
  4. data/.github/workflows/linting.yml +6 -5
  5. data/.github/workflows/plugins.yml +48 -35
  6. data/.github/workflows/rspec.yml +15 -28
  7. data/.github/workflows/typecheck.yml +3 -2
  8. data/.gitignore +1 -0
  9. data/.rubocop.yml +38 -6
  10. data/.rubocop_todo.yml +53 -966
  11. data/CHANGELOG.md +24 -0
  12. data/Gemfile +3 -1
  13. data/README.md +3 -3
  14. data/Rakefile +26 -23
  15. data/bin/solargraph +9 -8
  16. data/lib/solargraph/api_map/cache.rb +110 -110
  17. data/lib/solargraph/api_map/constants.rb +288 -279
  18. data/lib/solargraph/api_map/index.rb +204 -193
  19. data/lib/solargraph/api_map/source_to_yard.rb +110 -97
  20. data/lib/solargraph/api_map/store.rb +395 -384
  21. data/lib/solargraph/api_map.rb +1029 -945
  22. data/lib/solargraph/bench.rb +44 -45
  23. data/lib/solargraph/complex_type/conformance.rb +176 -0
  24. data/lib/solargraph/complex_type/type_methods.rb +240 -228
  25. data/lib/solargraph/complex_type/unique_type.rb +641 -482
  26. data/lib/solargraph/complex_type.rb +557 -444
  27. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -61
  28. data/lib/solargraph/convention/data_definition/data_definition_node.rb +93 -91
  29. data/lib/solargraph/convention/data_definition.rb +108 -105
  30. data/lib/solargraph/convention/gemfile.rb +15 -15
  31. data/lib/solargraph/convention/gemspec.rb +23 -23
  32. data/lib/solargraph/convention/rakefile.rb +17 -17
  33. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +62 -61
  34. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +103 -102
  35. data/lib/solargraph/convention/struct_definition.rb +168 -164
  36. data/lib/solargraph/convention.rb +78 -78
  37. data/lib/solargraph/converters/dd.rb +19 -17
  38. data/lib/solargraph/converters/dl.rb +17 -15
  39. data/lib/solargraph/converters/dt.rb +17 -15
  40. data/lib/solargraph/converters/misc.rb +3 -1
  41. data/lib/solargraph/diagnostics/require_not_found.rb +54 -53
  42. data/lib/solargraph/diagnostics/rubocop.rb +119 -118
  43. data/lib/solargraph/diagnostics/rubocop_helpers.rb +70 -68
  44. data/lib/solargraph/diagnostics/type_check.rb +56 -55
  45. data/lib/solargraph/diagnostics/update_errors.rb +37 -41
  46. data/lib/solargraph/doc_map.rb +438 -439
  47. data/lib/solargraph/equality.rb +34 -34
  48. data/lib/solargraph/gem_pins.rb +98 -98
  49. data/lib/solargraph/language_server/error_codes.rb +20 -20
  50. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  51. data/lib/solargraph/language_server/host/dispatch.rb +130 -130
  52. data/lib/solargraph/language_server/host/message_worker.rb +113 -112
  53. data/lib/solargraph/language_server/host/sources.rb +100 -99
  54. data/lib/solargraph/language_server/host.rb +886 -878
  55. data/lib/solargraph/language_server/message/base.rb +97 -97
  56. data/lib/solargraph/language_server/message/client/register_capability.rb +13 -15
  57. data/lib/solargraph/language_server/message/completion_item/resolve.rb +58 -60
  58. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +108 -114
  59. data/lib/solargraph/language_server/message/extended/document.rb +24 -23
  60. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
  61. data/lib/solargraph/language_server/message/extended/download_core.rb +20 -19
  62. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  63. data/lib/solargraph/language_server/message/initialize.rb +197 -191
  64. data/lib/solargraph/language_server/message/text_document/completion.rb +58 -56
  65. data/lib/solargraph/language_server/message/text_document/definition.rb +49 -40
  66. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +23 -16
  67. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +36 -26
  68. data/lib/solargraph/language_server/message/text_document/formatting.rb +150 -148
  69. data/lib/solargraph/language_server/message/text_document/hover.rb +58 -58
  70. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +18 -11
  71. data/lib/solargraph/language_server/message/text_document/references.rb +23 -16
  72. data/lib/solargraph/language_server/message/text_document/rename.rb +26 -19
  73. data/lib/solargraph/language_server/message/text_document/signature_help.rb +25 -24
  74. data/lib/solargraph/language_server/message/text_document/type_definition.rb +33 -25
  75. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +41 -35
  76. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +48 -40
  77. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +32 -26
  78. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +33 -23
  79. data/lib/solargraph/language_server/message.rb +94 -94
  80. data/lib/solargraph/language_server/request.rb +29 -27
  81. data/lib/solargraph/language_server/transport/data_reader.rb +72 -74
  82. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  83. data/lib/solargraph/library.rb +702 -683
  84. data/lib/solargraph/location.rb +85 -82
  85. data/lib/solargraph/logging.rb +55 -37
  86. data/lib/solargraph/page.rb +92 -92
  87. data/lib/solargraph/parser/comment_ripper.rb +84 -69
  88. data/lib/solargraph/parser/flow_sensitive_typing.rb +471 -255
  89. data/lib/solargraph/parser/node_processor/base.rb +122 -92
  90. data/lib/solargraph/parser/node_processor.rb +63 -62
  91. data/lib/solargraph/parser/parser_gem/class_methods.rb +165 -149
  92. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -19
  93. data/lib/solargraph/parser/parser_gem/node_chainer.rb +191 -166
  94. data/lib/solargraph/parser/parser_gem/node_methods.rb +507 -486
  95. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -22
  96. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +61 -59
  97. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +24 -15
  98. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +45 -46
  99. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +60 -53
  100. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +38 -37
  101. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +53 -23
  102. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +42 -40
  103. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +30 -29
  104. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +61 -59
  105. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -98
  106. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  107. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -17
  108. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +39 -38
  109. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +51 -52
  110. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +302 -291
  111. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -29
  112. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  113. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +33 -29
  114. data/lib/solargraph/parser/parser_gem/node_processors.rb +74 -70
  115. data/lib/solargraph/parser/parser_gem.rb +14 -12
  116. data/lib/solargraph/parser/region.rb +75 -69
  117. data/lib/solargraph/parser/snippet.rb +19 -17
  118. data/lib/solargraph/parser.rb +25 -23
  119. data/lib/solargraph/pin/base.rb +773 -729
  120. data/lib/solargraph/pin/base_variable.rb +375 -126
  121. data/lib/solargraph/pin/block.rb +127 -104
  122. data/lib/solargraph/pin/breakable.rb +15 -9
  123. data/lib/solargraph/pin/callable.rb +275 -231
  124. data/lib/solargraph/pin/closure.rb +69 -72
  125. data/lib/solargraph/pin/common.rb +97 -79
  126. data/lib/solargraph/pin/compound_statement.rb +55 -0
  127. data/lib/solargraph/pin/constant.rb +43 -45
  128. data/lib/solargraph/pin/conversions.rb +129 -123
  129. data/lib/solargraph/pin/delegated_method.rb +131 -120
  130. data/lib/solargraph/pin/documenting.rb +116 -114
  131. data/lib/solargraph/pin/instance_variable.rb +38 -34
  132. data/lib/solargraph/pin/keyword.rb +16 -20
  133. data/lib/solargraph/pin/local_variable.rb +31 -75
  134. data/lib/solargraph/pin/method.rb +724 -672
  135. data/lib/solargraph/pin/method_alias.rb +42 -34
  136. data/lib/solargraph/pin/namespace.rb +122 -115
  137. data/lib/solargraph/pin/parameter.rb +339 -275
  138. data/lib/solargraph/pin/proxy_type.rb +42 -39
  139. data/lib/solargraph/pin/reference/override.rb +47 -47
  140. data/lib/solargraph/pin/reference/superclass.rb +17 -15
  141. data/lib/solargraph/pin/reference/type_alias.rb +16 -0
  142. data/lib/solargraph/pin/reference.rb +59 -39
  143. data/lib/solargraph/pin/search.rb +62 -61
  144. data/lib/solargraph/pin/signature.rb +64 -61
  145. data/lib/solargraph/pin/symbol.rb +54 -53
  146. data/lib/solargraph/pin/until.rb +16 -18
  147. data/lib/solargraph/pin/while.rb +16 -18
  148. data/lib/solargraph/pin.rb +46 -44
  149. data/lib/solargraph/pin_cache.rb +248 -245
  150. data/lib/solargraph/position.rb +139 -119
  151. data/lib/solargraph/range.rb +113 -112
  152. data/lib/solargraph/rbs_map/conversions.rb +952 -823
  153. data/lib/solargraph/rbs_map/core_fills.rb +91 -84
  154. data/lib/solargraph/rbs_map/core_map.rb +65 -58
  155. data/lib/solargraph/rbs_map/stdlib_map.rb +71 -43
  156. data/lib/solargraph/rbs_map.rb +207 -163
  157. data/lib/solargraph/server_methods.rb +16 -16
  158. data/lib/solargraph/shell.rb +555 -352
  159. data/lib/solargraph/source/chain/array.rb +39 -37
  160. data/lib/solargraph/source/chain/call.rb +377 -337
  161. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  162. data/lib/solargraph/source/chain/constant.rb +30 -26
  163. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  164. data/lib/solargraph/source/chain/hash.rb +37 -34
  165. data/lib/solargraph/source/chain/if.rb +30 -28
  166. data/lib/solargraph/source/chain/instance_variable.rb +36 -13
  167. data/lib/solargraph/source/chain/link.rb +99 -109
  168. data/lib/solargraph/source/chain/literal.rb +51 -48
  169. data/lib/solargraph/source/chain/or.rb +29 -23
  170. data/lib/solargraph/source/chain/q_call.rb +13 -11
  171. data/lib/solargraph/source/chain/variable.rb +15 -13
  172. data/lib/solargraph/source/chain/z_super.rb +28 -30
  173. data/lib/solargraph/source/chain.rb +304 -291
  174. data/lib/solargraph/source/change.rb +89 -82
  175. data/lib/solargraph/source/cursor.rb +172 -166
  176. data/lib/solargraph/source/encoding_fixes.rb +22 -23
  177. data/lib/solargraph/source/source_chainer.rb +218 -194
  178. data/lib/solargraph/source/updater.rb +59 -55
  179. data/lib/solargraph/source.rb +522 -498
  180. data/lib/solargraph/source_map/clip.rb +245 -226
  181. data/lib/solargraph/source_map/data.rb +37 -34
  182. data/lib/solargraph/source_map/mapper.rb +286 -259
  183. data/lib/solargraph/source_map.rb +224 -212
  184. data/lib/solargraph/type_checker/problem.rb +34 -32
  185. data/lib/solargraph/type_checker/rules.rb +157 -84
  186. data/lib/solargraph/type_checker.rb +888 -814
  187. data/lib/solargraph/version.rb +5 -5
  188. data/lib/solargraph/workspace/config.rb +258 -255
  189. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  190. data/lib/solargraph/workspace/require_paths.rb +98 -97
  191. data/lib/solargraph/workspace.rb +242 -220
  192. data/lib/solargraph/yard_map/helpers.rb +49 -44
  193. data/lib/solargraph/yard_map/mapper/to_method.rb +136 -130
  194. data/lib/solargraph/yard_map/mapper/to_namespace.rb +32 -31
  195. data/lib/solargraph/yard_map/mapper.rb +84 -79
  196. data/lib/solargraph/yard_map.rb +17 -18
  197. data/lib/solargraph/yard_tags.rb +20 -20
  198. data/lib/solargraph/yardoc.rb +90 -87
  199. data/lib/solargraph.rb +128 -105
  200. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  201. data/rbs/fills/tuple/tuple.rbs +28 -0
  202. data/rbs/shims/ast/0/node.rbs +5 -0
  203. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  204. data/rbs_collection.yaml +1 -1
  205. data/solargraph.gemspec +37 -35
  206. metadata +52 -51
  207. data/lib/solargraph/type_checker/checks.rb +0 -124
  208. data/lib/solargraph/type_checker/param_def.rb +0 -37
  209. data/lib/solargraph/yard_map/to_method.rb +0 -89
  210. data/sig/shims/ast/0/node.rbs +0 -5
  211. /data/{sig → rbs}/shims/ast/2.4/.rbs_meta.yaml +0 -0
  212. /data/{sig → rbs}/shims/ast/2.4/ast.rbs +0 -0
  213. /data/{sig → rbs}/shims/parser/3.2.0.1/builders/default.rbs +0 -0
  214. /data/{sig → rbs}/shims/parser/3.2.0.1/manifest.yaml +0 -0
  215. /data/{sig → rbs}/shims/parser/3.2.0.1/parser.rbs +0 -0
  216. /data/{sig → rbs}/shims/parser/3.2.0.1/polyfill.rbs +0 -0
  217. /data/{sig → rbs}/shims/thor/1.2.0.1/.rbs_meta.yaml +0 -0
  218. /data/{sig → rbs}/shims/thor/1.2.0.1/manifest.yaml +0 -0
  219. /data/{sig → rbs}/shims/thor/1.2.0.1/thor.rbs +0 -0
@@ -1,19 +1,19 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module Parser
5
- module ParserGem
6
- # A custom builder for source parsers that ignores character encoding
7
- # issues in literal strings.
8
- #
9
- class FlawedBuilder < ::Parser::Builders::Default
10
- # @param token [::Parser::AST::Node]
11
- # @return [String]
12
- # @sg-ignore
13
- def string_value(token)
14
- value(token)
15
- end
16
- end
17
- end
18
- end
19
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Parser
5
+ module ParserGem
6
+ # A custom builder for source parsers that ignores character encoding
7
+ # issues in literal strings.
8
+ #
9
+ class FlawedBuilder < ::Parser::Builders::Default
10
+ # @param token [::Parser::AST::Node]
11
+ # @return [String]
12
+ # @sg-ignore
13
+ def string_value token
14
+ value(token)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,166 +1,191 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module Parser
5
- module ParserGem
6
- # A factory for generating chains from nodes.
7
- #
8
- class NodeChainer
9
- include NodeMethods
10
-
11
- Chain = Source::Chain
12
-
13
- # @param node [Parser::AST::Node]
14
- # @param filename [String, nil]
15
- # @param parent [Parser::AST::Node, nil]
16
- def initialize node, filename = nil, parent = nil
17
- @node = node
18
- @filename = filename
19
- @parent = parent
20
- end
21
-
22
- # @return [Source::Chain]
23
- def chain
24
- links = generate_links(@node)
25
- Chain.new(links, @node, (Parser.is_ast_node?(@node) && @node.type == :splat))
26
- end
27
-
28
- class << self
29
- # @param node [Parser::AST::Node]
30
- # @param filename [String, nil]
31
- # @param parent [Parser::AST::Node, nil]
32
- # @return [Source::Chain]
33
- def chain node, filename = nil, parent = nil
34
- NodeChainer.new(node, filename, parent).chain
35
- end
36
-
37
- # @param code [String]
38
- # @return [Source::Chain]
39
- def load_string(code)
40
- node = Parser.parse(code.sub(/\.$/, ''))
41
- chain = NodeChainer.new(node).chain
42
- chain.links.push(Chain::Link.new) if code.end_with?('.')
43
- chain
44
- end
45
- end
46
-
47
- private
48
-
49
- # @param n [Parser::AST::Node]
50
- # @return [Array<Chain::Link>]
51
- def generate_links n
52
- return [] unless n.is_a?(::Parser::AST::Node)
53
- return generate_links(n.children[0]) if n.type == :splat
54
- # @type [Array<Chain::Link>]
55
- result = []
56
- if n.type == :block
57
- result.concat NodeChainer.chain(n.children[0], @filename, n).links
58
- elsif n.type == :send
59
- if n.children[0].is_a?(::Parser::AST::Node)
60
- result.concat generate_links(n.children[0])
61
- result.push Chain::Call.new(n.children[1].to_s, Location.from_node(n), node_args(n), passed_block(n))
62
- elsif n.children[0].nil?
63
- args = []
64
- n.children[2..-1].each do |c|
65
- args.push NodeChainer.chain(c, @filename, n)
66
- end
67
- result.push Chain::Call.new(n.children[1].to_s, Location.from_node(n), node_args(n), passed_block(n))
68
- else
69
- raise "No idea what to do with #{n}"
70
- end
71
- elsif n.type == :csend
72
- if n.children[0].is_a?(::Parser::AST::Node)
73
- result.concat generate_links(n.children[0])
74
- result.push Chain::QCall.new(n.children[1].to_s, Location.from_node(n), node_args(n))
75
- elsif n.children[0].nil?
76
- result.push Chain::QCall.new(n.children[1].to_s, Location.from_node(n), node_args(n))
77
- else
78
- raise "No idea what to do with #{n}"
79
- end
80
- elsif n.type == :self
81
- result.push Chain::Head.new('self')
82
- elsif n.type == :zsuper
83
- result.push Chain::ZSuper.new('super')
84
- elsif n.type == :super
85
- args = n.children.map { |c| NodeChainer.chain(c, @filename, n) }
86
- result.push Chain::Call.new('super', Location.from_node(n), args)
87
- elsif n.type == :yield
88
- args = n.children.map { |c| NodeChainer.chain(c, @filename, n) }
89
- result.push Chain::Call.new('yield', Location.from_node(n), args)
90
- elsif n.type == :const
91
- const = unpack_name(n)
92
- result.push Chain::Constant.new(const)
93
- elsif [:lvar, :lvasgn].include?(n.type)
94
- result.push Chain::Call.new(n.children[0].to_s, Location.from_node(n))
95
- elsif [:ivar, :ivasgn].include?(n.type)
96
- result.push Chain::InstanceVariable.new(n.children[0].to_s)
97
- elsif [:cvar, :cvasgn].include?(n.type)
98
- result.push Chain::ClassVariable.new(n.children[0].to_s)
99
- elsif [:gvar, :gvasgn].include?(n.type)
100
- result.push Chain::GlobalVariable.new(n.children[0].to_s)
101
- elsif n.type == :or_asgn
102
- new_node = n.updated(n.children[0].type, n.children[0].children + [n.children[1]])
103
- result.concat generate_links new_node
104
- elsif [:class, :module, :def, :defs].include?(n.type)
105
- # @todo Undefined or what?
106
- result.push Chain::UNDEFINED_CALL
107
- elsif n.type == :and
108
- result.concat generate_links(n.children.last)
109
- elsif n.type == :or
110
- result.push Chain::Or.new([NodeChainer.chain(n.children[0], @filename), NodeChainer.chain(n.children[1], @filename, n)])
111
- elsif n.type == :if
112
- result.push Chain::If.new([NodeChainer.chain(n.children[1], @filename), NodeChainer.chain(n.children[2], @filename, n)])
113
- elsif [:begin, :kwbegin].include?(n.type)
114
- result.concat generate_links(n.children.last)
115
- elsif n.type == :block_pass
116
- block_variable_name_node = n.children[0]
117
- if block_variable_name_node.nil?
118
- # anonymous block forwarding (e.g., "&")
119
- # added in Ruby 3.1 - https://bugs.ruby-lang.org/issues/11256
120
- result.push Chain::BlockVariable.new(nil)
121
- else
122
- if block_variable_name_node.type == :sym
123
- result.push Chain::BlockSymbol.new("#{block_variable_name_node.children[0].to_s}")
124
- else
125
- result.push Chain::BlockVariable.new("&#{block_variable_name_node.children[0].to_s}")
126
- end
127
- end
128
- elsif n.type == :hash
129
- result.push Chain::Hash.new('::Hash', n, hash_is_splatted?(n))
130
- elsif n.type == :array
131
- chained_children = n.children.map { |c| NodeChainer.chain(c) }
132
- result.push Source::Chain::Array.new(chained_children, n)
133
- else
134
- lit = infer_literal_node_type(n)
135
- result.push (lit ? Chain::Literal.new(lit, n) : Chain::Link.new)
136
- end
137
- result
138
- end
139
-
140
- # @param node [Parser::AST::Node]
141
- def hash_is_splatted? node
142
- return false unless Parser.is_ast_node?(node) && node.type == :hash
143
- return false unless Parser.is_ast_node?(node.children.last) && node.children.last.type == :kwsplat
144
- return false if Parser.is_ast_node?(node.children.last.children[0]) && node.children.last.children[0].type == :hash
145
- true
146
- end
147
-
148
- # @param node [Parser::AST::Node]
149
- # @return [Source::Chain, nil]
150
- def passed_block node
151
- return unless node == @node && @parent&.type == :block
152
-
153
- NodeChainer.chain(@parent.children[2], @filename)
154
- end
155
-
156
- # @param node [Parser::AST::Node]
157
- # @return [Array<Source::Chain>]
158
- def node_args node
159
- node.children[2..-1].map do |child|
160
- NodeChainer.chain(child, @filename, node)
161
- end
162
- end
163
- end
164
- end
165
- end
166
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Parser
5
+ module ParserGem
6
+ # A factory for generating chains from nodes.
7
+ #
8
+ class NodeChainer
9
+ include NodeMethods
10
+
11
+ Chain = Source::Chain
12
+
13
+ # @param node [Parser::AST::Node]
14
+ # @param filename [String, nil]
15
+ # @param parent [Parser::AST::Node, nil]
16
+ def initialize node, filename = nil, parent = nil
17
+ @node = node
18
+ @filename = filename
19
+ @parent = parent
20
+ end
21
+
22
+ # @return [Source::Chain]
23
+ def chain
24
+ links = generate_links(@node)
25
+ Chain.new(links, @node, Parser.is_ast_node?(@node) && @node.type == :splat)
26
+ end
27
+
28
+ class << self
29
+ # @param node [Parser::AST::Node]
30
+ # @param filename [String, nil]
31
+ # @param parent [Parser::AST::Node, nil]
32
+ # @return [Source::Chain]
33
+ def chain node, filename = nil, parent = nil
34
+ NodeChainer.new(node, filename, parent).chain
35
+ end
36
+
37
+ # @param code [String]
38
+ # @param filename [String]
39
+ # @param starting_line [Integer]
40
+ #
41
+ # @return [Source::Chain]
42
+ def load_string code, filename, starting_line
43
+ node = Parser.parse(code.sub(/\.$/, ''), filename, starting_line)
44
+ chain = NodeChainer.new(node).chain
45
+ chain.links.push(Chain::Link.new) if code.end_with?('.')
46
+ chain
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ # @param n [Parser::AST::Node]
53
+ # @return [Array<Chain::Link>]
54
+ def generate_links n
55
+ return [] unless n.is_a?(::Parser::AST::Node)
56
+ return generate_links(n.children[0]) if n.type == :splat
57
+ # @type [Array<Chain::Link>]
58
+ result = []
59
+ if n.type == :block
60
+ result.concat NodeChainer.chain(n.children[0], @filename, n).links
61
+ elsif n.type == :send
62
+ if n.children[0].is_a?(::Parser::AST::Node)
63
+ result.concat generate_links(n.children[0])
64
+ result.push Chain::Call.new(n.children[1].to_s, Location.from_node(n), node_args(n), passed_block(n))
65
+ elsif n.children[0].nil?
66
+ # @sg-ignore Need to add nil check here
67
+ n.children[2..].map do |c|
68
+ NodeChainer.chain(c, @filename, n)
69
+ end
70
+ result.push Chain::Call.new(n.children[1].to_s, Location.from_node(n), node_args(n), passed_block(n))
71
+ else
72
+ raise "No idea what to do with #{n}"
73
+ end
74
+ elsif n.type == :csend
75
+ if n.children[0].is_a?(::Parser::AST::Node)
76
+ result.concat generate_links(n.children[0])
77
+ result.push Chain::QCall.new(n.children[1].to_s, Location.from_node(n), node_args(n))
78
+ elsif n.children[0].nil?
79
+ result.push Chain::QCall.new(n.children[1].to_s, Location.from_node(n), node_args(n))
80
+ else
81
+ raise "No idea what to do with #{n}"
82
+ end
83
+ elsif n.type == :self
84
+ result.push Chain::Head.new('self')
85
+ elsif n.type == :zsuper
86
+ result.push Chain::ZSuper.new('super')
87
+ elsif n.type == :super
88
+ args = n.children.map { |c| NodeChainer.chain(c, @filename, n) }
89
+ result.push Chain::Call.new('super', Location.from_node(n), args)
90
+ elsif n.type == :yield
91
+ args = n.children.map { |c| NodeChainer.chain(c, @filename, n) }
92
+ result.push Chain::Call.new('yield', Location.from_node(n), args)
93
+ elsif n.type == :const
94
+ const = unpack_name(n)
95
+ result.push Chain::Constant.new(const)
96
+ elsif %i[lvar lvasgn].include?(n.type)
97
+ result.push Chain::Call.new(n.children[0].to_s, Location.from_node(n))
98
+ elsif %i[ivar ivasgn].include?(n.type)
99
+ result.push Chain::InstanceVariable.new(n.children[0].to_s, n, Location.from_node(n))
100
+ elsif %i[cvar cvasgn].include?(n.type)
101
+ result.push Chain::ClassVariable.new(n.children[0].to_s)
102
+ elsif %i[gvar gvasgn].include?(n.type)
103
+ result.push Chain::GlobalVariable.new(n.children[0].to_s)
104
+ elsif n.type == :or_asgn
105
+ # @bar ||= 123 translates to:
106
+ #
107
+ # s(:or_asgn,
108
+ # s(:ivasgn, :@bar),
109
+ # s(:int, 123))
110
+ lhs_chain = NodeChainer.chain n.children[0] # s(:ivasgn, :@bar)
111
+ rhs_chain = NodeChainer.chain n.children[1] # s(:int, 123)
112
+ or_link = Chain::Or.new([lhs_chain, rhs_chain])
113
+ # this is just for a call chain, so we don't need to record the assignment
114
+ result.push(or_link)
115
+ elsif %i[class module def defs].include?(n.type)
116
+ # @todo Undefined or what?
117
+ result.push Chain::UNDEFINED_CALL
118
+ elsif n.type == :and
119
+ result.concat generate_links(n.children.last)
120
+ elsif n.type == :or
121
+ result.push Chain::Or.new([NodeChainer.chain(n.children[0], @filename),
122
+ NodeChainer.chain(n.children[1], @filename, n)])
123
+ elsif n.type == :if
124
+ then_clause = if n.children[1]
125
+ NodeChainer.chain(n.children[1], @filename, n)
126
+ else
127
+ Source::Chain.new([Source::Chain::Literal.new('nil', nil)], n)
128
+ end
129
+ else_clause = if n.children[2]
130
+ NodeChainer.chain(n.children[2], @filename, n)
131
+ else
132
+ Source::Chain.new([Source::Chain::Literal.new('nil', nil)], n)
133
+ end
134
+ result.push Chain::If.new([then_clause, else_clause])
135
+ elsif %i[begin kwbegin].include?(n.type)
136
+ result.concat generate_links(n.children.last)
137
+ elsif n.type == :block_pass
138
+ block_variable_name_node = n.children[0]
139
+ if block_variable_name_node.nil?
140
+ # anonymous block forwarding (e.g., "&")
141
+ # added in Ruby 3.1 - https://bugs.ruby-lang.org/issues/11256
142
+ result.push Chain::BlockVariable.new(nil)
143
+ elsif block_variable_name_node.type == :sym
144
+ result.push Chain::BlockSymbol.new(block_variable_name_node.children[0].to_s)
145
+ else
146
+ result.push Chain::BlockVariable.new("&#{block_variable_name_node.children[0]}")
147
+ end
148
+ elsif n.type == :hash
149
+ result.push Chain::Hash.new('::Hash', n, hash_is_splatted?(n))
150
+ elsif n.type == :array
151
+ chained_children = n.children.map { |c| NodeChainer.chain(c) }
152
+ result.push Source::Chain::Array.new(chained_children, n)
153
+ else
154
+ lit = infer_literal_node_type(n)
155
+ result.push(lit ? Chain::Literal.new(lit, n) : Chain::Link.new)
156
+ end
157
+ result
158
+ end
159
+
160
+ # @param node [Parser::AST::Node]
161
+ def hash_is_splatted? node
162
+ return false unless Parser.is_ast_node?(node) && node.type == :hash
163
+ return false unless Parser.is_ast_node?(node.children.last) && node.children.last.type == :kwsplat
164
+ if Parser.is_ast_node?(node.children.last.children[0]) && node.children.last.children[0].type == :hash
165
+ return false
166
+ end
167
+ true
168
+ end
169
+
170
+ # @param node [Parser::AST::Node]
171
+ # @return [Source::Chain, nil]
172
+ def passed_block node
173
+ return unless node == @node && @parent&.type == :block
174
+
175
+ # @sg-ignore Need to add nil check here
176
+ NodeChainer.chain(@parent.children[2], @filename)
177
+ end
178
+
179
+ # @param node [Parser::AST::Node]
180
+ # @sg-ignore Need to add nil check here
181
+ # @return [Array<Source::Chain>]
182
+ def node_args node
183
+ # @sg-ignore Need to add nil check here
184
+ node.children[2..].map do |child|
185
+ NodeChainer.chain(child, @filename, node)
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end