ruby-lsp 0.14.6 → 0.16.5

Sign up to get free protection for your applications and to get access to all the features.
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)) }