solargraph 0.59.0 → 0.59.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linting.yml +6 -0
  3. data/.github/workflows/plugins.yml +9 -1
  4. data/.github/workflows/typecheck.yml +3 -1
  5. data/CHANGELOG.md +12 -0
  6. data/lib/solargraph/api_map/store.rb +1 -2
  7. data/lib/solargraph/api_map.rb +4 -6
  8. data/lib/solargraph/complex_type/type_methods.rb +1 -0
  9. data/lib/solargraph/complex_type/unique_type.rb +14 -15
  10. data/lib/solargraph/complex_type.rb +2 -1
  11. data/lib/solargraph/convention/active_support_concern.rb +111 -111
  12. data/lib/solargraph/convention/base.rb +50 -50
  13. data/lib/solargraph/diagnostics.rb +55 -55
  14. data/lib/solargraph/environ.rb +52 -52
  15. data/lib/solargraph/gem_pins.rb +0 -11
  16. data/lib/solargraph/language_server/host.rb +6 -7
  17. data/lib/solargraph/language_server/message/extended/environment.rb +25 -25
  18. data/lib/solargraph/language_server/message/initialized.rb +28 -28
  19. data/lib/solargraph/language_server/message/text_document.rb +28 -28
  20. data/lib/solargraph/language_server/progress.rb +143 -143
  21. data/lib/solargraph/language_server/transport/adapter.rb +68 -68
  22. data/lib/solargraph/language_server.rb +20 -20
  23. data/lib/solargraph/parser/parser_gem/node_chainer.rb +1 -0
  24. data/lib/solargraph/parser/parser_gem/node_methods.rb +91 -4
  25. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +24 -24
  26. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +36 -36
  27. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +24 -24
  28. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +24 -24
  29. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +40 -40
  30. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +20 -20
  31. data/lib/solargraph/pin/base.rb +3 -3
  32. data/lib/solargraph/pin/method.rb +2 -0
  33. data/lib/solargraph/pin/parameter.rb +3 -1
  34. data/lib/solargraph/pin/reference/require.rb +14 -14
  35. data/lib/solargraph/pin/search.rb +5 -5
  36. data/lib/solargraph/pin/singleton.rb +11 -11
  37. data/lib/solargraph/rbs_map/conversions.rb +15 -8
  38. data/lib/solargraph/shell.rb +1 -1
  39. data/lib/solargraph/source/chain/array.rb +1 -12
  40. data/lib/solargraph/source/chain/block_symbol.rb +13 -13
  41. data/lib/solargraph/source/chain/block_variable.rb +13 -13
  42. data/lib/solargraph/source/chain/head.rb +19 -19
  43. data/lib/solargraph/source/chain/literal.rb +18 -14
  44. data/lib/solargraph/source/cursor.rb +11 -2
  45. data/lib/solargraph/source/source_chainer.rb +4 -4
  46. data/lib/solargraph/source_map/clip.rb +6 -1
  47. data/lib/solargraph/type_checker.rb +4 -4
  48. data/lib/solargraph/version.rb +1 -1
  49. data/lib/solargraph/yard_map/cache.rb +25 -25
  50. data/lib/solargraph/yard_map/mapper/to_constant.rb +28 -28
  51. data/lib/solargraph/yard_map/mapper/to_method.rb +1 -1
  52. data/lib/solargraph.rb +2 -2
  53. metadata +1 -2
  54. data/rbs/fills/tuple/tuple.rbs +0 -177
@@ -1,143 +1,143 @@
1
- # frozen_string_literal: true
2
-
3
- require 'securerandom'
4
-
5
- module Solargraph
6
- module LanguageServer
7
- # Progress notification handling for language server hosts.
8
- #
9
- class Progress
10
- WAITING = :waiting
11
- CREATED = :created
12
- FINISHED = :finished
13
-
14
- # @return [String]
15
- attr_reader :uuid
16
-
17
- # @return [String]
18
- attr_reader :title
19
-
20
- # @return [String, nil]
21
- attr_reader :kind
22
-
23
- # @return [String, nil]
24
- attr_reader :message
25
-
26
- # @return [Integer]
27
- attr_reader :percentage
28
-
29
- # @return [Symbol]
30
- attr_reader :status
31
-
32
- # @param title [String]
33
- def initialize title
34
- @title = title
35
- @uuid = SecureRandom.uuid
36
- @percentage = 0
37
- @status = WAITING
38
- end
39
-
40
- # @param message [String]
41
- # @param percentage [Integer]
42
- # @return [void]
43
- def begin message, percentage
44
- @kind = 'begin'
45
- @message = message
46
- @percentage = percentage
47
- end
48
-
49
- # @param message [String]
50
- # @param percentage [Integer]
51
- # @return [void]
52
- def report message, percentage
53
- @kind = 'report'
54
- @message = message
55
- @percentage = percentage
56
- end
57
-
58
- # @param message [String]
59
- # @return [void]
60
- def finish message
61
- @kind = 'end'
62
- @message = message
63
- @percentage = 100
64
- true
65
- end
66
-
67
- # @param host [Solargraph::LanguageServer::Host]
68
- # @return [void]
69
- def send host
70
- return unless host.client_supports_progress? && !finished?
71
-
72
- message = build
73
- create(host)
74
- host.send_notification '$/progress', message
75
- @status = FINISHED if kind == 'end'
76
- keep_alive host
77
- end
78
-
79
- def created?
80
- [CREATED, FINISHED].include?(status)
81
- end
82
-
83
- def finished?
84
- status == FINISHED
85
- end
86
-
87
- private
88
-
89
- # @param host [Solargraph::LanguageServer::Host]
90
- # @return [void]
91
- def create host
92
- return if created?
93
-
94
- host.send_request 'window/workDoneProgress/create', { token: uuid }
95
- @status = CREATED
96
- end
97
-
98
- # @return [Hash]
99
- def build
100
- {
101
- token: uuid,
102
- value: {
103
- kind: kind,
104
- cancellable: false
105
- }.merge(build_value)
106
- }
107
- end
108
-
109
- # @return [Hash]
110
- def build_value
111
- case kind
112
- when 'begin'
113
- { title: title, message: message, percentage: percentage }
114
- when 'report'
115
- { message: message, percentage: percentage }
116
- when 'end'
117
- { message: message }
118
- else
119
- raise "Invalid progress kind #{kind}"
120
- end
121
- end
122
-
123
- # @param host [Host]
124
- # @return [void]
125
- def keep_alive host
126
- mutex.synchronize { @last = Time.now }
127
- @keep_alive ||= Thread.new do
128
- until finished?
129
- sleep 10
130
- break if finished?
131
- next if mutex.synchronize { Time.now - @last < 10 }
132
- send host
133
- end
134
- end
135
- end
136
-
137
- # @return [Thread::Mutex]
138
- def mutex
139
- @mutex ||= Mutex.new
140
- end
141
- end
142
- end
143
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Solargraph
6
+ module LanguageServer
7
+ # Progress notification handling for language server hosts.
8
+ #
9
+ class Progress
10
+ WAITING = :waiting
11
+ CREATED = :created
12
+ FINISHED = :finished
13
+
14
+ # @return [String]
15
+ attr_reader :uuid
16
+
17
+ # @return [String]
18
+ attr_reader :title
19
+
20
+ # @return [String, nil]
21
+ attr_reader :kind
22
+
23
+ # @return [String, nil]
24
+ attr_reader :message
25
+
26
+ # @return [Integer]
27
+ attr_reader :percentage
28
+
29
+ # @return [Symbol]
30
+ attr_reader :status
31
+
32
+ # @param title [String]
33
+ def initialize title
34
+ @title = title
35
+ @uuid = SecureRandom.uuid
36
+ @percentage = 0
37
+ @status = WAITING
38
+ end
39
+
40
+ # @param message [String]
41
+ # @param percentage [Integer]
42
+ # @return [void]
43
+ def begin message, percentage
44
+ @kind = 'begin'
45
+ @message = message
46
+ @percentage = percentage
47
+ end
48
+
49
+ # @param message [String]
50
+ # @param percentage [Integer]
51
+ # @return [void]
52
+ def report message, percentage
53
+ @kind = 'report'
54
+ @message = message
55
+ @percentage = percentage
56
+ end
57
+
58
+ # @param message [String]
59
+ # @return [void]
60
+ def finish message
61
+ @kind = 'end'
62
+ @message = message
63
+ @percentage = 100
64
+ true
65
+ end
66
+
67
+ # @param host [Solargraph::LanguageServer::Host]
68
+ # @return [void]
69
+ def send host
70
+ return unless host.client_supports_progress? && !finished?
71
+
72
+ message = build
73
+ create(host)
74
+ host.send_notification '$/progress', message
75
+ @status = FINISHED if kind == 'end'
76
+ keep_alive host
77
+ end
78
+
79
+ def created?
80
+ [CREATED, FINISHED].include?(status)
81
+ end
82
+
83
+ def finished?
84
+ status == FINISHED
85
+ end
86
+
87
+ private
88
+
89
+ # @param host [Solargraph::LanguageServer::Host]
90
+ # @return [void]
91
+ def create host
92
+ return if created?
93
+
94
+ host.send_request 'window/workDoneProgress/create', { token: uuid }
95
+ @status = CREATED
96
+ end
97
+
98
+ # @return [Hash]
99
+ def build
100
+ {
101
+ token: uuid,
102
+ value: {
103
+ kind: kind,
104
+ cancellable: false
105
+ }.merge(build_value)
106
+ }
107
+ end
108
+
109
+ # @return [Hash]
110
+ def build_value
111
+ case kind
112
+ when 'begin'
113
+ { title: title, message: message, percentage: percentage }
114
+ when 'report'
115
+ { message: message, percentage: percentage }
116
+ when 'end'
117
+ { message: message }
118
+ else
119
+ raise "Invalid progress kind #{kind}"
120
+ end
121
+ end
122
+
123
+ # @param host [Host]
124
+ # @return [void]
125
+ def keep_alive host
126
+ mutex.synchronize { @last = Time.now }
127
+ @keep_alive ||= Thread.new do
128
+ until finished?
129
+ sleep 10
130
+ break if finished?
131
+ next if mutex.synchronize { Time.now - @last < 10 }
132
+ send host
133
+ end
134
+ end
135
+ end
136
+
137
+ # @return [Thread::Mutex]
138
+ def mutex
139
+ @mutex ||= Mutex.new
140
+ end
141
+ end
142
+ end
143
+ end
@@ -1,68 +1,68 @@
1
- # frozen_string_literal: true
2
-
3
- require 'backport'
4
-
5
- module Solargraph
6
- module LanguageServer
7
- module Transport
8
- # A common module for running language servers in Backport.
9
- #
10
- module Adapter
11
- # This runs in the context of Backport::Adapter, which
12
- # provides write() - but if we didn't hide this behind a parse
13
- # tag, it would override the one in the class.
14
- #
15
- # @!method write(text)
16
- # @abstract
17
- # Write the change to the specified text.
18
- # @param text [String] The text to be changed.
19
- # @return [String] The updated text.
20
-
21
- # @return [void]
22
- def opening
23
- @host = Solargraph::LanguageServer::Host.new
24
- @host.add_observer self
25
- @host.start
26
- @data_reader = Solargraph::LanguageServer::Transport::DataReader.new
27
- @data_reader.set_message_handler do |message|
28
- process message
29
- end
30
- end
31
-
32
- # @return [void]
33
- def closing
34
- @host.stop
35
- end
36
-
37
- # @param data [String]
38
- # @return [void]
39
- def receiving data
40
- @data_reader.receive data
41
- end
42
-
43
- # @return [void]
44
- def update
45
- if @host.stopped?
46
- shutdown
47
- else
48
- tmp = @host.flush
49
- write tmp unless tmp.empty?
50
- end
51
- end
52
-
53
- private
54
-
55
- # @param request [Hash]
56
- # @return [void]
57
- def process request
58
- @host.process(request)
59
- end
60
-
61
- # @return [void]
62
- def shutdown
63
- Backport.stop unless @host.options['transport'] == 'external'
64
- end
65
- end
66
- end
67
- end
68
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'backport'
4
+
5
+ module Solargraph
6
+ module LanguageServer
7
+ module Transport
8
+ # A common module for running language servers in Backport.
9
+ #
10
+ module Adapter
11
+ # This runs in the context of Backport::Adapter, which
12
+ # provides write() - but if we didn't hide this behind a parse
13
+ # tag, it would override the one in the class.
14
+ #
15
+ # @!method write(text)
16
+ # @abstract
17
+ # Write the change to the specified text.
18
+ # @param text [String] The text to be changed.
19
+ # @return [String] The updated text.
20
+
21
+ # @return [void]
22
+ def opening
23
+ @host = Solargraph::LanguageServer::Host.new
24
+ @host.add_observer self
25
+ @host.start
26
+ @data_reader = Solargraph::LanguageServer::Transport::DataReader.new
27
+ @data_reader.set_message_handler do |message|
28
+ process message
29
+ end
30
+ end
31
+
32
+ # @return [void]
33
+ def closing
34
+ @host.stop
35
+ end
36
+
37
+ # @param data [String]
38
+ # @return [void]
39
+ def receiving data
40
+ @data_reader.receive data
41
+ end
42
+
43
+ # @return [void]
44
+ def update
45
+ if @host.stopped?
46
+ shutdown
47
+ else
48
+ tmp = @host.flush
49
+ write tmp unless tmp.empty?
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ # @param request [Hash]
56
+ # @return [void]
57
+ def process request
58
+ @host.process(request)
59
+ end
60
+
61
+ # @return [void]
62
+ def shutdown
63
+ Backport.stop unless @host.options['transport'] == 'external'
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -1,20 +1,20 @@
1
- # frozen_string_literal: true
2
-
3
- require 'solargraph/language_server/error_codes'
4
- require 'solargraph/language_server/completion_item_kinds'
5
- require 'solargraph/language_server/symbol_kinds'
6
-
7
- module Solargraph
8
- # The LanguageServer namespace contains the classes and modules that compose
9
- # concrete implementations of language servers.
10
- #
11
- module LanguageServer
12
- autoload :Host, 'solargraph/language_server/host'
13
- autoload :Message, 'solargraph/language_server/message'
14
- autoload :UriHelpers, 'solargraph/language_server/uri_helpers'
15
- autoload :MessageTypes, 'solargraph/language_server/message_types'
16
- autoload :Request, 'solargraph/language_server/request'
17
- autoload :Transport, 'solargraph/language_server/transport'
18
- autoload :Progress, 'solargraph/language_server/progress'
19
- end
20
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'solargraph/language_server/error_codes'
4
+ require 'solargraph/language_server/completion_item_kinds'
5
+ require 'solargraph/language_server/symbol_kinds'
6
+
7
+ module Solargraph
8
+ # The LanguageServer namespace contains the classes and modules that compose
9
+ # concrete implementations of language servers.
10
+ #
11
+ module LanguageServer
12
+ autoload :Host, 'solargraph/language_server/host'
13
+ autoload :Message, 'solargraph/language_server/message'
14
+ autoload :UriHelpers, 'solargraph/language_server/uri_helpers'
15
+ autoload :MessageTypes, 'solargraph/language_server/message_types'
16
+ autoload :Request, 'solargraph/language_server/request'
17
+ autoload :Transport, 'solargraph/language_server/transport'
18
+ autoload :Progress, 'solargraph/language_server/progress'
19
+ end
20
+ end
@@ -153,6 +153,7 @@ module Solargraph
153
153
  else
154
154
  lit = infer_literal_node_type(n)
155
155
  result.push(lit ? Chain::Literal.new(lit, n) : Chain::Link.new)
156
+ # result.push Chain::Link.new
156
157
  end
157
158
  result
158
159
  end
@@ -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
@@ -246,15 +247,100 @@ module Solargraph
246
247
  end
247
248
  prev = node
248
249
  end
249
- nil
250
+ find_recipient_node_by_text(source, offset)
251
+ end
252
+
253
+ # Text-based fallback for finding a method call recipient when the AST
254
+ # is unavailable (e.g., unparseable source with syntax errors).
255
+ #
256
+ # Scans backward from cursor offset to find '(' and the method name
257
+ # before it, then creates a minimal :send node.
258
+ #
259
+ # @param source [Solargraph::Source]
260
+ # @param offset [Integer]
261
+ # @return [Parser::AST::Node, nil]
262
+ def find_recipient_node_by_text source, offset
263
+ code = source.code
264
+ return nil if offset.nil? || offset <= 0 || offset > code.length
265
+
266
+ # The '(' could be at offset-1 (cursor after '(') or at offset (cursor on '(')
267
+ start_pos = offset - 1
268
+ if start_pos.positive? && code[start_pos] != '(' && code[offset] == '('
269
+ start_pos = offset
270
+ end
271
+
272
+ # Scan backward to find the matching '(' (handle nested parens)
273
+ depth = 0
274
+ paren_pos = nil
275
+ pos = start_pos
276
+ while pos >= 0
277
+ case code[pos]
278
+ when ')'
279
+ depth += 1
280
+ when '('
281
+ if depth.zero?
282
+ paren_pos = pos
283
+ break
284
+ end
285
+ depth -= 1
286
+ end
287
+ pos -= 1
288
+ end
289
+ return nil if paren_pos.nil?
290
+
291
+ # Skip whitespace before '(' to find method name
292
+ idx = paren_pos - 1
293
+ idx -= 1 while idx >= 0 && code[idx] =~ /\s/
294
+ return nil if idx.negative?
295
+
296
+ # Read method name (including ? and !)
297
+ name_end = idx + 1
298
+ idx -= 1 while idx >= 0 && code[idx] =~ /[a-zA-Z0-9_?!]/
299
+ name_start = idx + 1
300
+ return nil if name_start >= name_end
301
+ method_name = code[name_start...name_end]
302
+ return nil if method_name.empty?
303
+
304
+ # Check for receiver pattern: receiver.method( or receiver::method(
305
+ idx = name_start - 1
306
+ idx -= 1 while idx >= 0 && code[idx] =~ /\s/
307
+ if idx >= 0 && code[idx] == '.'
308
+ idx -= 1
309
+ idx -= 1 while idx >= 0 && code[idx] =~ /\s/
310
+ recv_end = idx + 1
311
+ idx -= 1 while idx >= 0 && code[idx] =~ /[a-zA-Z0-9_@$]/
312
+ recv_start = idx + 1
313
+ if recv_start < recv_end
314
+ recv_name = code[recv_start...recv_end]
315
+ unless recv_name.empty?
316
+ receiver_node = ::Parser::AST::Node.new(:send, [nil, recv_name.to_sym])
317
+ return ::Parser::AST::Node.new(:send, [receiver_node, method_name.to_sym])
318
+ end
319
+ end
320
+ elsif idx >= 0 && idx.positive? && code[idx - 1] == ':' && code[idx] == ':'
321
+ const_end = idx - 1
322
+ const_start = const_end
323
+ const_start -= 1 while const_start.positive? && code[const_start - 1] =~ /[a-zA-Z0-9_]/
324
+ const_name = code[const_start...const_end]
325
+ unless const_name.empty? || method_name.empty?
326
+ const_node = ::Parser::AST::Node.new(:const, [nil, const_name.to_sym])
327
+ return ::Parser::AST::Node.new(:send, [const_node, method_name.to_sym])
328
+ end
329
+ end
330
+
331
+ # Simple method call without receiver
332
+ ::Parser::AST::Node.new(:send, [nil, method_name.to_sym])
250
333
  end
251
334
 
252
335
  # @param cursor [Solargraph::Source::Cursor]
253
336
  # @return [Parser::AST::Node, nil]
254
337
  def repaired_find_recipient_node cursor
255
- cursor = cursor.source.cursor_at([cursor.position.line, cursor.position.column - 1])
256
- node = cursor.source.tree_at(cursor.position.line, cursor.position.column).first
257
- node if node && node.type == :send
338
+ c = cursor.source.cursor_at([cursor.position.line, cursor.position.column - 1])
339
+ tree = c.source.tree_at(c.position.line, c.position.column)
340
+ tree.each do |node|
341
+ return node if node.type == :send
342
+ end
343
+ find_recipient_node_by_text(cursor.source, cursor.offset)
258
344
  end
259
345
 
260
346
  #
@@ -505,3 +591,4 @@ module Solargraph
505
591
  end
506
592
  end
507
593
  end
594
+ # 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