solargraph 0.58.1 → 0.59.0.dev.1

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 (162) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +4 -5
  4. data/.github/workflows/plugins.yml +40 -36
  5. data/.github/workflows/rspec.yml +45 -13
  6. data/.github/workflows/typecheck.yml +2 -2
  7. data/.rubocop_todo.yml +27 -49
  8. data/README.md +3 -3
  9. data/Rakefile +1 -0
  10. data/lib/solargraph/api_map/cache.rb +110 -110
  11. data/lib/solargraph/api_map/constants.rb +289 -279
  12. data/lib/solargraph/api_map/index.rb +204 -193
  13. data/lib/solargraph/api_map/source_to_yard.rb +109 -97
  14. data/lib/solargraph/api_map/store.rb +387 -384
  15. data/lib/solargraph/api_map.rb +1000 -945
  16. data/lib/solargraph/complex_type/conformance.rb +176 -0
  17. data/lib/solargraph/complex_type/type_methods.rb +242 -228
  18. data/lib/solargraph/complex_type/unique_type.rb +632 -482
  19. data/lib/solargraph/complex_type.rb +549 -444
  20. data/lib/solargraph/convention/data_definition/data_definition_node.rb +93 -91
  21. data/lib/solargraph/convention/data_definition.rb +108 -105
  22. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +62 -61
  23. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +103 -102
  24. data/lib/solargraph/convention/struct_definition.rb +168 -164
  25. data/lib/solargraph/diagnostics/require_not_found.rb +54 -53
  26. data/lib/solargraph/diagnostics/rubocop.rb +119 -118
  27. data/lib/solargraph/diagnostics/rubocop_helpers.rb +70 -68
  28. data/lib/solargraph/diagnostics/type_check.rb +56 -55
  29. data/lib/solargraph/doc_map.rb +200 -439
  30. data/lib/solargraph/equality.rb +34 -34
  31. data/lib/solargraph/gem_pins.rb +97 -98
  32. data/lib/solargraph/language_server/host/dispatch.rb +131 -130
  33. data/lib/solargraph/language_server/host/message_worker.rb +113 -112
  34. data/lib/solargraph/language_server/host/sources.rb +100 -99
  35. data/lib/solargraph/language_server/host.rb +883 -878
  36. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +109 -114
  37. data/lib/solargraph/language_server/message/extended/document.rb +24 -23
  38. data/lib/solargraph/language_server/message/text_document/completion.rb +58 -56
  39. data/lib/solargraph/language_server/message/text_document/definition.rb +42 -40
  40. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +28 -26
  41. data/lib/solargraph/language_server/message/text_document/formatting.rb +150 -148
  42. data/lib/solargraph/language_server/message/text_document/hover.rb +60 -58
  43. data/lib/solargraph/language_server/message/text_document/signature_help.rb +25 -24
  44. data/lib/solargraph/language_server/message/text_document/type_definition.rb +27 -25
  45. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +25 -23
  46. data/lib/solargraph/library.rb +729 -683
  47. data/lib/solargraph/location.rb +87 -82
  48. data/lib/solargraph/logging.rb +57 -37
  49. data/lib/solargraph/parser/comment_ripper.rb +76 -69
  50. data/lib/solargraph/parser/flow_sensitive_typing.rb +483 -255
  51. data/lib/solargraph/parser/node_processor/base.rb +122 -92
  52. data/lib/solargraph/parser/node_processor.rb +63 -62
  53. data/lib/solargraph/parser/parser_gem/class_methods.rb +167 -149
  54. data/lib/solargraph/parser/parser_gem/node_chainer.rb +191 -166
  55. data/lib/solargraph/parser/parser_gem/node_methods.rb +506 -486
  56. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -22
  57. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +61 -59
  58. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +24 -15
  59. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +46 -46
  60. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +60 -53
  61. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +53 -23
  62. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +41 -40
  63. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +30 -29
  64. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +61 -59
  65. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -98
  66. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  67. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -17
  68. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +39 -38
  69. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +53 -52
  70. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +296 -291
  71. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  72. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +33 -29
  73. data/lib/solargraph/parser/parser_gem/node_processors.rb +74 -70
  74. data/lib/solargraph/parser/region.rb +75 -69
  75. data/lib/solargraph/parser/snippet.rb +17 -17
  76. data/lib/solargraph/pin/base.rb +761 -729
  77. data/lib/solargraph/pin/base_variable.rb +418 -126
  78. data/lib/solargraph/pin/block.rb +126 -104
  79. data/lib/solargraph/pin/breakable.rb +13 -9
  80. data/lib/solargraph/pin/callable.rb +278 -231
  81. data/lib/solargraph/pin/closure.rb +68 -72
  82. data/lib/solargraph/pin/common.rb +94 -79
  83. data/lib/solargraph/pin/compound_statement.rb +55 -0
  84. data/lib/solargraph/pin/conversions.rb +124 -123
  85. data/lib/solargraph/pin/delegated_method.rb +131 -120
  86. data/lib/solargraph/pin/documenting.rb +115 -114
  87. data/lib/solargraph/pin/instance_variable.rb +38 -34
  88. data/lib/solargraph/pin/keyword.rb +16 -20
  89. data/lib/solargraph/pin/local_variable.rb +31 -75
  90. data/lib/solargraph/pin/method.rb +720 -672
  91. data/lib/solargraph/pin/method_alias.rb +42 -34
  92. data/lib/solargraph/pin/namespace.rb +121 -115
  93. data/lib/solargraph/pin/parameter.rb +338 -275
  94. data/lib/solargraph/pin/proxy_type.rb +40 -39
  95. data/lib/solargraph/pin/reference/override.rb +47 -47
  96. data/lib/solargraph/pin/reference/superclass.rb +17 -15
  97. data/lib/solargraph/pin/reference.rb +41 -39
  98. data/lib/solargraph/pin/search.rb +62 -61
  99. data/lib/solargraph/pin/signature.rb +69 -61
  100. data/lib/solargraph/pin/symbol.rb +53 -53
  101. data/lib/solargraph/pin/until.rb +18 -18
  102. data/lib/solargraph/pin/while.rb +18 -18
  103. data/lib/solargraph/pin.rb +46 -44
  104. data/lib/solargraph/pin_cache.rb +665 -245
  105. data/lib/solargraph/position.rb +118 -119
  106. data/lib/solargraph/range.rb +112 -112
  107. data/lib/solargraph/rbs_map/conversions.rb +846 -823
  108. data/lib/solargraph/rbs_map/core_map.rb +65 -58
  109. data/lib/solargraph/rbs_map/stdlib_map.rb +72 -43
  110. data/lib/solargraph/rbs_map.rb +217 -163
  111. data/lib/solargraph/shell.rb +397 -352
  112. data/lib/solargraph/source/chain/call.rb +372 -337
  113. data/lib/solargraph/source/chain/constant.rb +28 -26
  114. data/lib/solargraph/source/chain/hash.rb +35 -34
  115. data/lib/solargraph/source/chain/if.rb +29 -28
  116. data/lib/solargraph/source/chain/instance_variable.rb +34 -13
  117. data/lib/solargraph/source/chain/literal.rb +53 -48
  118. data/lib/solargraph/source/chain/or.rb +31 -23
  119. data/lib/solargraph/source/chain.rb +294 -291
  120. data/lib/solargraph/source/change.rb +89 -82
  121. data/lib/solargraph/source/cursor.rb +172 -166
  122. data/lib/solargraph/source/source_chainer.rb +204 -194
  123. data/lib/solargraph/source/updater.rb +59 -55
  124. data/lib/solargraph/source.rb +524 -498
  125. data/lib/solargraph/source_map/clip.rb +237 -226
  126. data/lib/solargraph/source_map/data.rb +37 -34
  127. data/lib/solargraph/source_map/mapper.rb +282 -259
  128. data/lib/solargraph/source_map.rb +220 -212
  129. data/lib/solargraph/type_checker/problem.rb +34 -32
  130. data/lib/solargraph/type_checker/rules.rb +157 -84
  131. data/lib/solargraph/type_checker.rb +895 -814
  132. data/lib/solargraph/version.rb +1 -1
  133. data/lib/solargraph/workspace/config.rb +257 -255
  134. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  135. data/lib/solargraph/workspace/require_paths.rb +98 -97
  136. data/lib/solargraph/workspace.rb +362 -220
  137. data/lib/solargraph/yard_map/helpers.rb +45 -44
  138. data/lib/solargraph/yard_map/mapper/to_method.rb +134 -130
  139. data/lib/solargraph/yard_map/mapper/to_namespace.rb +32 -31
  140. data/lib/solargraph/yard_map/mapper.rb +84 -79
  141. data/lib/solargraph/yardoc.rb +97 -87
  142. data/lib/solargraph.rb +126 -105
  143. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  144. data/rbs/fills/tuple/tuple.rbs +28 -0
  145. data/rbs/shims/ast/0/node.rbs +5 -0
  146. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  147. data/rbs_collection.yaml +1 -1
  148. data/solargraph.gemspec +2 -1
  149. metadata +22 -17
  150. data/lib/solargraph/type_checker/checks.rb +0 -124
  151. data/lib/solargraph/type_checker/param_def.rb +0 -37
  152. data/lib/solargraph/yard_map/to_method.rb +0 -89
  153. data/sig/shims/ast/0/node.rbs +0 -5
  154. /data/{sig → rbs}/shims/ast/2.4/.rbs_meta.yaml +0 -0
  155. /data/{sig → rbs}/shims/ast/2.4/ast.rbs +0 -0
  156. /data/{sig → rbs}/shims/parser/3.2.0.1/builders/default.rbs +0 -0
  157. /data/{sig → rbs}/shims/parser/3.2.0.1/manifest.yaml +0 -0
  158. /data/{sig → rbs}/shims/parser/3.2.0.1/parser.rbs +0 -0
  159. /data/{sig → rbs}/shims/parser/3.2.0.1/polyfill.rbs +0 -0
  160. /data/{sig → rbs}/shims/thor/1.2.0.1/.rbs_meta.yaml +0 -0
  161. /data/{sig → rbs}/shims/thor/1.2.0.1/manifest.yaml +0 -0
  162. /data/{sig → rbs}/shims/thor/1.2.0.1/thor.rbs +0 -0
@@ -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
+ args = []
67
+ # @sg-ignore Need to add nil check here
68
+ n.children[2..-1].each do |c|
69
+ args.push NodeChainer.chain(c, @filename, n)
70
+ end
71
+ result.push Chain::Call.new(n.children[1].to_s, Location.from_node(n), node_args(n), passed_block(n))
72
+ else
73
+ raise "No idea what to do with #{n}"
74
+ end
75
+ elsif n.type == :csend
76
+ if n.children[0].is_a?(::Parser::AST::Node)
77
+ result.concat generate_links(n.children[0])
78
+ result.push Chain::QCall.new(n.children[1].to_s, Location.from_node(n), node_args(n))
79
+ elsif n.children[0].nil?
80
+ result.push Chain::QCall.new(n.children[1].to_s, Location.from_node(n), node_args(n))
81
+ else
82
+ raise "No idea what to do with #{n}"
83
+ end
84
+ elsif n.type == :self
85
+ result.push Chain::Head.new('self')
86
+ elsif n.type == :zsuper
87
+ result.push Chain::ZSuper.new('super')
88
+ elsif n.type == :super
89
+ args = n.children.map { |c| NodeChainer.chain(c, @filename, n) }
90
+ result.push Chain::Call.new('super', Location.from_node(n), args)
91
+ elsif n.type == :yield
92
+ args = n.children.map { |c| NodeChainer.chain(c, @filename, n) }
93
+ result.push Chain::Call.new('yield', Location.from_node(n), args)
94
+ elsif n.type == :const
95
+ const = unpack_name(n)
96
+ result.push Chain::Constant.new(const)
97
+ elsif [:lvar, :lvasgn].include?(n.type)
98
+ result.push Chain::Call.new(n.children[0].to_s, Location.from_node(n))
99
+ elsif [:ivar, :ivasgn].include?(n.type)
100
+ result.push Chain::InstanceVariable.new(n.children[0].to_s, n, Location.from_node(n))
101
+ elsif [:cvar, :cvasgn].include?(n.type)
102
+ result.push Chain::ClassVariable.new(n.children[0].to_s)
103
+ elsif [:gvar, :gvasgn].include?(n.type)
104
+ result.push Chain::GlobalVariable.new(n.children[0].to_s)
105
+ elsif n.type == :or_asgn
106
+ # @bar ||= 123 translates to:
107
+ #
108
+ # s(:or_asgn,
109
+ # s(:ivasgn, :@bar),
110
+ # s(:int, 123))
111
+ lhs_chain = NodeChainer.chain n.children[0] # s(:ivasgn, :@bar)
112
+ rhs_chain = NodeChainer.chain n.children[1] # s(:int, 123)
113
+ or_link = Chain::Or.new([lhs_chain, rhs_chain])
114
+ # this is just for a call chain, so we don't need to record the assignment
115
+ result.push(or_link)
116
+ elsif [:class, :module, :def, :defs].include?(n.type)
117
+ # @todo Undefined or what?
118
+ result.push Chain::UNDEFINED_CALL
119
+ elsif n.type == :and
120
+ result.concat generate_links(n.children.last)
121
+ elsif n.type == :or
122
+ result.push Chain::Or.new([NodeChainer.chain(n.children[0], @filename), 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 [: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
+ else
144
+ if block_variable_name_node.type == :sym
145
+ result.push Chain::BlockSymbol.new("#{block_variable_name_node.children[0].to_s}")
146
+ else
147
+ result.push Chain::BlockVariable.new("&#{block_variable_name_node.children[0].to_s}")
148
+ end
149
+ end
150
+ elsif n.type == :hash
151
+ result.push Chain::Hash.new('::Hash', n, hash_is_splatted?(n))
152
+ elsif n.type == :array
153
+ chained_children = n.children.map { |c| NodeChainer.chain(c) }
154
+ result.push Source::Chain::Array.new(chained_children, n)
155
+ else
156
+ lit = infer_literal_node_type(n)
157
+ result.push (lit ? Chain::Literal.new(lit, n) : Chain::Link.new)
158
+ end
159
+ result
160
+ end
161
+
162
+ # @param node [Parser::AST::Node]
163
+ def hash_is_splatted? node
164
+ return false unless Parser.is_ast_node?(node) && node.type == :hash
165
+ return false unless Parser.is_ast_node?(node.children.last) && node.children.last.type == :kwsplat
166
+ return false if Parser.is_ast_node?(node.children.last.children[0]) && node.children.last.children[0].type == :hash
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..-1].map do |child|
185
+ NodeChainer.chain(child, @filename, node)
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end