solargraph 0.51.2 → 0.54.2

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 (183) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/plugins.yml +40 -0
  3. data/.github/workflows/rspec.yml +1 -3
  4. data/.github/workflows/typecheck.yml +34 -0
  5. data/.yardopts +2 -2
  6. data/CHANGELOG.md +127 -5
  7. data/README.md +13 -16
  8. data/SPONSORS.md +1 -7
  9. data/lib/solargraph/api_map/cache.rb +50 -20
  10. data/lib/solargraph/api_map/source_to_yard.rb +17 -10
  11. data/lib/solargraph/api_map/store.rb +60 -15
  12. data/lib/solargraph/api_map.rb +282 -123
  13. data/lib/solargraph/bench.rb +3 -2
  14. data/lib/solargraph/cache.rb +29 -5
  15. data/lib/solargraph/complex_type/type_methods.rb +122 -39
  16. data/lib/solargraph/complex_type/unique_type.rb +310 -76
  17. data/lib/solargraph/complex_type.rb +166 -44
  18. data/lib/solargraph/convention.rb +0 -1
  19. data/lib/solargraph/converters/dd.rb +5 -0
  20. data/lib/solargraph/converters/dl.rb +3 -0
  21. data/lib/solargraph/converters/dt.rb +3 -0
  22. data/lib/solargraph/diagnostics/rubocop.rb +8 -7
  23. data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -0
  24. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  25. data/lib/solargraph/diagnostics.rb +2 -2
  26. data/lib/solargraph/doc_map.rb +187 -0
  27. data/lib/solargraph/gem_pins.rb +72 -0
  28. data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
  29. data/lib/solargraph/language_server/host/dispatch.rb +22 -5
  30. data/lib/solargraph/language_server/host/message_worker.rb +49 -5
  31. data/lib/solargraph/language_server/host/sources.rb +8 -65
  32. data/lib/solargraph/language_server/host.rb +65 -84
  33. data/lib/solargraph/language_server/message/base.rb +19 -12
  34. data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
  35. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
  36. data/lib/solargraph/language_server/message/initialize.rb +19 -2
  37. data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
  38. data/lib/solargraph/language_server/message/text_document/definition.rb +3 -3
  39. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +3 -3
  40. data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -0
  41. data/lib/solargraph/language_server/message/text_document/hover.rb +3 -1
  42. data/lib/solargraph/language_server/message/text_document/type_definition.rb +3 -3
  43. data/lib/solargraph/language_server/message/text_document.rb +0 -1
  44. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
  45. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -2
  46. data/lib/solargraph/language_server/progress.rb +135 -0
  47. data/lib/solargraph/language_server/transport/adapter.rb +16 -1
  48. data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
  49. data/lib/solargraph/language_server.rb +1 -0
  50. data/lib/solargraph/library.rb +207 -111
  51. data/lib/solargraph/location.rb +15 -1
  52. data/lib/solargraph/page.rb +6 -0
  53. data/lib/solargraph/parser/comment_ripper.rb +4 -0
  54. data/lib/solargraph/parser/node_methods.rb +47 -7
  55. data/lib/solargraph/parser/node_processor/base.rb +11 -1
  56. data/lib/solargraph/parser/node_processor.rb +1 -0
  57. data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +31 -9
  58. data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
  59. data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +62 -43
  60. data/lib/solargraph/parser/parser_gem/node_methods.rb +495 -0
  61. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
  62. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +57 -0
  63. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
  64. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
  65. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +2 -2
  66. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +1 -1
  67. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/def_node.rb +7 -20
  68. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
  69. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
  70. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
  71. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +4 -4
  72. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +53 -0
  73. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
  74. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
  75. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
  76. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sclass_node.rb +1 -1
  77. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +8 -6
  78. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/sym_node.rb +1 -1
  79. data/lib/solargraph/parser/parser_gem/node_processors.rb +56 -0
  80. data/lib/solargraph/parser/parser_gem.rb +12 -0
  81. data/lib/solargraph/parser/region.rb +1 -1
  82. data/lib/solargraph/parser/snippet.rb +2 -0
  83. data/lib/solargraph/parser.rb +8 -12
  84. data/lib/solargraph/pin/base.rb +78 -10
  85. data/lib/solargraph/pin/base_variable.rb +40 -7
  86. data/lib/solargraph/pin/block.rb +69 -46
  87. data/lib/solargraph/pin/callable.rb +147 -0
  88. data/lib/solargraph/pin/closure.rb +23 -3
  89. data/lib/solargraph/pin/common.rb +6 -6
  90. data/lib/solargraph/pin/conversions.rb +36 -5
  91. data/lib/solargraph/pin/delegated_method.rb +6 -2
  92. data/lib/solargraph/pin/documenting.rb +25 -32
  93. data/lib/solargraph/pin/instance_variable.rb +6 -2
  94. data/lib/solargraph/pin/local_variable.rb +13 -1
  95. data/lib/solargraph/pin/method.rb +205 -32
  96. data/lib/solargraph/pin/namespace.rb +20 -7
  97. data/lib/solargraph/pin/parameter.rb +41 -36
  98. data/lib/solargraph/pin/proxy_type.rb +1 -1
  99. data/lib/solargraph/pin/reference/override.rb +2 -2
  100. data/lib/solargraph/pin/reference.rb +8 -0
  101. data/lib/solargraph/pin/search.rb +3 -3
  102. data/lib/solargraph/pin/signature.rb +8 -14
  103. data/lib/solargraph/pin.rb +4 -2
  104. data/lib/solargraph/range.rb +4 -6
  105. data/lib/solargraph/rbs_map/conversions.rb +326 -76
  106. data/lib/solargraph/rbs_map/core_fills.rb +16 -33
  107. data/lib/solargraph/rbs_map/core_map.rb +3 -13
  108. data/lib/solargraph/rbs_map/stdlib_map.rb +2 -8
  109. data/lib/solargraph/rbs_map.rb +32 -13
  110. data/lib/solargraph/shell.rb +95 -72
  111. data/lib/solargraph/source/chain/array.rb +33 -0
  112. data/lib/solargraph/source/chain/block_symbol.rb +13 -0
  113. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  114. data/lib/solargraph/source/chain/call.rb +152 -69
  115. data/lib/solargraph/source/chain/constant.rb +15 -1
  116. data/lib/solargraph/source/chain/if.rb +23 -0
  117. data/lib/solargraph/source/chain/link.rb +17 -2
  118. data/lib/solargraph/source/chain/or.rb +2 -2
  119. data/lib/solargraph/source/chain/z_super.rb +3 -3
  120. data/lib/solargraph/source/chain.rb +85 -26
  121. data/lib/solargraph/source/change.rb +3 -0
  122. data/lib/solargraph/source/cursor.rb +16 -2
  123. data/lib/solargraph/source/source_chainer.rb +8 -5
  124. data/lib/solargraph/source/updater.rb +1 -0
  125. data/lib/solargraph/source.rb +120 -148
  126. data/lib/solargraph/source_map/clip.rb +16 -27
  127. data/lib/solargraph/source_map/data.rb +30 -0
  128. data/lib/solargraph/source_map/mapper.rb +15 -3
  129. data/lib/solargraph/source_map.rb +48 -24
  130. data/lib/solargraph/type_checker/checks.rb +10 -2
  131. data/lib/solargraph/type_checker/rules.rb +6 -1
  132. data/lib/solargraph/type_checker.rb +150 -39
  133. data/lib/solargraph/version.rb +1 -1
  134. data/lib/solargraph/views/environment.erb +3 -5
  135. data/lib/solargraph/workspace/config.rb +9 -6
  136. data/lib/solargraph/workspace.rb +30 -3
  137. data/lib/solargraph/yard_map/cache.rb +6 -0
  138. data/lib/solargraph/yard_map/helpers.rb +1 -1
  139. data/lib/solargraph/yard_map/mapper/to_method.rb +16 -3
  140. data/lib/solargraph/yard_map/mapper.rb +1 -1
  141. data/lib/solargraph/yard_map/to_method.rb +11 -4
  142. data/lib/solargraph/yard_map.rb +1 -292
  143. data/lib/solargraph/yard_tags.rb +20 -0
  144. data/lib/solargraph/yardoc.rb +52 -0
  145. data/lib/solargraph.rb +6 -4
  146. data/solargraph.gemspec +7 -6
  147. metadata +71 -82
  148. data/lib/solargraph/api_map/bundler_methods.rb +0 -22
  149. data/lib/solargraph/documentor.rb +0 -76
  150. data/lib/solargraph/language_server/host/cataloger.rb +0 -56
  151. data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
  152. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
  153. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -50
  154. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
  155. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +0 -18
  156. data/lib/solargraph/parser/legacy/node_processors.rb +0 -55
  157. data/lib/solargraph/parser/legacy.rb +0 -12
  158. data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -153
  159. data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
  160. data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -317
  161. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
  162. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
  163. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -33
  164. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
  165. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +0 -75
  166. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -68
  167. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
  168. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
  169. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
  170. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
  171. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
  172. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
  173. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
  174. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
  175. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -51
  176. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -32
  177. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
  178. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -279
  179. data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -64
  180. data/lib/solargraph/parser/rubyvm/node_wrapper.rb +0 -47
  181. data/lib/solargraph/parser/rubyvm.rb +0 -40
  182. data/lib/solargraph/rbs_map/core_signs.rb +0 -33
  183. data/lib/yard-solargraph.rb +0 -33
@@ -3,38 +3,78 @@ module Solargraph
3
3
  class NodeMethods
4
4
  module_function
5
5
 
6
+ # @abstract
7
+ # @param node [Parser::AST::Node]
8
+ # @return [String]
6
9
  def unpack_name node
7
10
  raise NotImplementedError
8
11
  end
9
12
 
10
- def infer_literal_type node
13
+ # @abstract
14
+ # @todo Temporarily here for testing. Move to Solargraph::Parser.
15
+ # @param node [Parser::AST::Node]
16
+ # @return [Array<Parser::AST::Node>]
17
+ def call_nodes_from node
11
18
  raise NotImplementedError
12
19
  end
13
20
 
14
- def calls_from node
21
+ # Find all the nodes within the provided node that potentially return a
22
+ # value.
23
+ #
24
+ # The node parameter typically represents a method's logic, e.g., the
25
+ # second child (after the :args node) of a :def node. A simple one-line
26
+ # method would typically return itself, while a node with conditions
27
+ # would return the resulting node from each conditional branch. Nodes
28
+ # that follow a :return node are assumed to be unreachable. Nil values
29
+ # are converted to nil node types.
30
+ #
31
+ # @abstract
32
+ # @param node [Parser::AST::Node]
33
+ # @return [Array<Parser::AST::Node>]
34
+ def returns_from_method_body node
15
35
  raise NotImplementedError
16
36
  end
17
37
 
18
- def returns_from node
38
+ # @abstract
39
+ # @param node [Parser::AST::Node]
40
+ #
41
+ # @return [Array<Parser::AST::Node>]
42
+ def const_nodes_from node
19
43
  raise NotImplementedError
20
44
  end
21
45
 
22
- def process node
46
+ # @abstract
47
+ # @param cursor [Solargraph::Source::Cursor]
48
+ # @return [Parser::AST::Node, nil]
49
+ def find_recipient_node cursor
23
50
  raise NotImplementedError
24
51
  end
25
52
 
26
- def references node
53
+ # @abstract
54
+ # @param node [Parser::AST::Node]
55
+ # @return [Array<AST::Node>] low-level value nodes in
56
+ # value position. Does not include explicit return
57
+ # statements
58
+ def value_position_nodes_only(node)
27
59
  raise NotImplementedError
28
60
  end
29
61
 
30
- def chain node, filename = nil, in_block = false
62
+ # @abstract
63
+ # @param nodes [Enumerable<Parser::AST::Node>]
64
+ def any_splatted_call?(nodes)
31
65
  raise NotImplementedError
32
66
  end
33
67
 
34
- def node? node
68
+ # @abstract
69
+ # @param node [Parser::AST::Node]
70
+ # @return [void]
71
+ def process node
35
72
  raise NotImplementedError
36
73
  end
37
74
 
75
+ # @abstract
76
+ # @param node [Parser::AST::Node]
77
+ # @return [Hash{Parser::AST::Node => Chain}]
38
78
  def convert_hash node
39
79
  raise NotImplementedError
40
80
  end
@@ -13,12 +13,13 @@ module Solargraph
13
13
  # @return [Array<Pin::Base>]
14
14
  attr_reader :pins
15
15
 
16
- # @return [Array<Pin::Base>]
16
+ # @return [Array<Pin::BaseVariable>]
17
17
  attr_reader :locals
18
18
 
19
19
  # @param node [Parser::AST::Node]
20
20
  # @param region [Region]
21
21
  # @param pins [Array<Pin::Base>]
22
+ # @param locals [Array<Pin::LocalVariable>]
22
23
  def initialize node, region, pins, locals
23
24
  @node = node
24
25
  @region = region
@@ -54,20 +55,29 @@ module Solargraph
54
55
  Location.new(region.filename, range)
55
56
  end
56
57
 
58
+ # @param node [Parser::AST::Node]
59
+ # @return [String, nil]
57
60
  def comments_for(node)
58
61
  region.source.comments_for(node)
59
62
  end
60
63
 
64
+ # @param position [Solargraph::Position]
65
+ # @return [Pin::Closure, nil]
61
66
  def named_path_pin position
62
67
  pins.select{|pin| pin.is_a?(Pin::Closure) && pin.path && !pin.path.empty? && pin.location.range.contain?(position)}.last
63
68
  end
64
69
 
65
70
  # @todo Candidate for deprecation
71
+ # @param position [Solargraph::Position]
72
+ # @return [Pin::Closure, nil]
66
73
  def block_pin position
74
+ # @todo determine if this can return a Pin::Block
67
75
  pins.select{|pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position)}.last
68
76
  end
69
77
 
70
78
  # @todo Candidate for deprecation
79
+ # @param position [Solargraph::Position]
80
+ # @return [Pin::Closure, nil]
71
81
  def closure_pin position
72
82
  pins.select{|pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position)}.last
73
83
  end
@@ -24,6 +24,7 @@ module Solargraph
24
24
  # @param node [Parser::AST::Node]
25
25
  # @param region [Region]
26
26
  # @param pins [Array<Pin::Base>]
27
+ # @param locals [Array<Pin::BaseVariable>]
27
28
  # @return [Array(Array<Pin::Base>, Array<Pin::Base>)]
28
29
  def self.process node, region = Region.new, pins = [], locals = []
29
30
  if pins.empty?
@@ -1,12 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'parser/current'
4
+ require 'parser/source/buffer'
2
5
 
3
6
  module Solargraph
4
7
  module Parser
5
- module Legacy
8
+ module ParserGem
6
9
  module ClassMethods
7
10
  # @param code [String]
8
- # @param filename [String]
9
- # @return [Array(Parser::AST::Node, Array<Parser::Source::Comment>)]
11
+ # @param filename [String, nil]
12
+ # @return [Array(Parser::AST::Node, Hash{Integer => String})]
10
13
  def parse_with_comments code, filename = nil
11
14
  buffer = ::Parser::Source::Buffer.new(filename, 0)
12
15
  buffer.source = code
@@ -29,7 +32,7 @@ module Solargraph
29
32
  raise Parser::SyntaxError, e.message
30
33
  end
31
34
 
32
- # @return [Parser::Base]
35
+ # @return [::Parser::Base]
33
36
  def parser
34
37
  # @todo Consider setting an instance variable. We might not need to
35
38
  # recreate the parser every time we use it.
@@ -39,19 +42,26 @@ module Solargraph
39
42
  parser
40
43
  end
41
44
 
45
+ # @param source [Source]
46
+ # @return [Array(Array<Pin::Base>, Array<Pin::Base>)]
42
47
  def map source
43
48
  NodeProcessor.process(source.node, Region.new(source: source))
44
49
  end
45
50
 
46
- def returns_from node
47
- NodeMethods.returns_from(node)
48
- end
49
-
51
+ # @param source [Source]
52
+ # @param name [String]
53
+ # @return [Array<Location>]
50
54
  def references source, name
51
55
  if name.end_with?("=")
52
56
  reg = /#{Regexp.escape name[0..-2]}\s*=/
57
+ # @param code [String]
58
+ # @param offset [Integer]
59
+ # @return [Array(Integer, Integer), Array(nil, nil)]
53
60
  extract_offset = ->(code, offset) { reg.match(code, offset).offset(0) }
54
61
  else
62
+ # @param code [String]
63
+ # @param offset [Integer]
64
+ # @return [Array(Integer, Integer), Array(nil, nil)]
55
65
  extract_offset = ->(code, offset) { [soff = code.index(name, offset), soff + name.length] }
56
66
  end
57
67
  inner_node_references(name, source.node).map do |n|
@@ -80,36 +90,48 @@ module Solargraph
80
90
  result
81
91
  end
82
92
 
93
+ # @return [Source::Chain]
83
94
  def chain *args
84
95
  NodeChainer.chain *args
85
96
  end
86
97
 
98
+ # @return [Source::Chain]
87
99
  def chain_string *args
88
100
  NodeChainer.load_string *args
89
101
  end
90
102
 
103
+ # @return [Array(Array<Pin::Base>, Array<Pin::Base>)]
91
104
  def process_node *args
92
105
  Solargraph::Parser::NodeProcessor.process *args
93
106
  end
94
107
 
108
+ # @param node [Parser::AST::Node]
109
+ # @return [String, nil]
95
110
  def infer_literal_node_type node
96
111
  NodeMethods.infer_literal_node_type node
97
112
  end
98
113
 
114
+ # @return [Integer]
99
115
  def version
100
116
  parser.version
101
117
  end
102
118
 
119
+ # @param node [BasicObject]
120
+ # @return [Boolean]
103
121
  def is_ast_node? node
104
122
  node.is_a?(::Parser::AST::Node)
105
123
  end
106
124
 
125
+ # @param node [Parser::AST::Node]
126
+ # @return [Range]
107
127
  def node_range node
108
128
  st = Position.new(node.loc.line, node.loc.column)
109
129
  en = Position.new(node.loc.last_line, node.loc.last_column)
110
130
  Range.new(st, en)
111
131
  end
112
132
 
133
+ # @param node [Parser::AST::Node]
134
+ # @return [Array<Range>]
113
135
  def string_ranges node
114
136
  return [] unless is_ast_node?(node)
115
137
  result = []
@@ -128,7 +150,7 @@ module Solargraph
128
150
  end
129
151
  end
130
152
  result
131
- end
153
+ end
132
154
  end
133
155
  end
134
156
  end
@@ -2,11 +2,13 @@
2
2
 
3
3
  module Solargraph
4
4
  module Parser
5
- module Legacy
5
+ module ParserGem
6
6
  # A custom builder for source parsers that ignores character encoding
7
7
  # issues in literal strings.
8
8
  #
9
9
  class FlawedBuilder < ::Parser::Builders::Default
10
+ # @param token [::Parser::AST::Node]
11
+ # @return [String]
10
12
  def string_value(token)
11
13
  value(token)
12
14
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Solargraph
4
4
  module Parser
5
- module Legacy
5
+ module ParserGem
6
6
  # A factory for generating chains from nodes.
7
7
  #
8
8
  class NodeChainer
@@ -10,11 +10,12 @@ module Solargraph
10
10
  Chain = Source::Chain
11
11
 
12
12
  # @param node [Parser::AST::Node]
13
- # @param filename [String]
14
- def initialize node, filename = nil, in_block = false
13
+ # @param filename [String, nil]
14
+ # @param parent [Parser::AST::Node, nil]
15
+ def initialize node, filename = nil, parent = nil
15
16
  @node = node
16
17
  @filename = filename
17
- @in_block = in_block ? 1 : 0
18
+ @parent = parent
18
19
  end
19
20
 
20
21
  # @return [Source::Chain]
@@ -25,10 +26,11 @@ module Solargraph
25
26
 
26
27
  class << self
27
28
  # @param node [Parser::AST::Node]
28
- # @param filename [String]
29
+ # @param filename [String, nil]
30
+ # @param parent [Parser::AST::Node, nil]
29
31
  # @return [Source::Chain]
30
- def chain node, filename = nil, in_block = false
31
- NodeChainer.new(node, filename, in_block).chain
32
+ def chain node, filename = nil, parent = nil
33
+ NodeChainer.new(node, filename, parent).chain
32
34
  end
33
35
 
34
36
  # @param code [String]
@@ -47,66 +49,61 @@ module Solargraph
47
49
  # @return [Array<Chain::Link>]
48
50
  def generate_links n
49
51
  return [] unless n.is_a?(::Parser::AST::Node)
50
- return generate_links(n.children[0]) if n.type == :begin
51
52
  return generate_links(n.children[0]) if n.type == :splat
53
+ # @type [Array<Chain::Link>]
52
54
  result = []
53
55
  if n.type == :block
54
- @in_block += 1
55
- result.concat generate_links(n.children[0])
56
- @in_block -= 1
56
+ result.concat NodeChainer.chain(n.children[0], @filename, n).links
57
57
  elsif n.type == :send
58
58
  if n.children[0].is_a?(::Parser::AST::Node)
59
59
  result.concat generate_links(n.children[0])
60
- args = []
61
- n.children[2..-1].each do |c|
62
- args.push NodeChainer.chain(c)
63
- end
64
- result.push Chain::Call.new(n.children[1].to_s, args, @in_block > 0 || block_passed?(n))
60
+ result.push Chain::Call.new(n.children[1].to_s, node_args(n), passed_block(n))
65
61
  elsif n.children[0].nil?
66
62
  args = []
67
63
  n.children[2..-1].each do |c|
68
- args.push NodeChainer.chain(c)
64
+ args.push NodeChainer.chain(c, @filename, n)
69
65
  end
70
- result.push Chain::Call.new(n.children[1].to_s, args, @in_block > 0 || block_passed?(n))
66
+ result.push Chain::Call.new(n.children[1].to_s, node_args(n), passed_block(n))
71
67
  else
72
68
  raise "No idea what to do with #{n}"
73
69
  end
74
70
  elsif n.type == :csend
75
71
  if n.children[0].is_a?(::Parser::AST::Node)
76
72
  result.concat generate_links(n.children[0])
77
- args = []
78
- n.children[2..-1].each do |c|
79
- args.push NodeChainer.chain(c)
80
- end
81
- result.push Chain::QCall.new(n.children[1].to_s, args, @in_block > 0 || block_passed?(n))
73
+ result.push Chain::QCall.new(n.children[1].to_s, node_args(n))
82
74
  elsif n.children[0].nil?
83
- args = []
84
- n.children[2..-1].each do |c|
85
- args.push NodeChainer.chain(c)
86
- end
87
- result.push Chain::QCall.new(n.children[1].to_s, args, @in_block > 0 || block_passed?(n))
75
+ result.push Chain::QCall.new(n.children[1].to_s, node_args(n))
88
76
  else
89
77
  raise "No idea what to do with #{n}"
90
78
  end
91
79
  elsif n.type == :self
92
80
  result.push Chain::Head.new('self')
93
81
  elsif n.type == :zsuper
94
- result.push Chain::ZSuper.new('super', @in_block > 0 || block_passed?(n))
82
+ result.push Chain::ZSuper.new('super')
95
83
  elsif n.type == :super
96
- args = n.children.map { |c| NodeChainer.chain(c) }
97
- result.push Chain::Call.new('super', args, @in_block > 0 || block_passed?(n))
84
+ args = n.children.map { |c| NodeChainer.chain(c, @filename, n) }
85
+ result.push Chain::Call.new('super', args)
86
+ elsif n.type == :yield
87
+ args = n.children.map { |c| NodeChainer.chain(c, @filename, n) }
88
+ result.push Chain::Call.new('yield', args)
98
89
  elsif n.type == :const
99
90
  const = unpack_name(n)
100
91
  result.push Chain::Constant.new(const)
101
- elsif [:lvar, :lvasgn].include?(n.type)
92
+ elsif [:lvasgn, :ivasgn, :gvasgn, :cvasgn].include?(n.type)
93
+ result.concat generate_links(n.children[1])
94
+ elsif n.type == :lvar
102
95
  result.push Chain::Call.new(n.children[0].to_s)
103
- elsif [:ivar, :ivasgn].include?(n.type)
104
- result.push Chain::InstanceVariable.new(n.children[0].to_s)
105
- elsif [:cvar, :cvasgn].include?(n.type)
106
- result.push Chain::ClassVariable.new(n.children[0].to_s)
107
- elsif [:gvar, :gvasgn].include?(n.type)
108
- result.push Chain::GlobalVariable.new(n.children[0].to_s)
96
+ elsif n.type == :ivar
97
+ result.push Chain::InstanceVariable.new(n.children[0].to_s)
98
+ elsif n.type == :cvar
99
+ result.push Chain::ClassVariable.new(n.children[0].to_s)
100
+ elsif n.type == :gvar
101
+ result.push Chain::GlobalVariable.new(n.children[0].to_s)
109
102
  elsif n.type == :or_asgn
103
+ # @todo: Need a new Link class here that evaluates the
104
+ # existing variable type with the RHS, and generates a
105
+ # union type of the LHS alone if never nil, or minus nil +
106
+ # RHS if it is nilable.
110
107
  result.concat generate_links n.children[1]
111
108
  elsif [:class, :module, :def, :defs].include?(n.type)
112
109
  # @todo Undefined or what?
@@ -114,9 +111,11 @@ module Solargraph
114
111
  elsif n.type == :and
115
112
  result.concat generate_links(n.children.last)
116
113
  elsif n.type == :or
117
- result.push Chain::Or.new([NodeChainer.chain(n.children[0], @filename), NodeChainer.chain(n.children[1], @filename)])
114
+ result.push Chain::Or.new([NodeChainer.chain(n.children[0], @filename), NodeChainer.chain(n.children[1], @filename, n)])
115
+ elsif n.type == :if
116
+ result.push Chain::If.new([NodeChainer.chain(n.children[1], @filename), NodeChainer.chain(n.children[2], @filename, n)])
118
117
  elsif [:begin, :kwbegin].include?(n.type)
119
- result.concat generate_links(n.children[0])
118
+ result.concat generate_links(n.children.last)
120
119
  elsif n.type == :block_pass
121
120
  block_variable_name_node = n.children[0]
122
121
  if block_variable_name_node.nil?
@@ -124,10 +123,17 @@ module Solargraph
124
123
  # added in Ruby 3.1 - https://bugs.ruby-lang.org/issues/11256
125
124
  result.push Chain::BlockVariable.new(nil)
126
125
  else
127
- result.push Chain::BlockVariable.new("&#{block_variable_name_node.children[0].to_s}")
126
+ if block_variable_name_node.type == :sym
127
+ result.push Chain::BlockSymbol.new("#{block_variable_name_node.children[0].to_s}")
128
+ else
129
+ result.push Chain::BlockVariable.new("&#{block_variable_name_node.children[0].to_s}")
130
+ end
128
131
  end
129
132
  elsif n.type == :hash
130
133
  result.push Chain::Hash.new('::Hash', hash_is_splatted?(n))
134
+ elsif n.type == :array
135
+ chained_children = n.children.map { |c| NodeChainer.chain(c) }
136
+ result.push Source::Chain::Array.new(chained_children)
131
137
  else
132
138
  lit = infer_literal_node_type(n)
133
139
  result.push (lit ? Chain::Literal.new(lit) : Chain::Link.new)
@@ -135,6 +141,7 @@ module Solargraph
135
141
  result
136
142
  end
137
143
 
144
+ # @param node [Parser::AST::Node]
138
145
  def hash_is_splatted? node
139
146
  return false unless Parser.is_ast_node?(node) && node.type == :hash
140
147
  return false unless Parser.is_ast_node?(node.children.last) && node.children.last.type == :kwsplat
@@ -142,8 +149,20 @@ module Solargraph
142
149
  true
143
150
  end
144
151
 
145
- def block_passed? node
146
- node.children.last.is_a?(::Parser::AST::Node) && node.children.last.type == :block_pass
152
+ # @param node [Parser::AST::Node]
153
+ # @return [Source::Chain, nil]
154
+ def passed_block node
155
+ return unless node == @node && @parent&.type == :block
156
+
157
+ NodeChainer.chain(@parent.children[2], @filename)
158
+ end
159
+
160
+ # @param node [Parser::AST::Node]
161
+ # @return [Array<Source::Chain>]
162
+ def node_args node
163
+ node.children[2..-1].map do |child|
164
+ NodeChainer.chain(child, @filename, node)
165
+ end
147
166
  end
148
167
  end
149
168
  end