ruby-lsp 0.14.6 → 0.16.5

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/VERSION +1 -1
  4. data/exe/ruby-lsp +1 -16
  5. data/exe/ruby-lsp-check +13 -22
  6. data/exe/ruby-lsp-doctor +9 -0
  7. data/lib/ruby_indexer/lib/ruby_indexer/collector.rb +14 -1
  8. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +11 -23
  9. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +32 -8
  10. data/lib/ruby_indexer/lib/ruby_indexer/location.rb +26 -0
  11. data/lib/ruby_indexer/ruby_indexer.rb +1 -0
  12. data/lib/ruby_indexer/test/classes_and_modules_test.rb +46 -0
  13. data/lib/ruby_indexer/test/configuration_test.rb +2 -11
  14. data/lib/ruby_lsp/addon.rb +18 -9
  15. data/lib/ruby_lsp/base_server.rb +149 -0
  16. data/lib/ruby_lsp/document.rb +6 -11
  17. data/lib/ruby_lsp/global_state.rb +180 -0
  18. data/lib/ruby_lsp/internal.rb +4 -1
  19. data/lib/ruby_lsp/listeners/code_lens.rb +22 -13
  20. data/lib/ruby_lsp/listeners/completion.rb +13 -14
  21. data/lib/ruby_lsp/listeners/definition.rb +14 -6
  22. data/lib/ruby_lsp/listeners/document_symbol.rb +91 -3
  23. data/lib/ruby_lsp/listeners/hover.rb +6 -5
  24. data/lib/ruby_lsp/listeners/signature_help.rb +7 -4
  25. data/lib/ruby_lsp/load_sorbet.rb +62 -0
  26. data/lib/ruby_lsp/requests/code_lens.rb +3 -2
  27. data/lib/ruby_lsp/requests/completion.rb +15 -4
  28. data/lib/ruby_lsp/requests/completion_resolve.rb +56 -0
  29. data/lib/ruby_lsp/requests/definition.rb +11 -4
  30. data/lib/ruby_lsp/requests/diagnostics.rb +8 -11
  31. data/lib/ruby_lsp/requests/document_symbol.rb +3 -3
  32. data/lib/ruby_lsp/requests/formatting.rb +7 -43
  33. data/lib/ruby_lsp/requests/hover.rb +4 -4
  34. data/lib/ruby_lsp/requests/request.rb +2 -0
  35. data/lib/ruby_lsp/requests/semantic_highlighting.rb +7 -4
  36. data/lib/ruby_lsp/requests/signature_help.rb +4 -3
  37. data/lib/ruby_lsp/requests/support/common.rb +16 -5
  38. data/lib/ruby_lsp/requests/support/formatter.rb +26 -0
  39. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +1 -1
  40. data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +47 -0
  41. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +4 -0
  42. data/lib/ruby_lsp/requests/support/{syntax_tree_formatting_runner.rb → syntax_tree_formatter.rb} +13 -6
  43. data/lib/ruby_lsp/requests/workspace_symbol.rb +5 -4
  44. data/lib/ruby_lsp/requests.rb +3 -1
  45. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +36 -13
  46. data/lib/ruby_lsp/server.rb +763 -142
  47. data/lib/ruby_lsp/setup_bundler.rb +13 -1
  48. data/lib/ruby_lsp/store.rb +3 -15
  49. data/lib/ruby_lsp/test_helper.rb +52 -0
  50. data/lib/ruby_lsp/utils.rb +68 -33
  51. metadata +16 -13
  52. data/lib/ruby_lsp/executor.rb +0 -614
  53. data/lib/ruby_lsp/requests/support/dependency_detector.rb +0 -93
  54. data/lib/ruby_lsp/requests/support/formatter_runner.rb +0 -18
  55. data/lib/ruby_lsp/requests/support/rubocop_diagnostics_runner.rb +0 -34
  56. data/lib/ruby_lsp/requests/support/rubocop_formatting_runner.rb +0 -35
@@ -12,17 +12,20 @@ module RubyLsp
12
12
  sig do
13
13
  params(
14
14
  response_builder: ResponseBuilders::DocumentSymbol,
15
+ uri: URI::Generic,
15
16
  dispatcher: Prism::Dispatcher,
16
17
  ).void
17
18
  end
18
- def initialize(response_builder, dispatcher)
19
+ def initialize(response_builder, uri, dispatcher)
19
20
  @response_builder = response_builder
21
+ @uri = uri
20
22
 
21
23
  dispatcher.register(
22
24
  self,
23
25
  :on_class_node_enter,
24
26
  :on_class_node_leave,
25
27
  :on_call_node_enter,
28
+ :on_call_node_leave,
26
29
  :on_constant_path_write_node_enter,
27
30
  :on_constant_write_node_enter,
28
31
  :on_constant_path_or_write_node_enter,
@@ -79,10 +82,24 @@ module RubyLsp
79
82
 
80
83
  sig { params(node: Prism::CallNode).void }
81
84
  def on_call_node_enter(node)
82
- if ATTR_ACCESSORS.include?(node.name)
85
+ node_name = node.name
86
+ if ATTR_ACCESSORS.include?(node_name)
83
87
  handle_attr_accessor(node)
84
- elsif node.name == :alias_method
88
+ elsif node_name == :alias_method
85
89
  handle_alias_method(node)
90
+ elsif node_name == :namespace
91
+ handle_rake_namespace(node)
92
+ elsif node_name == :task
93
+ handle_rake_task(node)
94
+ end
95
+ end
96
+
97
+ sig { params(node: Prism::CallNode).void }
98
+ def on_call_node_leave(node)
99
+ return unless rake?
100
+
101
+ if node.name == :namespace && !node.receiver
102
+ @response_builder.pop
86
103
  end
87
104
  end
88
105
 
@@ -279,6 +296,7 @@ module RubyLsp
279
296
  ).returns(Interface::DocumentSymbol)
280
297
  end
281
298
  def create_document_symbol(name:, kind:, range_location:, selection_range_location:)
299
+ name = "<blank>" if name.empty?
282
300
  symbol = Interface::DocumentSymbol.new(
283
301
  name: name,
284
302
  kind: kind,
@@ -357,6 +375,76 @@ module RubyLsp
357
375
  )
358
376
  end
359
377
  end
378
+
379
+ sig { params(node: Prism::CallNode).void }
380
+ def handle_rake_namespace(node)
381
+ return unless rake?
382
+ return if node.receiver
383
+
384
+ arguments = node.arguments
385
+ return unless arguments
386
+
387
+ name_argument = arguments.arguments.first
388
+ return unless name_argument
389
+
390
+ name = case name_argument
391
+ when Prism::StringNode then name_argument.content
392
+ when Prism::SymbolNode then name_argument.value
393
+ end
394
+
395
+ return if name.nil? || name.empty?
396
+
397
+ @response_builder << create_document_symbol(
398
+ name: name,
399
+ kind: Constant::SymbolKind::MODULE,
400
+ range_location: name_argument.location,
401
+ selection_range_location: name_argument.location,
402
+ )
403
+ end
404
+
405
+ sig { params(node: Prism::CallNode).void }
406
+ def handle_rake_task(node)
407
+ return unless rake?
408
+ return if node.receiver
409
+
410
+ arguments = node.arguments
411
+ return unless arguments
412
+
413
+ name_argument = arguments.arguments.first
414
+ return unless name_argument
415
+
416
+ name = case name_argument
417
+ when Prism::StringNode then name_argument.content
418
+ when Prism::SymbolNode then name_argument.value
419
+ when Prism::KeywordHashNode
420
+ first_element = name_argument.elements.first
421
+ if first_element.is_a?(Prism::AssocNode)
422
+ key = first_element.key
423
+ case key
424
+ when Prism::StringNode then key.content
425
+ when Prism::SymbolNode then key.value
426
+ end
427
+ end
428
+ end
429
+
430
+ return if name.nil? || name.empty?
431
+
432
+ create_document_symbol(
433
+ name: name,
434
+ kind: Constant::SymbolKind::METHOD,
435
+ range_location: name_argument.location,
436
+ selection_range_location: name_argument.location,
437
+ )
438
+ end
439
+
440
+ sig { returns(T::Boolean) }
441
+ def rake?
442
+ if (path = @uri.to_standardized_path)
443
+ path.match?(/(Rakefile|\.rake)$/)
444
+ else
445
+ false
446
+ end
447
+ end
360
448
  end
361
449
  end
362
450
  end
@@ -28,18 +28,19 @@ module RubyLsp
28
28
  sig do
29
29
  params(
30
30
  response_builder: ResponseBuilders::Hover,
31
+ global_state: GlobalState,
31
32
  uri: URI::Generic,
32
33
  nesting: T::Array[String],
33
- index: RubyIndexer::Index,
34
34
  dispatcher: Prism::Dispatcher,
35
35
  typechecker_enabled: T::Boolean,
36
36
  ).void
37
37
  end
38
- def initialize(response_builder, uri, nesting, index, dispatcher, typechecker_enabled) # rubocop:disable Metrics/ParameterLists
38
+ def initialize(response_builder, global_state, uri, nesting, dispatcher, typechecker_enabled) # rubocop:disable Metrics/ParameterLists
39
39
  @response_builder = response_builder
40
+ @global_state = global_state
41
+ @index = T.let(global_state.index, RubyIndexer::Index)
40
42
  @path = T.let(uri.to_standardized_path, T.nilable(String))
41
43
  @nesting = nesting
42
- @index = index
43
44
  @typechecker_enabled = typechecker_enabled
44
45
 
45
46
  dispatcher.register(
@@ -63,14 +64,14 @@ module RubyLsp
63
64
 
64
65
  sig { params(node: Prism::ConstantWriteNode).void }
65
66
  def on_constant_write_node_enter(node)
66
- return if DependencyDetector.instance.typechecker
67
+ return if @global_state.typechecker
67
68
 
68
69
  generate_hover(node.name.to_s, node.name_loc)
69
70
  end
70
71
 
71
72
  sig { params(node: Prism::ConstantPathNode).void }
72
73
  def on_constant_path_node_enter(node)
73
- return if DependencyDetector.instance.typechecker
74
+ return if @global_state.typechecker
74
75
 
75
76
  name = constant_name(node)
76
77
  return if name.nil?
@@ -10,21 +10,24 @@ module RubyLsp
10
10
  sig do
11
11
  params(
12
12
  response_builder: ResponseBuilders::SignatureHelp,
13
+ global_state: GlobalState,
13
14
  nesting: T::Array[String],
14
- index: RubyIndexer::Index,
15
15
  dispatcher: Prism::Dispatcher,
16
+ typechecker_enabled: T::Boolean,
16
17
  ).void
17
18
  end
18
- def initialize(response_builder, nesting, index, dispatcher)
19
+ def initialize(response_builder, global_state, nesting, dispatcher, typechecker_enabled)
20
+ @typechecker_enabled = typechecker_enabled
19
21
  @response_builder = response_builder
22
+ @global_state = global_state
23
+ @index = T.let(global_state.index, RubyIndexer::Index)
20
24
  @nesting = nesting
21
- @index = index
22
25
  dispatcher.register(self, :on_call_node_enter)
23
26
  end
24
27
 
25
28
  sig { params(node: Prism::CallNode).void }
26
29
  def on_call_node_enter(node)
27
- return if DependencyDetector.instance.typechecker
30
+ return if @typechecker_enabled
28
31
  return unless self_receiver?(node)
29
32
 
30
33
  message = node.message
@@ -0,0 +1,62 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ require "sorbet-runtime"
5
+
6
+ begin
7
+ T::Configuration.default_checked_level = :never
8
+ # Suppresses call validation errors
9
+ T::Configuration.call_validation_error_handler = ->(*) {}
10
+ # Suppresses errors caused by T.cast, T.let, T.must, etc.
11
+ T::Configuration.inline_type_error_handler = ->(*) {}
12
+ # Suppresses errors caused by incorrect parameter ordering
13
+ T::Configuration.sig_validation_error_handler = ->(*) {}
14
+ rescue
15
+ # Need this rescue so that if another gem has
16
+ # already set the checked level by the time we
17
+ # get to it, we don't fail outright.
18
+ nil
19
+ end
20
+
21
+ module RubyLsp
22
+ # No-op all inline type assertions defined in T
23
+ module InlineTypeAssertions
24
+ def absurd(value)
25
+ value
26
+ end
27
+
28
+ def any(type_a, type_b, *types)
29
+ T::Types::Union.new([type_a, type_b, *types])
30
+ end
31
+
32
+ def assert_type!(value, type, checked: true)
33
+ value
34
+ end
35
+
36
+ def bind(value, type, checked: true)
37
+ value
38
+ end
39
+
40
+ def cast(value, type, checked: true)
41
+ value
42
+ end
43
+
44
+ def let(value, type, checked: true)
45
+ value
46
+ end
47
+
48
+ def must(arg)
49
+ arg
50
+ end
51
+
52
+ def nilable(type)
53
+ T::Types::Union.new([type, T::Utils::Nilable::NIL_TYPE])
54
+ end
55
+
56
+ def unsafe(value)
57
+ value
58
+ end
59
+
60
+ T.singleton_class.prepend(self)
61
+ end
62
+ end
@@ -34,17 +34,18 @@ module RubyLsp
34
34
 
35
35
  sig do
36
36
  params(
37
+ global_state: GlobalState,
37
38
  uri: URI::Generic,
38
39
  dispatcher: Prism::Dispatcher,
39
40
  ).void
40
41
  end
41
- def initialize(uri, dispatcher)
42
+ def initialize(global_state, uri, dispatcher)
42
43
  @response_builder = T.let(
43
44
  ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens].new,
44
45
  ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens],
45
46
  )
46
47
  super()
47
- Listeners::CodeLens.new(@response_builder, uri, dispatcher)
48
+ Listeners::CodeLens.new(@response_builder, global_state, uri, dispatcher)
48
49
 
49
50
  Addon.addons.each do |addon|
50
51
  addon.create_code_lens_listener(@response_builder, uri, dispatcher)
@@ -33,7 +33,7 @@ module RubyLsp
33
33
  sig { returns(Interface::CompletionOptions) }
34
34
  def provider
35
35
  Interface::CompletionOptions.new(
36
- resolve_provider: false,
36
+ resolve_provider: true,
37
37
  trigger_characters: ["/", "\"", "'"],
38
38
  completion_item: {
39
39
  labelDetailsSupport: true,
@@ -45,13 +45,13 @@ module RubyLsp
45
45
  sig do
46
46
  params(
47
47
  document: Document,
48
- index: RubyIndexer::Index,
48
+ global_state: GlobalState,
49
49
  position: T::Hash[Symbol, T.untyped],
50
50
  typechecker_enabled: T::Boolean,
51
51
  dispatcher: Prism::Dispatcher,
52
52
  ).void
53
53
  end
54
- def initialize(document, index, position, typechecker_enabled, dispatcher)
54
+ def initialize(document, global_state, position, typechecker_enabled, dispatcher)
55
55
  super()
56
56
  @target = T.let(nil, T.nilable(Prism::Node))
57
57
  @dispatcher = dispatcher
@@ -68,7 +68,18 @@ module RubyLsp
68
68
  ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem],
69
69
  )
70
70
 
71
- Listeners::Completion.new(@response_builder, index, nesting, typechecker_enabled, dispatcher, document.uri)
71
+ Listeners::Completion.new(
72
+ @response_builder,
73
+ global_state,
74
+ nesting,
75
+ typechecker_enabled,
76
+ dispatcher,
77
+ document.uri,
78
+ )
79
+
80
+ Addon.addons.each do |addon|
81
+ addon.create_completion_listener(@response_builder, nesting, dispatcher, document.uri)
82
+ end
72
83
 
73
84
  return unless matched && parent
74
85
 
@@ -0,0 +1,56 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RubyLsp
5
+ module Requests
6
+ # ![Completion resolve demo](../../completion_resolve.gif)
7
+ #
8
+ # The [completionItem/resolve](https://microsoft.github.io/language-server-protocol/specification#completionItem_resolve)
9
+ # request provides additional information about the currently selected completion. Specifically, the `labelDetails`
10
+ # and `documentation` fields are provided, which are omitted from the completion items returned by
11
+ # `textDocument/completion`.
12
+ #
13
+ # The `labelDetails` field lists the files where the completion item is defined, and the `documentation` field
14
+ # includes any available documentation for those definitions.
15
+ #
16
+ # At most 10 definitions are included, to ensure low latency during request processing and rendering the completion
17
+ # item.
18
+ #
19
+ # # Example
20
+ #
21
+ # ```ruby
22
+ # A # -> as the user cycles through completion items, the documentation will be resolved and displayed
23
+ # ```
24
+ class CompletionResolve < Request
25
+ extend T::Sig
26
+ include Requests::Support::Common
27
+
28
+ # set a limit on the number of documentation entries returned, to avoid rendering performance issues
29
+ # https://github.com/Shopify/ruby-lsp/pull/1798
30
+ MAX_DOCUMENTATION_ENTRIES = 10
31
+
32
+ sig { params(global_state: GlobalState, item: T::Hash[Symbol, T.untyped]).void }
33
+ def initialize(global_state, item)
34
+ super()
35
+ @index = T.let(global_state.index, RubyIndexer::Index)
36
+ @item = item
37
+ end
38
+
39
+ sig { override.returns(Interface::CompletionItem) }
40
+ def perform
41
+ label = @item[:label]
42
+ entries = @index[label] || []
43
+ Interface::CompletionItem.new(
44
+ label: label,
45
+ label_details: Interface::CompletionItemLabelDetails.new(
46
+ description: entries.take(MAX_DOCUMENTATION_ENTRIES).map(&:file_name).join(","),
47
+ ),
48
+ documentation: Interface::MarkupContent.new(
49
+ kind: "markdown",
50
+ value: markdown_from_index_entries(label, entries, MAX_DOCUMENTATION_ENTRIES),
51
+ ),
52
+ )
53
+ end
54
+ end
55
+ end
56
+ end
@@ -31,13 +31,13 @@ module RubyLsp
31
31
  sig do
32
32
  params(
33
33
  document: Document,
34
- index: RubyIndexer::Index,
34
+ global_state: GlobalState,
35
35
  position: T::Hash[Symbol, T.untyped],
36
36
  dispatcher: Prism::Dispatcher,
37
37
  typechecker_enabled: T::Boolean,
38
38
  ).void
39
39
  end
40
- def initialize(document, index, position, dispatcher, typechecker_enabled)
40
+ def initialize(document, global_state, position, dispatcher, typechecker_enabled)
41
41
  super()
42
42
  @response_builder = T.let(
43
43
  ResponseBuilders::CollectionResponseBuilder[Interface::Location].new,
@@ -57,10 +57,17 @@ module RubyLsp
57
57
  )
58
58
  end
59
59
 
60
- Listeners::Definition.new(@response_builder, document.uri, nesting, index, dispatcher, typechecker_enabled)
60
+ Listeners::Definition.new(
61
+ @response_builder,
62
+ global_state,
63
+ document.uri,
64
+ nesting,
65
+ dispatcher,
66
+ typechecker_enabled,
67
+ )
61
68
 
62
69
  Addon.addons.each do |addon|
63
- addon.create_definition_listener(@response_builder, document.uri, nesting, index, dispatcher)
70
+ addon.create_definition_listener(@response_builder, document.uri, nesting, dispatcher)
64
71
  end
65
72
 
66
73
  @target = T.let(target, T.nilable(Prism::Node))
@@ -1,8 +1,6 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- require "ruby_lsp/requests/support/rubocop_diagnostics_runner"
5
-
6
4
  module RubyLsp
7
5
  module Requests
8
6
  # ![Diagnostics demo](../../diagnostics.gif)
@@ -33,9 +31,10 @@ module RubyLsp
33
31
  end
34
32
  end
35
33
 
36
- sig { params(document: Document).void }
37
- def initialize(document)
34
+ sig { params(global_state: GlobalState, document: Document).void }
35
+ def initialize(global_state, document)
38
36
  super()
37
+ @active_linters = T.let(global_state.active_linters, T::Array[Support::Formatter])
39
38
  @document = document
40
39
  @uri = T.let(document.uri, URI::Generic)
41
40
  end
@@ -46,14 +45,12 @@ module RubyLsp
46
45
  diagnostics.concat(syntax_error_diagnostics, syntax_warning_diagnostics)
47
46
 
48
47
  # Running RuboCop is slow, so to avoid excessive runs we only do so if the file is syntactically valid
49
- return diagnostics if @document.syntax_error?
48
+ return diagnostics if @document.syntax_error? || @active_linters.empty?
50
49
 
51
- diagnostics.concat(
52
- Support::RuboCopDiagnosticsRunner.instance.run(
53
- @uri,
54
- @document,
55
- ).map!(&:to_lsp_diagnostic),
56
- ) if defined?(Support::RuboCopDiagnosticsRunner)
50
+ @active_linters.each do |linter|
51
+ linter_diagnostics = linter.run_diagnostic(@uri, @document)
52
+ diagnostics.concat(linter_diagnostics) if linter_diagnostics
53
+ end
57
54
 
58
55
  diagnostics
59
56
  end
@@ -45,11 +45,11 @@ module RubyLsp
45
45
  end
46
46
  end
47
47
 
48
- sig { params(dispatcher: Prism::Dispatcher).void }
49
- def initialize(dispatcher)
48
+ sig { params(uri: URI::Generic, dispatcher: Prism::Dispatcher).void }
49
+ def initialize(uri, dispatcher)
50
50
  super()
51
51
  @response_builder = T.let(ResponseBuilders::DocumentSymbol.new, ResponseBuilders::DocumentSymbol)
52
- Listeners::DocumentSymbol.new(@response_builder, dispatcher)
52
+ Listeners::DocumentSymbol.new(@response_builder, uri, dispatcher)
53
53
 
54
54
  Addon.addons.each do |addon|
55
55
  addon.create_document_symbol_listener(@response_builder, dispatcher)
@@ -1,9 +1,6 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- require "ruby_lsp/requests/support/rubocop_formatting_runner"
5
- require "ruby_lsp/requests/support/syntax_tree_formatting_runner"
6
-
7
4
  module RubyLsp
8
5
  module Requests
9
6
  # ![Formatting symbol demo](../../formatting.gif)
@@ -26,47 +23,24 @@ module RubyLsp
26
23
  # end
27
24
  # ```
28
25
  class Formatting < Request
29
- class Error < StandardError; end
30
- class InvalidFormatter < StandardError; end
31
-
32
- @formatters = T.let({}, T::Hash[String, Support::FormatterRunner])
33
-
34
- class << self
35
- extend T::Sig
36
-
37
- sig { returns(T::Hash[String, Support::FormatterRunner]) }
38
- attr_reader :formatters
39
-
40
- sig { params(identifier: String, instance: Support::FormatterRunner).void }
41
- def register_formatter(identifier, instance)
42
- @formatters[identifier] = instance
43
- end
44
- end
45
-
46
- if defined?(Support::RuboCopFormattingRunner)
47
- register_formatter("rubocop", Support::RuboCopFormattingRunner.instance)
48
- end
49
-
50
- if defined?(Support::SyntaxTreeFormattingRunner)
51
- register_formatter("syntax_tree", Support::SyntaxTreeFormattingRunner.instance)
52
- end
53
-
54
26
  extend T::Sig
55
27
 
56
- sig { params(document: Document, formatter: String).void }
57
- def initialize(document, formatter: "auto")
28
+ class Error < StandardError; end
29
+
30
+ sig { params(global_state: GlobalState, document: Document).void }
31
+ def initialize(global_state, document)
58
32
  super()
59
33
  @document = document
34
+ @active_formatter = T.let(global_state.active_formatter, T.nilable(Support::Formatter))
60
35
  @uri = T.let(document.uri, URI::Generic)
61
- @formatter = formatter
62
36
  end
63
37
 
64
38
  sig { override.returns(T.nilable(T.all(T::Array[Interface::TextEdit], Object))) }
65
39
  def perform
66
- return if @formatter == "none"
40
+ return unless @active_formatter
67
41
  return if @document.syntax_error?
68
42
 
69
- formatted_text = formatted_file
43
+ formatted_text = @active_formatter.run_formatting(@uri, @document)
70
44
  return unless formatted_text
71
45
 
72
46
  size = @document.source.size
@@ -82,16 +56,6 @@ module RubyLsp
82
56
  ),
83
57
  ]
84
58
  end
85
-
86
- private
87
-
88
- sig { returns(T.nilable(String)) }
89
- def formatted_file
90
- formatter_runner = Formatting.formatters[@formatter]
91
- raise InvalidFormatter, "Formatter is not available: #{@formatter}" unless formatter_runner
92
-
93
- formatter_runner.run(@uri, @document)
94
- end
95
59
  end
96
60
  end
97
61
  end
@@ -33,13 +33,13 @@ module RubyLsp
33
33
  sig do
34
34
  params(
35
35
  document: Document,
36
- index: RubyIndexer::Index,
36
+ global_state: GlobalState,
37
37
  position: T::Hash[Symbol, T.untyped],
38
38
  dispatcher: Prism::Dispatcher,
39
39
  typechecker_enabled: T::Boolean,
40
40
  ).void
41
41
  end
42
- def initialize(document, index, position, dispatcher, typechecker_enabled)
42
+ def initialize(document, global_state, position, dispatcher, typechecker_enabled)
43
43
  super()
44
44
  @target = T.let(nil, T.nilable(Prism::Node))
45
45
  @target, parent, nesting = document.locate_node(
@@ -62,9 +62,9 @@ module RubyLsp
62
62
 
63
63
  uri = document.uri
64
64
  @response_builder = T.let(ResponseBuilders::Hover.new, ResponseBuilders::Hover)
65
- Listeners::Hover.new(@response_builder, uri, nesting, index, dispatcher, typechecker_enabled)
65
+ Listeners::Hover.new(@response_builder, global_state, uri, nesting, dispatcher, typechecker_enabled)
66
66
  Addon.addons.each do |addon|
67
- addon.create_hover_listener(@response_builder, nesting, index, dispatcher)
67
+ addon.create_hover_listener(@response_builder, nesting, dispatcher)
68
68
  end
69
69
 
70
70
  @dispatcher = dispatcher
@@ -8,6 +8,8 @@ module RubyLsp
8
8
  extend T::Sig
9
9
  extend T::Generic
10
10
 
11
+ class InvalidFormatter < StandardError; end
12
+
11
13
  abstract!
12
14
 
13
15
  sig { abstract.returns(T.anything) }
@@ -29,7 +29,7 @@ module RubyLsp
29
29
  sig { returns(Interface::SemanticTokensRegistrationOptions) }
30
30
  def provider
31
31
  Interface::SemanticTokensRegistrationOptions.new(
32
- document_selector: { scheme: "file", language: "ruby" },
32
+ document_selector: [{ language: "ruby" }],
33
33
  legend: Interface::SemanticTokensLegend.new(
34
34
  token_types: ResponseBuilders::SemanticHighlighting::TOKEN_TYPES.keys,
35
35
  token_modifiers: ResponseBuilders::SemanticHighlighting::TOKEN_MODIFIERS.keys,
@@ -40,10 +40,13 @@ module RubyLsp
40
40
  end
41
41
  end
42
42
 
43
- sig { params(dispatcher: Prism::Dispatcher, range: T.nilable(T::Range[Integer])).void }
44
- def initialize(dispatcher, range: nil)
43
+ sig { params(global_state: GlobalState, dispatcher: Prism::Dispatcher, range: T.nilable(T::Range[Integer])).void }
44
+ def initialize(global_state, dispatcher, range: nil)
45
45
  super()
46
- @response_builder = T.let(ResponseBuilders::SemanticHighlighting.new, ResponseBuilders::SemanticHighlighting)
46
+ @response_builder = T.let(
47
+ ResponseBuilders::SemanticHighlighting.new(global_state.encoding),
48
+ ResponseBuilders::SemanticHighlighting,
49
+ )
47
50
  Listeners::SemanticHighlighting.new(dispatcher, @response_builder, range: range)
48
51
 
49
52
  Addon.addons.each do |addon|
@@ -42,13 +42,14 @@ module RubyLsp
42
42
  sig do
43
43
  params(
44
44
  document: Document,
45
- index: RubyIndexer::Index,
45
+ global_state: GlobalState,
46
46
  position: T::Hash[Symbol, T.untyped],
47
47
  context: T.nilable(T::Hash[Symbol, T.untyped]),
48
48
  dispatcher: Prism::Dispatcher,
49
+ typechecker_enabled: T::Boolean,
49
50
  ).void
50
51
  end
51
- def initialize(document, index, position, context, dispatcher)
52
+ def initialize(document, global_state, position, context, dispatcher, typechecker_enabled) # rubocop:disable Metrics/ParameterLists
52
53
  super()
53
54
  target, parent, nesting = document.locate_node(
54
55
  { line: position[:line], character: position[:character] },
@@ -60,7 +61,7 @@ module RubyLsp
60
61
  @target = T.let(target, T.nilable(Prism::Node))
61
62
  @dispatcher = dispatcher
62
63
  @response_builder = T.let(ResponseBuilders::SignatureHelp.new, ResponseBuilders::SignatureHelp)
63
- Listeners::SignatureHelp.new(@response_builder, nesting, index, dispatcher)
64
+ Listeners::SignatureHelp.new(@response_builder, global_state, nesting, dispatcher, typechecker_enabled)
64
65
  end
65
66
 
66
67
  sig { override.returns(T.nilable(Interface::SignatureHelp)) }