solargraph 0.58.3 → 0.60.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 (238) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +12 -5
  4. data/.github/workflows/plugins.yml +54 -34
  5. data/.github/workflows/rspec.yml +18 -28
  6. data/.github/workflows/typecheck.yml +6 -3
  7. data/.rubocop.yml +39 -6
  8. data/.rubocop_todo.yml +53 -966
  9. data/CHANGELOG.md +35 -0
  10. data/Gemfile +6 -1
  11. data/README.md +3 -3
  12. data/Rakefile +26 -23
  13. data/bin/solargraph +2 -1
  14. data/lib/solargraph/api_map/cache.rb +3 -3
  15. data/lib/solargraph/api_map/constants.rb +12 -3
  16. data/lib/solargraph/api_map/index.rb +42 -20
  17. data/lib/solargraph/api_map/source_to_yard.rb +22 -9
  18. data/lib/solargraph/api_map/store.rb +61 -36
  19. data/lib/solargraph/api_map.rb +192 -78
  20. data/lib/solargraph/bench.rb +2 -3
  21. data/lib/solargraph/complex_type/conformance.rb +176 -0
  22. data/lib/solargraph/complex_type/type_methods.rb +31 -18
  23. data/lib/solargraph/complex_type/unique_type.rb +225 -63
  24. data/lib/solargraph/complex_type.rb +177 -59
  25. data/lib/solargraph/convention/active_support_concern.rb +111 -111
  26. data/lib/solargraph/convention/base.rb +50 -50
  27. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -1
  28. data/lib/solargraph/convention/data_definition/data_definition_node.rb +7 -5
  29. data/lib/solargraph/convention/data_definition.rb +5 -2
  30. data/lib/solargraph/convention/gemfile.rb +1 -1
  31. data/lib/solargraph/convention/gemspec.rb +1 -1
  32. data/lib/solargraph/convention/rakefile.rb +1 -1
  33. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
  34. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -3
  35. data/lib/solargraph/convention/struct_definition.rb +8 -4
  36. data/lib/solargraph/convention.rb +2 -2
  37. data/lib/solargraph/converters/dd.rb +2 -0
  38. data/lib/solargraph/converters/dl.rb +2 -0
  39. data/lib/solargraph/converters/dt.rb +2 -0
  40. data/lib/solargraph/converters/misc.rb +2 -0
  41. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  42. data/lib/solargraph/diagnostics/rubocop.rb +11 -10
  43. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  44. data/lib/solargraph/diagnostics/type_check.rb +11 -10
  45. data/lib/solargraph/diagnostics/update_errors.rb +4 -8
  46. data/lib/solargraph/diagnostics.rb +55 -55
  47. data/lib/solargraph/doc_map.rb +39 -39
  48. data/lib/solargraph/environ.rb +52 -52
  49. data/lib/solargraph/equality.rb +4 -4
  50. data/lib/solargraph/gem_pins.rb +4 -15
  51. data/lib/solargraph/language_server/error_codes.rb +10 -10
  52. data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
  53. data/lib/solargraph/language_server/host/dispatch.rb +3 -3
  54. data/lib/solargraph/language_server/host/message_worker.rb +4 -3
  55. data/lib/solargraph/language_server/host/sources.rb +2 -1
  56. data/lib/solargraph/language_server/host.rb +35 -28
  57. data/lib/solargraph/language_server/message/base.rb +1 -1
  58. data/lib/solargraph/language_server/message/client/register_capability.rb +1 -3
  59. data/lib/solargraph/language_server/message/completion_item/resolve.rb +6 -8
  60. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +12 -18
  61. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  62. data/lib/solargraph/language_server/message/extended/document_gems.rb +7 -7
  63. data/lib/solargraph/language_server/message/extended/download_core.rb +2 -1
  64. data/lib/solargraph/language_server/message/extended/environment.rb +25 -25
  65. data/lib/solargraph/language_server/message/extended/search.rb +1 -1
  66. data/lib/solargraph/language_server/message/initialize.rb +20 -14
  67. data/lib/solargraph/language_server/message/initialized.rb +28 -28
  68. data/lib/solargraph/language_server/message/text_document/completion.rb +10 -8
  69. data/lib/solargraph/language_server/message/text_document/definition.rb +41 -32
  70. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +17 -10
  71. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +29 -19
  72. data/lib/solargraph/language_server/message/text_document/formatting.rb +8 -6
  73. data/lib/solargraph/language_server/message/text_document/hover.rb +5 -5
  74. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +13 -6
  75. data/lib/solargraph/language_server/message/text_document/references.rb +17 -10
  76. data/lib/solargraph/language_server/message/text_document/rename.rb +20 -13
  77. data/lib/solargraph/language_server/message/text_document/signature_help.rb +3 -2
  78. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -17
  79. data/lib/solargraph/language_server/message/text_document.rb +28 -28
  80. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +34 -28
  81. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +38 -30
  82. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +23 -17
  83. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +27 -17
  84. data/lib/solargraph/language_server/message.rb +1 -1
  85. data/lib/solargraph/language_server/progress.rb +143 -143
  86. data/lib/solargraph/language_server/request.rb +4 -2
  87. data/lib/solargraph/language_server/transport/adapter.rb +68 -68
  88. data/lib/solargraph/language_server/transport/data_reader.rb +11 -13
  89. data/lib/solargraph/language_server/uri_helpers.rb +2 -2
  90. data/lib/solargraph/language_server.rb +20 -20
  91. data/lib/solargraph/library.rb +57 -38
  92. data/lib/solargraph/location.rb +17 -14
  93. data/lib/solargraph/logging.rb +22 -4
  94. data/lib/solargraph/page.rb +1 -1
  95. data/lib/solargraph/parser/comment_ripper.rb +19 -4
  96. data/lib/solargraph/parser/flow_sensitive_typing.rb +324 -108
  97. data/lib/solargraph/parser/node_processor/base.rb +34 -4
  98. data/lib/solargraph/parser/node_processor.rb +8 -7
  99. data/lib/solargraph/parser/parser_gem/class_methods.rb +30 -14
  100. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -1
  101. data/lib/solargraph/parser/parser_gem/node_chainer.rb +51 -25
  102. data/lib/solargraph/parser/parser_gem/node_methods.rb +222 -72
  103. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +24 -24
  104. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  105. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +13 -11
  106. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  107. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -12
  108. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +36 -36
  109. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +24 -24
  110. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +10 -3
  111. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +9 -8
  112. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +24 -24
  113. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  114. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +5 -3
  115. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  116. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  117. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +64 -40
  118. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +3 -3
  119. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  120. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  121. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  122. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -5
  123. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +124 -113
  124. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +20 -20
  125. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +1 -1
  126. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  127. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +6 -2
  128. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  129. data/lib/solargraph/parser/parser_gem.rb +2 -0
  130. data/lib/solargraph/parser/region.rb +9 -3
  131. data/lib/solargraph/parser/snippet.rb +3 -1
  132. data/lib/solargraph/parser.rb +2 -0
  133. data/lib/solargraph/pin/base.rb +156 -84
  134. data/lib/solargraph/pin/base_variable.rb +273 -24
  135. data/lib/solargraph/pin/block.rb +29 -6
  136. data/lib/solargraph/pin/breakable.rb +7 -1
  137. data/lib/solargraph/pin/callable.rb +67 -23
  138. data/lib/solargraph/pin/closure.rb +7 -10
  139. data/lib/solargraph/pin/common.rb +36 -6
  140. data/lib/solargraph/pin/compound_statement.rb +55 -0
  141. data/lib/solargraph/pin/constant.rb +3 -5
  142. data/lib/solargraph/pin/conversions.rb +10 -4
  143. data/lib/solargraph/pin/delegated_method.rb +19 -8
  144. data/lib/solargraph/pin/documenting.rb +4 -2
  145. data/lib/solargraph/pin/instance_variable.rb +5 -1
  146. data/lib/solargraph/pin/keyword.rb +0 -4
  147. data/lib/solargraph/pin/local_variable.rb +15 -59
  148. data/lib/solargraph/pin/method.rb +205 -111
  149. data/lib/solargraph/pin/method_alias.rb +8 -0
  150. data/lib/solargraph/pin/namespace.rb +19 -12
  151. data/lib/solargraph/pin/parameter.rb +102 -36
  152. data/lib/solargraph/pin/proxy_type.rb +4 -1
  153. data/lib/solargraph/pin/reference/override.rb +1 -1
  154. data/lib/solargraph/pin/reference/require.rb +14 -14
  155. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  156. data/lib/solargraph/pin/reference/type_alias.rb +16 -0
  157. data/lib/solargraph/pin/reference.rb +20 -0
  158. data/lib/solargraph/pin/search.rb +8 -7
  159. data/lib/solargraph/pin/signature.rb +15 -12
  160. data/lib/solargraph/pin/singleton.rb +11 -11
  161. data/lib/solargraph/pin/symbol.rb +2 -1
  162. data/lib/solargraph/pin/until.rb +2 -4
  163. data/lib/solargraph/pin/while.rb +2 -4
  164. data/lib/solargraph/pin.rb +2 -0
  165. data/lib/solargraph/pin_cache.rb +22 -19
  166. data/lib/solargraph/position.rb +17 -10
  167. data/lib/solargraph/range.rb +16 -15
  168. data/lib/solargraph/rbs_map/conversions.rb +278 -191
  169. data/lib/solargraph/rbs_map/core_fills.rb +18 -11
  170. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  171. data/lib/solargraph/rbs_map/stdlib_map.rb +33 -5
  172. data/lib/solargraph/rbs_map.rb +76 -32
  173. data/lib/solargraph/rbs_translator.rb +206 -0
  174. data/lib/solargraph/server_methods.rb +1 -1
  175. data/lib/solargraph/shell.rb +330 -71
  176. data/lib/solargraph/source/chain/array.rb +3 -12
  177. data/lib/solargraph/source/chain/block_symbol.rb +13 -13
  178. data/lib/solargraph/source/chain/block_variable.rb +13 -13
  179. data/lib/solargraph/source/chain/call.rb +91 -119
  180. data/lib/solargraph/source/chain/class_variable.rb +1 -1
  181. data/lib/solargraph/source/chain/constant.rb +5 -1
  182. data/lib/solargraph/source/chain/global_variable.rb +1 -1
  183. data/lib/solargraph/source/chain/hash.rb +8 -5
  184. data/lib/solargraph/source/chain/head.rb +19 -19
  185. data/lib/solargraph/source/chain/if.rb +12 -10
  186. data/lib/solargraph/source/chain/instance_variable.rb +24 -1
  187. data/lib/solargraph/source/chain/link.rb +12 -22
  188. data/lib/solargraph/source/chain/literal.rb +22 -15
  189. data/lib/solargraph/source/chain/or.rb +10 -4
  190. data/lib/solargraph/source/chain/q_call.rb +2 -0
  191. data/lib/solargraph/source/chain/variable.rb +3 -1
  192. data/lib/solargraph/source/chain/z_super.rb +1 -3
  193. data/lib/solargraph/source/chain.rb +51 -38
  194. data/lib/solargraph/source/change.rb +12 -5
  195. data/lib/solargraph/source/cursor.rb +33 -18
  196. data/lib/solargraph/source/encoding_fixes.rb +6 -7
  197. data/lib/solargraph/source/source_chainer.rb +56 -32
  198. data/lib/solargraph/source/updater.rb +5 -1
  199. data/lib/solargraph/source.rb +59 -35
  200. data/lib/solargraph/source_map/clip.rb +54 -30
  201. data/lib/solargraph/source_map/data.rb +4 -1
  202. data/lib/solargraph/source_map/mapper.rb +28 -131
  203. data/lib/solargraph/source_map.rb +35 -9
  204. data/lib/solargraph/type_checker/problem.rb +3 -1
  205. data/lib/solargraph/type_checker/rules.rb +81 -8
  206. data/lib/solargraph/type_checker.rb +196 -122
  207. data/lib/solargraph/version.rb +19 -1
  208. data/lib/solargraph/workspace/config.rb +14 -11
  209. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  210. data/lib/solargraph/workspace/require_paths.rb +1 -0
  211. data/lib/solargraph/workspace.rb +50 -28
  212. data/lib/solargraph/yard_map/cache.rb +25 -25
  213. data/lib/solargraph/yard_map/directives/attribute_directive.rb +65 -0
  214. data/lib/solargraph/yard_map/directives/domain_directive.rb +30 -0
  215. data/lib/solargraph/yard_map/directives/method_directive.rb +51 -0
  216. data/lib/solargraph/yard_map/directives/override_directive.rb +30 -0
  217. data/lib/solargraph/yard_map/directives/parse_directive.rb +53 -0
  218. data/lib/solargraph/yard_map/directives/visibility_directive.rb +70 -0
  219. data/lib/solargraph/yard_map/directives.rb +35 -0
  220. data/lib/solargraph/yard_map/helpers.rb +8 -3
  221. data/lib/solargraph/yard_map/macro.rb +113 -0
  222. data/lib/solargraph/yard_map/mapper/to_constant.rb +28 -28
  223. data/lib/solargraph/yard_map/mapper/to_method.rb +13 -7
  224. data/lib/solargraph/yard_map/mapper/to_namespace.rb +2 -1
  225. data/lib/solargraph/yard_map/mapper.rb +31 -8
  226. data/lib/solargraph/yard_map.rb +19 -18
  227. data/lib/solargraph/yard_tags.rb +2 -2
  228. data/lib/solargraph/yardoc.rb +7 -4
  229. data/lib/solargraph.rb +34 -10
  230. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  231. data/rbs/shims/ast/0/node.rbs +1 -1
  232. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  233. data/solargraph.gemspec +38 -35
  234. metadata +64 -42
  235. data/lib/solargraph/type_checker/checks.rb +0 -124
  236. data/lib/solargraph/type_checker/param_def.rb +0 -37
  237. data/lib/solargraph/yard_map/to_method.rb +0 -89
  238. data/rbs/fills/tuple/tuple.rbs +0 -149
@@ -4,6 +4,7 @@ require 'parser'
4
4
  require 'ast'
5
5
 
6
6
  # https://github.com/whitequark/parser
7
+ # rubocop:disable Metrics/ModuleLength
7
8
  module Solargraph
8
9
  module Parser
9
10
  module ParserGem
@@ -12,17 +13,17 @@ module Solargraph
12
13
 
13
14
  # @param node [Parser::AST::Node]
14
15
  # @return [String]
15
- def unpack_name(node)
16
- pack_name(node).join("::")
16
+ def unpack_name node
17
+ pack_name(node).join('::')
17
18
  end
18
19
 
19
20
  # @param node [Parser::AST::Node]
20
21
  # @return [Array<String>]
21
- def pack_name(node)
22
+ def pack_name node
22
23
  # @type [Array<String>]
23
24
  parts = []
24
25
  if node.is_a?(AST::Node)
25
- node.children.each { |n|
26
+ node.children.each do |n|
26
27
  if n.is_a?(AST::Node)
27
28
  if n.type == :cbase
28
29
  parts = [''] + pack_name(n)
@@ -32,16 +33,16 @@ module Solargraph
32
33
  else
33
34
  parts.push n unless n.nil?
34
35
  end
35
- }
36
+ end
36
37
  end
37
38
  parts
38
39
  end
39
40
 
40
- # @param node [Parser::AST::Node]
41
+ # @param node [Parser::AST::Node, nil]
41
42
  # @return [String, nil]
42
43
  def infer_literal_node_type node
43
44
  return nil unless node.is_a?(AST::Node)
44
- if node.type == :str || node.type == :dstr
45
+ if %i[str dstr].include?(node.type)
45
46
  return '::String'
46
47
  elsif node.type == :array
47
48
  return '::Array'
@@ -53,30 +54,30 @@ module Solargraph
53
54
  return '::Integer'
54
55
  elsif node.type == :float
55
56
  return '::Float'
56
- elsif node.type == :sym || node.type == :dsym
57
+ elsif %i[sym dsym].include?(node.type)
57
58
  return '::Symbol'
58
59
  elsif node.type == :regexp
59
60
  return '::Regexp'
60
61
  elsif node.type == :irange
61
62
  return '::Range'
62
- elsif node.type == :true || node.type == :false
63
+ elsif %i[true false].include?(node.type)
63
64
  return '::Boolean'
64
65
  # @todo Support `nil` keyword in types
65
- # elsif node.type == :nil
66
- # return 'NilClass'
66
+ # elsif node.type == :nil
67
+ # return 'NilClass'
67
68
  end
68
69
  nil
69
70
  end
70
71
 
71
72
  # @param node [Parser::AST::Node]
72
73
  # @return [Position]
73
- def get_node_start_position(node)
74
+ def get_node_start_position node
74
75
  Position.new(node.loc.line, node.loc.column)
75
76
  end
76
77
 
77
78
  # @param node [Parser::AST::Node]
78
79
  # @return [Position]
79
- def get_node_end_position(node)
80
+ def get_node_end_position node
80
81
  Position.new(node.loc.last_line, node.loc.last_column)
81
82
  end
82
83
 
@@ -86,40 +87,84 @@ module Solargraph
86
87
  # @return [String]
87
88
  def drill_signature node, signature
88
89
  return signature unless node.is_a?(AST::Node)
89
- if node.type == :const or node.type == :cbase
90
- unless node.children[0].nil?
91
- signature += drill_signature(node.children[0], signature)
92
- end
90
+ if %i[const cbase].include?(node.type)
91
+ signature += drill_signature(node.children[0], signature) unless node.children[0].nil?
93
92
  signature += '::' unless signature.empty?
94
93
  signature += node.children[1].to_s
95
- elsif node.type == :lvar or node.type == :ivar or node.type == :cvar
94
+ elsif %i[lvar ivar cvar].include?(node.type)
96
95
  signature += '.' unless signature.empty?
97
96
  signature += node.children[0].to_s
98
97
  elsif node.type == :send
99
- unless node.children[0].nil?
100
- signature += drill_signature(node.children[0], signature)
101
- end
98
+ signature += drill_signature(node.children[0], signature) unless node.children[0].nil?
102
99
  signature += '.' unless signature.empty?
103
100
  signature += node.children[1].to_s
104
101
  end
105
102
  signature
106
103
  end
107
104
 
105
+ # Convert a DSL method call argument with directly inferrable simple params.
106
+ # @param node [Parser::AST::Node]
107
+ # @return [String, Integer, Float, Symbol, Array, Hash, Source::Chain, nil]
108
+ # @sg-ignore "does not match inferred type ::String, ::Parser::AST::Node" - this probably comes from the
109
+ # `.children[0]` call, which is not recognized as returning a literal value.
110
+ def simple_convert node
111
+ return nil unless Parser.is_ast_node?(node)
112
+
113
+ case node.type
114
+ when :const
115
+ unpack_name(node)
116
+ when :str, :dstr, :int, :float, :sym, true, false
117
+ node.children[0]
118
+ when :array
119
+ simple_convert_array(node)
120
+ when :hash
121
+ simple_convert_hash(node)
122
+ else
123
+ Solargraph::Parser.chain(node)
124
+ end
125
+ end
126
+
108
127
  # @param node [Parser::AST::Node]
128
+ # @return [Array]
129
+ def simple_convert_array node
130
+ return [] unless Parser.is_ast_node?(node) && node.type == :array
131
+ node.children.compact.map { |c| simple_convert(c) }
132
+ end
133
+
134
+ # @param node [Parser::AST::Node]
135
+ # @return [Hash]
136
+ def simple_convert_hash node
137
+ return {} unless Parser.is_ast_node?(node) && node.type == :hash
138
+ result = {}
139
+ # @param pair [Parser::AST::Node]
140
+ node.children.each do |pair|
141
+ next unless Parser.is_ast_node?(pair) && pair.children[0]
142
+ result[pair.children[0].children[0]] = simple_convert(pair.children[1])
143
+ end
144
+ result
145
+ end
146
+
147
+ # @param node [Parser::AST::Node, nil]
109
148
  # @return [Hash{Symbol => Chain}]
110
149
  def convert_hash node
111
150
  return {} unless Parser.is_ast_node?(node)
151
+ # @sg-ignore Translate to something flow sensitive typing understands
112
152
  return convert_hash(node.children[0]) if node.type == :kwsplat
113
- return convert_hash(node.children[0]) if Parser.is_ast_node?(node.children[0]) && node.children[0].type == :kwsplat
153
+ # @sg-ignore Translate to something flow sensitive typing understands
154
+ if Parser.is_ast_node?(node.children[0]) && node.children[0].type == :kwsplat
155
+ # @sg-ignore Translate to something flow sensitive typing understands
156
+ return convert_hash(node.children[0])
157
+ end
158
+ # @sg-ignore Translate to something flow sensitive typing understands
114
159
  return {} unless node.type == :hash
115
160
  result = {}
161
+ # @sg-ignore Translate to something flow sensitive typing understands
116
162
  node.children.each do |pair|
117
163
  result[pair.children[0].children[0]] = Solargraph::Parser.chain(pair.children[1])
118
164
  end
119
165
  result
120
166
  end
121
167
 
122
- # @sg-ignore Wrong argument type for AST::Node.new: type expected AST::_ToSym, received :nil
123
168
  NIL_NODE = ::Parser::AST::Node.new(:nil)
124
169
 
125
170
  # @param node [Parser::AST::Node]
@@ -148,7 +193,7 @@ module Solargraph
148
193
  end
149
194
 
150
195
  # @param nodes [Enumerable<Parser::AST::Node>]
151
- def any_splatted_call?(nodes)
196
+ def any_splatted_call? nodes
152
197
  nodes.any? { |n| splatted_call?(n) }
153
198
  end
154
199
 
@@ -161,14 +206,17 @@ module Solargraph
161
206
  if node.type == :block
162
207
  result.push node
163
208
  if Parser.is_ast_node?(node.children[0]) && node.children[0].children.length > 2
164
- node.children[0].children[2..-1].each { |child| result.concat call_nodes_from(child) }
209
+ # @sg-ignore Need to add nil check here
210
+ node.children[0].children[2..].each { |child| result.concat call_nodes_from(child) }
165
211
  end
166
- node.children[1..-1].each { |child| result.concat call_nodes_from(child) }
212
+ # @sg-ignore Need to add nil check here
213
+ node.children[1..].each { |child| result.concat call_nodes_from(child) }
167
214
  elsif node.type == :send
168
215
  result.push node
169
216
  result.concat call_nodes_from(node.children.first)
170
- node.children[2..-1].each { |child| result.concat call_nodes_from(child) }
171
- elsif [:super, :zsuper].include?(node.type)
217
+ # @sg-ignore Need to add nil check here
218
+ node.children[2..].each { |child| result.concat call_nodes_from(child) }
219
+ elsif %i[super zsuper].include?(node.type)
172
220
  result.push node
173
221
  node.children.each { |child| result.concat call_nodes_from(child) }
174
222
  else
@@ -199,53 +247,142 @@ module Solargraph
199
247
  # @return [Array<AST::Node>] low-level value nodes in
200
248
  # value position. Does not include explicit return
201
249
  # statements
202
- def value_position_nodes_only(node)
250
+ def value_position_nodes_only node
203
251
  DeepInference.value_position_nodes_only(node).map { |n| n || NIL_NODE }
204
252
  end
205
253
 
206
254
  # @param cursor [Solargraph::Source::Cursor]
207
255
  # @return [Parser::AST::Node, nil]
208
256
  def find_recipient_node cursor
209
- return repaired_find_recipient_node(cursor) if cursor.source.repaired? && cursor.source.code[cursor.offset - 1] == '('
257
+ if cursor.source.repaired? && cursor.source.code[cursor.offset - 1] == '('
258
+ return repaired_find_recipient_node(cursor)
259
+ end
210
260
  source = cursor.source
211
261
  position = cursor.position
212
262
  offset = cursor.offset
213
263
  tree = if source.synchronized?
214
- match = source.code[0..offset-1].match(/,\s*\z/)
215
- if match
216
- source.tree_at(position.line, position.column - match[0].length)
217
- else
218
- source.tree_at(position.line, position.column)
219
- end
220
- else
221
- source.tree_at(position.line, position.column - 1)
222
- end
264
+ # @sg-ignore Need to add nil check here
265
+ match = source.code[0..(offset - 1)].match(/,\s*\z/)
266
+ if match
267
+ # @sg-ignore Need to add nil check here
268
+ source.tree_at(position.line, position.column - match[0].length)
269
+ else
270
+ source.tree_at(position.line, position.column)
271
+ end
272
+ else
273
+ source.tree_at(position.line, position.column - 1)
274
+ end
223
275
  # @type [AST::Node, nil]
224
276
  prev = nil
225
277
  tree.each do |node|
226
278
  if node.type == :send
227
- args = node.children[2..-1]
279
+ args = node.children[2..]
280
+ # @sg-ignore Need to add nil check here
228
281
  if !args.empty?
282
+ # @sg-ignore Need to add nil check here
229
283
  return node if prev && args.include?(prev)
230
- else
231
- if source.synchronized?
232
- return node if source.code[0..offset-1] =~ /\(\s*\z/ && source.code[offset..-1] =~ /^\s*\)/
233
- else
234
- return node if source.code[0..offset-1] =~ /\([^(]*\z/
235
- end
284
+ elsif source.synchronized?
285
+ return node if source.code[0..(offset - 1)] =~ /\(\s*\z/ && source.code[offset..] =~ /^\s*\)/
286
+ elsif source.code[0..(offset - 1)] =~ /\([^(]*\z/
287
+ return node
236
288
  end
237
289
  end
238
290
  prev = node
239
291
  end
240
- nil
292
+ find_recipient_node_by_text(source, offset)
293
+ end
294
+
295
+ # Text-based fallback for finding a method call recipient when the AST
296
+ # is unavailable (e.g., unparseable source with syntax errors).
297
+ #
298
+ # Scans backward from cursor offset to find '(' and the method name
299
+ # before it, then creates a minimal :send node.
300
+ #
301
+ # @param source [Solargraph::Source]
302
+ # @param offset [Integer]
303
+ # @return [Parser::AST::Node, nil]
304
+ def find_recipient_node_by_text source, offset
305
+ code = source.code
306
+ return nil if offset.nil? || offset <= 0 || offset > code.length
307
+
308
+ # The '(' could be at offset-1 (cursor after '(') or at offset (cursor on '(')
309
+ start_pos = offset - 1
310
+ if start_pos.positive? && code[start_pos] != '(' && code[offset] == '('
311
+ start_pos = offset
312
+ end
313
+
314
+ # Scan backward to find the matching '(' (handle nested parens)
315
+ depth = 0
316
+ paren_pos = nil
317
+ pos = start_pos
318
+ while pos >= 0
319
+ case code[pos]
320
+ when ')'
321
+ depth += 1
322
+ when '('
323
+ if depth.zero?
324
+ paren_pos = pos
325
+ break
326
+ end
327
+ depth -= 1
328
+ end
329
+ pos -= 1
330
+ end
331
+ return nil if paren_pos.nil?
332
+
333
+ # Skip whitespace before '(' to find method name
334
+ idx = paren_pos - 1
335
+ idx -= 1 while idx >= 0 && code[idx] =~ /\s/
336
+ return nil if idx.negative?
337
+
338
+ # Read method name (including ? and !)
339
+ name_end = idx + 1
340
+ idx -= 1 while idx >= 0 && code[idx] =~ /[a-zA-Z0-9_?!]/
341
+ name_start = idx + 1
342
+ return nil if name_start >= name_end
343
+ method_name = code[name_start...name_end]
344
+ return nil if method_name.empty?
345
+
346
+ # Check for receiver pattern: receiver.method( or receiver::method(
347
+ idx = name_start - 1
348
+ idx -= 1 while idx >= 0 && code[idx] =~ /\s/
349
+ if idx >= 0 && code[idx] == '.'
350
+ idx -= 1
351
+ idx -= 1 while idx >= 0 && code[idx] =~ /\s/
352
+ recv_end = idx + 1
353
+ idx -= 1 while idx >= 0 && code[idx] =~ /[a-zA-Z0-9_@$]/
354
+ recv_start = idx + 1
355
+ if recv_start < recv_end
356
+ recv_name = code[recv_start...recv_end]
357
+ unless recv_name.empty?
358
+ receiver_node = ::Parser::AST::Node.new(:send, [nil, recv_name.to_sym])
359
+ return ::Parser::AST::Node.new(:send, [receiver_node, method_name.to_sym])
360
+ end
361
+ end
362
+ elsif idx >= 0 && idx.positive? && code[idx - 1] == ':' && code[idx] == ':'
363
+ const_end = idx - 1
364
+ const_start = const_end
365
+ const_start -= 1 while const_start.positive? && code[const_start - 1] =~ /[a-zA-Z0-9_]/
366
+ const_name = code[const_start...const_end]
367
+ unless const_name.empty? || method_name.empty?
368
+ const_node = ::Parser::AST::Node.new(:const, [nil, const_name.to_sym])
369
+ return ::Parser::AST::Node.new(:send, [const_node, method_name.to_sym])
370
+ end
371
+ end
372
+
373
+ # Simple method call without receiver
374
+ ::Parser::AST::Node.new(:send, [nil, method_name.to_sym])
241
375
  end
242
376
 
243
377
  # @param cursor [Solargraph::Source::Cursor]
244
378
  # @return [Parser::AST::Node, nil]
245
379
  def repaired_find_recipient_node cursor
246
- cursor = cursor.source.cursor_at([cursor.position.line, cursor.position.column - 1])
247
- node = cursor.source.tree_at(cursor.position.line, cursor.position.column).first
248
- return node if node && node.type == :send
380
+ c = cursor.source.cursor_at([cursor.position.line, cursor.position.column - 1])
381
+ tree = c.source.tree_at(c.position.line, c.position.column)
382
+ tree.each do |node|
383
+ return node if node.type == :send
384
+ end
385
+ find_recipient_node_by_text(cursor.source, cursor.offset)
249
386
  end
250
387
 
251
388
  #
@@ -302,19 +439,15 @@ module Solargraph
302
439
  # statements in value positions.
303
440
  module DeepInference
304
441
  class << self
305
- CONDITIONAL_ALL_BUT_FIRST = [:if, :unless]
306
- CONDITIONAL_ALL = [:or]
307
- ONLY_ONE_CHILD = [:return]
308
- FIRST_TWO_CHILDREN = [:rescue]
309
- COMPOUND_STATEMENTS = [:begin, :kwbegin]
310
- SKIPPABLE = [:def, :defs, :class, :sclass, :module]
311
- FUNCTION_VALUE = [:block]
312
- CASE_STATEMENT = [:case]
442
+ CONDITIONAL_ALL_BUT_FIRST = %i[if unless].freeze
443
+ ONLY_ONE_CHILD = [:return].freeze
444
+ FIRST_TWO_CHILDREN = [:rescue].freeze
445
+ COMPOUND_STATEMENTS = %i[begin kwbegin].freeze
446
+ SKIPPABLE = %i[def defs class sclass module].freeze
447
+ FUNCTION_VALUE = [:block].freeze
448
+ CASE_STATEMENT = [:case].freeze
313
449
 
314
450
  # @param node [AST::Node] a method body compound statement
315
- # @param include_explicit_returns [Boolean] If true,
316
- # include the value nodes of the parameter of the
317
- # 'return' statements in the type returned.
318
451
  # @return [Array<AST::Node>] low-level value nodes from
319
452
  # both nodes in value position as well as explicit
320
453
  # return statements in the method's closure.
@@ -327,14 +460,14 @@ module Solargraph
327
460
  # @return [Array<AST::Node>] low-level value nodes in
328
461
  # value position. Does not include explicit return
329
462
  # statements
330
- def value_position_nodes_only(node)
463
+ def value_position_nodes_only node
331
464
  from_value_position_statement(node, include_explicit_returns: false)
332
465
  end
333
466
 
334
467
  # Look at known control statements and use them to find
335
468
  # more specific return nodes.
336
469
  #
337
- # @param node [Parser::AST::Node] Statement which is in
470
+ # @param node [AST::Node] Statement which is in
338
471
  # value position for a method body
339
472
  # @param include_explicit_returns [Boolean] If true,
340
473
  # include the value nodes of the parameter of the
@@ -348,10 +481,9 @@ module Solargraph
348
481
  if COMPOUND_STATEMENTS.include?(node.type)
349
482
  result.concat from_value_position_compound_statement node
350
483
  elsif CONDITIONAL_ALL_BUT_FIRST.include?(node.type)
351
- result.concat reduce_to_value_nodes(node.children[1..-1])
484
+ # @sg-ignore Need to add nil check here
485
+ result.concat reduce_to_value_nodes(node.children[1..])
352
486
  # result.push NIL_NODE unless node.children[2]
353
- elsif CONDITIONAL_ALL.include?(node.type)
354
- result.concat reduce_to_value_nodes(node.children)
355
487
  elsif ONLY_ONE_CHILD.include?(node.type)
356
488
  result.concat reduce_to_value_nodes([node.children[0]])
357
489
  elsif FIRST_TWO_CHILDREN.include?(node.type)
@@ -362,9 +494,12 @@ module Solargraph
362
494
  # @todo any explicit returns actually return from
363
495
  # scope in which the proc is run. This asssumes
364
496
  # that the function is executed here.
365
- result.concat explicit_return_values_from_compound_statement(node.children[2]) if include_explicit_returns
497
+ if include_explicit_returns
498
+ result.concat explicit_return_values_from_compound_statement(node.children[2])
499
+ end
366
500
  elsif CASE_STATEMENT.include?(node.type)
367
- node.children[1..-1].each do |cc|
501
+ # @sg-ignore Need to add nil check here
502
+ node.children[1..].each do |cc|
368
503
  if cc.nil?
369
504
  result.push NIL_NODE
370
505
  elsif cc.type == :when
@@ -397,7 +532,7 @@ module Solargraph
397
532
  # @return [Array<Parser::AST::Node>]
398
533
  def from_value_position_compound_statement parent
399
534
  result = []
400
- nodes = parent.children.select{|n| n.is_a?(AST::Node)}
535
+ nodes = parent.children.select { |n| n.is_a?(AST::Node) }
401
536
  nodes.each_with_index do |node, idx|
402
537
  if node.type == :block
403
538
  result.concat explicit_return_values_from_compound_statement(node.children[2])
@@ -422,7 +557,10 @@ module Solargraph
422
557
  # value position. we already have the explicit values
423
558
  # from above; now we need to also gather the value
424
559
  # position nodes
425
- result.concat from_value_position_statement(nodes.last, include_explicit_returns: false) if idx == nodes.length - 1
560
+ if idx == nodes.length - 1
561
+ result.concat from_value_position_statement(nodes.last,
562
+ include_explicit_returns: false)
563
+ end
426
564
  end
427
565
  result
428
566
  end
@@ -438,7 +576,7 @@ module Solargraph
438
576
  def explicit_return_values_from_compound_statement parent
439
577
  return [] unless parent.is_a?(::Parser::AST::Node)
440
578
  result = []
441
- nodes = parent.children.select{|n| n.is_a?(::Parser::AST::Node)}
579
+ nodes = parent.children.select { |n| n.is_a?(::Parser::AST::Node) }
442
580
  nodes.each do |node|
443
581
  next if SKIPPABLE.include?(node.type)
444
582
  if node.type == :return
@@ -460,17 +598,28 @@ module Solargraph
460
598
  nodes.each do |node|
461
599
  if !node.is_a?(::Parser::AST::Node)
462
600
  result.push nil
601
+ # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
463
602
  elsif COMPOUND_STATEMENTS.include?(node.type)
464
603
  result.concat from_value_position_compound_statement(node)
604
+ # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
465
605
  elsif CONDITIONAL_ALL_BUT_FIRST.include?(node.type)
466
- result.concat reduce_to_value_nodes(node.children[1..-1])
606
+ # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
607
+ result.concat reduce_to_value_nodes(node.children[1..])
608
+ # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
467
609
  elsif node.type == :return
610
+ # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
468
611
  result.concat reduce_to_value_nodes([node.children[0]])
612
+ # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
469
613
  elsif node.type == :or
614
+ # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
470
615
  result.concat reduce_to_value_nodes(node.children)
616
+ # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
471
617
  elsif node.type == :block
618
+ # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
472
619
  result.concat explicit_return_values_from_compound_statement(node.children[2])
620
+ # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
473
621
  elsif node.type == :resbody
622
+ # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
474
623
  result.concat reduce_to_value_nodes([node.children[2]])
475
624
  else
476
625
  result.push node
@@ -484,3 +633,4 @@ module Solargraph
484
633
  end
485
634
  end
486
635
  end
636
+ # rubocop:enable Metrics/ModuleLength
@@ -1,24 +1,24 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module Parser
5
- module ParserGem
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
- source: :parser
17
- )
18
- process_children
19
- end
20
- end
21
- end
22
- end
23
- end
24
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Parser
5
+ module ParserGem
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
+ source: :parser
17
+ )
18
+ process_children
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -10,10 +10,10 @@ module Solargraph
10
10
  def process
11
11
  process_children
12
12
 
13
- position = get_node_start_position(node)
14
- # @sg-ignore https://github.com/castwide/solargraph/pull/1114
15
- enclosing_breakable_pin = pins.select{|pin| pin.is_a?(Pin::Breakable) && pin.location.range.contain?(position)}.last
16
- FlowSensitiveTyping.new(locals, enclosing_breakable_pin).process_and(node)
13
+ FlowSensitiveTyping.new(locals,
14
+ ivars,
15
+ enclosing_breakable_pin,
16
+ enclosing_compound_statement_pin).process_and(node)
17
17
  end
18
18
  end
19
19
  end
@@ -14,16 +14,17 @@ module Solargraph
14
14
  node.children.each do |u|
15
15
  loc = get_node_location(u)
16
16
  locals.push Solargraph::Pin::Parameter.new(
17
- location: loc,
18
- closure: callable,
19
- comments: comments_for(node),
20
- name: u.children[0].to_s,
21
- assignment: u.children[1],
22
- asgn_code: u.children[1] ? region.code_for(u.children[1]) : nil,
23
- presence: callable.location.range,
24
- decl: get_decl(u),
25
- source: :parser
26
- )
17
+ location: loc,
18
+ closure: callable,
19
+ comments: comments_for(node),
20
+ name: u.children[0].to_s,
21
+ assignment: u.children[1],
22
+ asgn_code: u.children[1] ? region.code_for(u.children[1]) : nil,
23
+ # @sg-ignore Need to add nil check here
24
+ presence: callable.location.range,
25
+ decl: get_decl(u),
26
+ source: :parser
27
+ )
27
28
  callable.parameters.push locals.last
28
29
  end
29
30
  end
@@ -35,11 +36,12 @@ module Solargraph
35
36
 
36
37
  # @param callable [Pin::Callable]
37
38
  # @return [void]
38
- def forward(callable)
39
+ def forward callable
39
40
  loc = get_node_location(node)
40
41
  locals.push Solargraph::Pin::Parameter.new(
41
42
  location: loc,
42
43
  closure: callable,
44
+ # @sg-ignore Need to add nil check here
43
45
  presence: region.closure.location.range,
44
46
  decl: get_decl(node),
45
47
  source: :parser
@@ -6,6 +6,15 @@ module Solargraph
6
6
  module NodeProcessors
7
7
  class BeginNode < Parser::NodeProcessor::Base
8
8
  def process
9
+ # We intentionally don't create a CompoundStatement pin
10
+ # here, as this is not necessarily a control flow block -
11
+ # e.g., a begin...end without rescue or ensure should be
12
+ # treated by flow sensitive typing as if the begin and end
13
+ # didn't exist at all. As such, we create the
14
+ # CompoundStatement pins around the things which actually
15
+ # result in control flow changes - like
16
+ # if/while/rescue/etc
17
+
9
18
  process_children
10
19
  end
11
20
  end