ruby-lsp 0.22.1 → 0.23.10

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/VERSION +1 -1
  4. data/exe/ruby-lsp +12 -11
  5. data/exe/ruby-lsp-check +5 -5
  6. data/exe/ruby-lsp-launcher +41 -15
  7. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +26 -20
  8. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +191 -100
  9. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +60 -30
  10. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +174 -61
  11. data/lib/ruby_indexer/lib/ruby_indexer/location.rb +12 -0
  12. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +16 -14
  13. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +82 -61
  14. data/lib/{core_ext → ruby_indexer/lib/ruby_indexer}/uri.rb +29 -3
  15. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +36 -0
  16. data/lib/ruby_indexer/ruby_indexer.rb +2 -1
  17. data/lib/ruby_indexer/test/class_variables_test.rb +140 -0
  18. data/lib/ruby_indexer/test/classes_and_modules_test.rb +30 -6
  19. data/lib/ruby_indexer/test/configuration_test.rb +116 -51
  20. data/lib/ruby_indexer/test/enhancements_test.rb +2 -2
  21. data/lib/ruby_indexer/test/index_test.rb +143 -44
  22. data/lib/ruby_indexer/test/instance_variables_test.rb +20 -0
  23. data/lib/ruby_indexer/test/method_test.rb +86 -8
  24. data/lib/ruby_indexer/test/rbs_indexer_test.rb +1 -1
  25. data/lib/ruby_indexer/test/reference_finder_test.rb +90 -2
  26. data/lib/ruby_indexer/test/test_case.rb +2 -2
  27. data/lib/ruby_indexer/test/uri_test.rb +72 -0
  28. data/lib/ruby_lsp/addon.rb +9 -0
  29. data/lib/ruby_lsp/base_server.rb +17 -18
  30. data/lib/ruby_lsp/client_capabilities.rb +7 -1
  31. data/lib/ruby_lsp/document.rb +72 -10
  32. data/lib/ruby_lsp/erb_document.rb +5 -3
  33. data/lib/ruby_lsp/global_state.rb +42 -3
  34. data/lib/ruby_lsp/internal.rb +3 -1
  35. data/lib/ruby_lsp/listeners/code_lens.rb +9 -5
  36. data/lib/ruby_lsp/listeners/completion.rb +78 -6
  37. data/lib/ruby_lsp/listeners/definition.rb +80 -19
  38. data/lib/ruby_lsp/listeners/document_highlight.rb +3 -2
  39. data/lib/ruby_lsp/listeners/document_link.rb +21 -3
  40. data/lib/ruby_lsp/listeners/document_symbol.rb +12 -1
  41. data/lib/ruby_lsp/listeners/folding_ranges.rb +1 -1
  42. data/lib/ruby_lsp/listeners/hover.rb +59 -2
  43. data/lib/ruby_lsp/load_sorbet.rb +3 -3
  44. data/lib/ruby_lsp/rbs_document.rb +2 -2
  45. data/lib/ruby_lsp/requests/code_action_resolve.rb +90 -6
  46. data/lib/ruby_lsp/requests/code_actions.rb +57 -1
  47. data/lib/ruby_lsp/requests/completion.rb +8 -1
  48. data/lib/ruby_lsp/requests/completion_resolve.rb +2 -1
  49. data/lib/ruby_lsp/requests/definition.rb +7 -1
  50. data/lib/ruby_lsp/requests/diagnostics.rb +1 -1
  51. data/lib/ruby_lsp/requests/document_highlight.rb +1 -1
  52. data/lib/ruby_lsp/requests/folding_ranges.rb +2 -6
  53. data/lib/ruby_lsp/requests/formatting.rb +2 -6
  54. data/lib/ruby_lsp/requests/hover.rb +1 -1
  55. data/lib/ruby_lsp/requests/on_type_formatting.rb +2 -2
  56. data/lib/ruby_lsp/requests/prepare_rename.rb +51 -0
  57. data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +1 -1
  58. data/lib/ruby_lsp/requests/references.rb +29 -2
  59. data/lib/ruby_lsp/requests/rename.rb +17 -7
  60. data/lib/ruby_lsp/requests/semantic_highlighting.rb +1 -1
  61. data/lib/ruby_lsp/requests/show_syntax_tree.rb +1 -4
  62. data/lib/ruby_lsp/requests/signature_help.rb +1 -1
  63. data/lib/ruby_lsp/requests/support/common.rb +2 -9
  64. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +3 -3
  65. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +13 -13
  66. data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +1 -1
  67. data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -3
  68. data/lib/ruby_lsp/ruby_document.rb +80 -6
  69. data/lib/ruby_lsp/scripts/compose_bundle.rb +1 -1
  70. data/lib/ruby_lsp/server.rb +205 -61
  71. data/lib/ruby_lsp/setup_bundler.rb +50 -43
  72. data/lib/ruby_lsp/store.rb +7 -7
  73. data/lib/ruby_lsp/test_helper.rb +45 -11
  74. data/lib/ruby_lsp/type_inferrer.rb +60 -31
  75. data/lib/ruby_lsp/utils.rb +63 -3
  76. metadata +8 -8
  77. data/lib/ruby_indexer/lib/ruby_indexer/indexable_path.rb +0 -29
@@ -12,6 +12,21 @@ module RubyLsp
12
12
  EXTRACT_TO_VARIABLE_TITLE = "Refactor: Extract Variable"
13
13
  EXTRACT_TO_METHOD_TITLE = "Refactor: Extract Method"
14
14
  TOGGLE_BLOCK_STYLE_TITLE = "Refactor: Toggle block style"
15
+ CREATE_ATTRIBUTE_READER = "Create Attribute Reader"
16
+ CREATE_ATTRIBUTE_WRITER = "Create Attribute Writer"
17
+ CREATE_ATTRIBUTE_ACCESSOR = "Create Attribute Accessor"
18
+
19
+ INSTANCE_VARIABLE_NODES = T.let(
20
+ [
21
+ Prism::InstanceVariableAndWriteNode,
22
+ Prism::InstanceVariableOperatorWriteNode,
23
+ Prism::InstanceVariableOrWriteNode,
24
+ Prism::InstanceVariableReadNode,
25
+ Prism::InstanceVariableTargetNode,
26
+ Prism::InstanceVariableWriteNode,
27
+ ],
28
+ T::Array[T.class_of(Prism::Node)],
29
+ )
15
30
 
16
31
  class << self
17
32
  extend T::Sig
@@ -19,7 +34,7 @@ module RubyLsp
19
34
  sig { returns(Interface::CodeActionRegistrationOptions) }
20
35
  def provider
21
36
  Interface::CodeActionRegistrationOptions.new(
22
- document_selector: [Interface::DocumentFilter.new(language: "ruby")],
37
+ document_selector: nil,
23
38
  resolve_provider: true,
24
39
  )
25
40
  end
@@ -66,9 +81,50 @@ module RubyLsp
66
81
  data: { range: @range, uri: @uri.to_s },
67
82
  )
68
83
  end
84
+ code_actions.concat(attribute_actions)
69
85
 
70
86
  code_actions
71
87
  end
88
+
89
+ private
90
+
91
+ sig { returns(T::Array[Interface::CodeAction]) }
92
+ def attribute_actions
93
+ return [] unless @document.is_a?(RubyDocument)
94
+
95
+ node = if @range.dig(:start) != @range.dig(:end)
96
+ @document.locate_first_within_range(
97
+ @range,
98
+ node_types: INSTANCE_VARIABLE_NODES,
99
+ )
100
+ end
101
+
102
+ if node.nil?
103
+ node_context = @document.locate_node(
104
+ @range[:start],
105
+ node_types: CodeActions::INSTANCE_VARIABLE_NODES,
106
+ )
107
+ return [] unless INSTANCE_VARIABLE_NODES.include?(node_context.node.class)
108
+ end
109
+
110
+ [
111
+ Interface::CodeAction.new(
112
+ title: CREATE_ATTRIBUTE_READER,
113
+ kind: Constant::CodeActionKind::EMPTY,
114
+ data: { range: @range, uri: @uri.to_s },
115
+ ),
116
+ Interface::CodeAction.new(
117
+ title: CREATE_ATTRIBUTE_WRITER,
118
+ kind: Constant::CodeActionKind::EMPTY,
119
+ data: { range: @range, uri: @uri.to_s },
120
+ ),
121
+ Interface::CodeAction.new(
122
+ title: CREATE_ATTRIBUTE_ACCESSOR,
123
+ kind: Constant::CodeActionKind::EMPTY,
124
+ data: { range: @range, uri: @uri.to_s },
125
+ ),
126
+ ]
127
+ end
72
128
  end
73
129
  end
74
130
  end
@@ -40,7 +40,8 @@ module RubyLsp
40
40
  @dispatcher = dispatcher
41
41
  # Completion always receives the position immediately after the character that was just typed. Here we adjust it
42
42
  # back by 1, so that we find the right node
43
- char_position = document.create_scanner.find_char_position(params[:position]) - 1
43
+ char_position, _ = document.find_index_by_position(params[:position])
44
+ char_position -= 1
44
45
  delegate_request_if_needed!(global_state, document, char_position)
45
46
 
46
47
  node_context = RubyDocument.locate(
@@ -62,6 +63,12 @@ module RubyLsp
62
63
  Prism::InstanceVariableOrWriteNode,
63
64
  Prism::InstanceVariableTargetNode,
64
65
  Prism::InstanceVariableWriteNode,
66
+ Prism::ClassVariableAndWriteNode,
67
+ Prism::ClassVariableOperatorWriteNode,
68
+ Prism::ClassVariableOrWriteNode,
69
+ Prism::ClassVariableReadNode,
70
+ Prism::ClassVariableTargetNode,
71
+ Prism::ClassVariableWriteNode,
65
72
  ],
66
73
  code_units_cache: document.code_units_cache,
67
74
  )
@@ -49,7 +49,8 @@ module RubyLsp
49
49
  if owner_name
50
50
  entries = entries.select do |entry|
51
51
  (entry.is_a?(RubyIndexer::Entry::Member) || entry.is_a?(RubyIndexer::Entry::InstanceVariable) ||
52
- entry.is_a?(RubyIndexer::Entry::MethodAlias)) && entry.owner&.name == owner_name
52
+ entry.is_a?(RubyIndexer::Entry::MethodAlias) || entry.is_a?(RubyIndexer::Entry::ClassVariable)) &&
53
+ entry.owner&.name == owner_name
53
54
  end
54
55
  end
55
56
 
@@ -29,7 +29,7 @@ module RubyLsp
29
29
  )
30
30
  @dispatcher = dispatcher
31
31
 
32
- char_position = document.create_scanner.find_char_position(position)
32
+ char_position, _ = document.find_index_by_position(position)
33
33
  delegate_request_if_needed!(global_state, document, char_position)
34
34
 
35
35
  node_context = RubyDocument.locate(
@@ -56,6 +56,12 @@ module RubyLsp
56
56
  Prism::StringNode,
57
57
  Prism::SuperNode,
58
58
  Prism::ForwardingSuperNode,
59
+ Prism::ClassVariableAndWriteNode,
60
+ Prism::ClassVariableOperatorWriteNode,
61
+ Prism::ClassVariableOrWriteNode,
62
+ Prism::ClassVariableReadNode,
63
+ Prism::ClassVariableTargetNode,
64
+ Prism::ClassVariableWriteNode,
59
65
  ],
60
66
  code_units_cache: document.code_units_cache,
61
67
  )
@@ -15,7 +15,7 @@ module RubyLsp
15
15
  sig { returns(Interface::DiagnosticRegistrationOptions) }
16
16
  def provider
17
17
  Interface::DiagnosticRegistrationOptions.new(
18
- document_selector: [Interface::DocumentFilter.new(language: "ruby")],
18
+ document_selector: nil,
19
19
  inter_file_dependencies: false,
20
20
  workspace_diagnostics: false,
21
21
  )
@@ -25,7 +25,7 @@ module RubyLsp
25
25
  end
26
26
  def initialize(global_state, document, position, dispatcher)
27
27
  super()
28
- char_position = document.create_scanner.find_char_position(position)
28
+ char_position, _ = document.find_index_by_position(position)
29
29
  delegate_request_if_needed!(global_state, document, char_position)
30
30
 
31
31
  node_context = RubyDocument.locate(
@@ -13,13 +13,9 @@ module RubyLsp
13
13
  class << self
14
14
  extend T::Sig
15
15
 
16
- sig { returns(Interface::FoldingRangeRegistrationOptions) }
16
+ sig { returns(TrueClass) }
17
17
  def provider
18
- Interface::FoldingRangeRegistrationOptions.new(
19
- document_selector: [
20
- Interface::DocumentFilter.new(language: "ruby"),
21
- ],
22
- )
18
+ true
23
19
  end
24
20
  end
25
21
 
@@ -14,13 +14,9 @@ module RubyLsp
14
14
  class << self
15
15
  extend T::Sig
16
16
 
17
- sig { returns(Interface::DocumentFormattingRegistrationOptions) }
17
+ sig { returns(TrueClass) }
18
18
  def provider
19
- Interface::DocumentFormattingRegistrationOptions.new(
20
- document_selector: [
21
- Interface::DocumentFilter.new(language: "ruby"),
22
- ],
23
- )
19
+ true
24
20
  end
25
21
  end
26
22
 
@@ -34,7 +34,7 @@ module RubyLsp
34
34
  def initialize(document, global_state, position, dispatcher, sorbet_level)
35
35
  super()
36
36
 
37
- char_position = document.create_scanner.find_char_position(position)
37
+ char_position, _ = document.find_index_by_position(position)
38
38
  delegate_request_if_needed!(global_state, document, char_position)
39
39
 
40
40
  node_context = RubyDocument.locate(
@@ -14,7 +14,7 @@ module RubyLsp
14
14
  sig { returns(Interface::DocumentOnTypeFormattingRegistrationOptions) }
15
15
  def provider
16
16
  Interface::DocumentOnTypeFormattingRegistrationOptions.new(
17
- document_selector: [Interface::DocumentFilter.new(language: "ruby")],
17
+ document_selector: nil,
18
18
  first_trigger_character: "{",
19
19
  more_trigger_character: ["\n", "|", "d"],
20
20
  )
@@ -170,7 +170,7 @@ module RubyLsp
170
170
 
171
171
  sig { params(line: Integer, character: Integer).void }
172
172
  def move_cursor_to(line, character)
173
- return unless @client_name.start_with?("Visual Studio Code")
173
+ return unless /Visual Studio Code|Cursor/.match?(@client_name)
174
174
 
175
175
  position = Interface::Position.new(
176
176
  line: line,
@@ -0,0 +1,51 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RubyLsp
5
+ module Requests
6
+ # The
7
+ # [prepare_rename](https://microsoft.github.io/language-server-protocol/specification#textDocument_prepareRename)
8
+ # # request checks the validity of a rename operation at a given location.
9
+ class PrepareRename < Request
10
+ extend T::Sig
11
+ include Support::Common
12
+
13
+ sig do
14
+ params(
15
+ document: RubyDocument,
16
+ position: T::Hash[Symbol, T.untyped],
17
+ ).void
18
+ end
19
+ def initialize(document, position)
20
+ super()
21
+ @document = document
22
+ @position = T.let(position, T::Hash[Symbol, Integer])
23
+ end
24
+
25
+ sig { override.returns(T.nilable(Interface::Range)) }
26
+ def perform
27
+ char_position, _ = @document.find_index_by_position(@position)
28
+
29
+ node_context = RubyDocument.locate(
30
+ @document.parse_result.value,
31
+ char_position,
32
+ node_types: [Prism::ConstantReadNode, Prism::ConstantPathNode, Prism::ConstantPathTargetNode],
33
+ code_units_cache: @document.code_units_cache,
34
+ )
35
+ target = node_context.node
36
+ parent = node_context.parent
37
+ return if !target || target.is_a?(Prism::ProgramNode)
38
+
39
+ if target.is_a?(Prism::ConstantReadNode) && parent.is_a?(Prism::ConstantPathNode)
40
+ target = determine_target(
41
+ target,
42
+ parent,
43
+ @position,
44
+ )
45
+ end
46
+
47
+ range_from_location(target.location)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -66,7 +66,7 @@ module RubyLsp
66
66
  Interface::TypeHierarchyItem.new(
67
67
  name: first_entry.name,
68
68
  kind: kind_for_entry(first_entry),
69
- uri: URI::Generic.from_path(path: first_entry.file_path).to_s,
69
+ uri: first_entry.uri.to_s,
70
70
  range: range,
71
71
  selection_range: range,
72
72
  ),
@@ -30,7 +30,7 @@ module RubyLsp
30
30
  sig { override.returns(T::Array[Interface::Location]) }
31
31
  def perform
32
32
  position = @params[:position]
33
- char_position = @document.create_scanner.find_char_position(position)
33
+ char_position, _ = @document.find_index_by_position(position)
34
34
 
35
35
  node_context = RubyDocument.locate(
36
36
  @document.parse_result.value,
@@ -39,6 +39,12 @@ module RubyLsp
39
39
  Prism::ConstantReadNode,
40
40
  Prism::ConstantPathNode,
41
41
  Prism::ConstantPathTargetNode,
42
+ Prism::InstanceVariableAndWriteNode,
43
+ Prism::InstanceVariableOperatorWriteNode,
44
+ Prism::InstanceVariableOrWriteNode,
45
+ Prism::InstanceVariableReadNode,
46
+ Prism::InstanceVariableTargetNode,
47
+ Prism::InstanceVariableWriteNode,
42
48
  Prism::CallNode,
43
49
  Prism::DefNode,
44
50
  ],
@@ -62,6 +68,12 @@ module RubyLsp
62
68
  Prism::ConstantReadNode,
63
69
  Prism::ConstantPathNode,
64
70
  Prism::ConstantPathTargetNode,
71
+ Prism::InstanceVariableAndWriteNode,
72
+ Prism::InstanceVariableOperatorWriteNode,
73
+ Prism::InstanceVariableOrWriteNode,
74
+ Prism::InstanceVariableReadNode,
75
+ Prism::InstanceVariableTargetNode,
76
+ Prism::InstanceVariableWriteNode,
65
77
  Prism::CallNode,
66
78
  Prism::DefNode,
67
79
  ),
@@ -97,6 +109,12 @@ module RubyLsp
97
109
  Prism::ConstantReadNode,
98
110
  Prism::ConstantPathNode,
99
111
  Prism::ConstantPathTargetNode,
112
+ Prism::InstanceVariableAndWriteNode,
113
+ Prism::InstanceVariableOperatorWriteNode,
114
+ Prism::InstanceVariableOrWriteNode,
115
+ Prism::InstanceVariableReadNode,
116
+ Prism::InstanceVariableTargetNode,
117
+ Prism::InstanceVariableWriteNode,
100
118
  Prism::CallNode,
101
119
  Prism::DefNode,
102
120
  ),
@@ -106,7 +124,7 @@ module RubyLsp
106
124
  def create_reference_target(target_node, node_context)
107
125
  case target_node
108
126
  when Prism::ConstantReadNode, Prism::ConstantPathNode, Prism::ConstantPathTargetNode
109
- name = constant_name(target_node)
127
+ name = RubyIndexer::Index.constant_name(target_node)
110
128
  return unless name
111
129
 
112
130
  entries = @global_state.index.resolve(name, node_context.nesting)
@@ -114,6 +132,14 @@ module RubyLsp
114
132
 
115
133
  fully_qualified_name = T.must(entries.first).name
116
134
  RubyIndexer::ReferenceFinder::ConstTarget.new(fully_qualified_name)
135
+ when
136
+ Prism::InstanceVariableAndWriteNode,
137
+ Prism::InstanceVariableOperatorWriteNode,
138
+ Prism::InstanceVariableOrWriteNode,
139
+ Prism::InstanceVariableReadNode,
140
+ Prism::InstanceVariableTargetNode,
141
+ Prism::InstanceVariableWriteNode
142
+ RubyIndexer::ReferenceFinder::InstanceVariableTarget.new(target_node.name.to_s)
117
143
  when Prism::CallNode, Prism::DefNode
118
144
  RubyIndexer::ReferenceFinder::MethodTarget.new(target_node.name.to_s)
119
145
  end
@@ -132,6 +158,7 @@ module RubyLsp
132
158
  target,
133
159
  @global_state.index,
134
160
  dispatcher,
161
+ uri,
135
162
  include_declarations: @params.dig(:context, :includeDeclaration) || true,
136
163
  )
137
164
  dispatcher.visit(parse_result.value)
@@ -12,6 +12,15 @@ module RubyLsp
12
12
 
13
13
  class InvalidNameError < StandardError; end
14
14
 
15
+ class << self
16
+ extend T::Sig
17
+
18
+ sig { returns(Interface::RenameOptions) }
19
+ def provider
20
+ Interface::RenameOptions.new(prepare_provider: true)
21
+ end
22
+ end
23
+
15
24
  sig do
16
25
  params(
17
26
  global_state: GlobalState,
@@ -31,7 +40,7 @@ module RubyLsp
31
40
 
32
41
  sig { override.returns(T.nilable(Interface::WorkspaceEdit)) }
33
42
  def perform
34
- char_position = @document.create_scanner.find_char_position(@position)
43
+ char_position, _ = @document.find_index_by_position(@position)
35
44
 
36
45
  node_context = RubyDocument.locate(
37
46
  @document.parse_result.value,
@@ -56,7 +65,7 @@ module RubyLsp
56
65
  T.any(Prism::ConstantReadNode, Prism::ConstantPathNode, Prism::ConstantPathTargetNode),
57
66
  )
58
67
 
59
- name = constant_name(target)
68
+ name = RubyIndexer::Index.constant_name(target)
60
69
  return unless name
61
70
 
62
71
  entries = @global_state.index.resolve(name, node_context.nesting)
@@ -106,7 +115,9 @@ module RubyLsp
106
115
 
107
116
  T.must(@global_state.index[fully_qualified_name]).each do |entry|
108
117
  # Do not rename files that are not part of the workspace
109
- next unless entry.file_path.start_with?(@global_state.workspace_path)
118
+ uri = entry.uri
119
+ file_path = uri.full_path
120
+ next unless file_path&.start_with?(@global_state.workspace_path)
110
121
 
111
122
  case entry
112
123
  when RubyIndexer::Entry::Class, RubyIndexer::Entry::Module, RubyIndexer::Entry::Constant,
@@ -117,13 +128,12 @@ module RubyLsp
117
128
  if "#{file_name}.rb" == entry.file_name
118
129
  new_file_name = file_from_constant_name(T.must(@new_name.split("::").last))
119
130
 
120
- old_uri = URI::Generic.from_path(path: entry.file_path).to_s
121
131
  new_uri = URI::Generic.from_path(path: File.join(
122
- File.dirname(entry.file_path),
132
+ File.dirname(file_path),
123
133
  "#{new_file_name}.rb",
124
134
  )).to_s
125
135
 
126
- document_changes << Interface::RenameFile.new(kind: "rename", old_uri: old_uri, new_uri: new_uri)
136
+ document_changes << Interface::RenameFile.new(kind: "rename", old_uri: uri.to_s, new_uri: new_uri)
127
137
  end
128
138
  end
129
139
  end
@@ -169,7 +179,7 @@ module RubyLsp
169
179
  end
170
180
  def collect_changes(target, parse_result, name, uri)
171
181
  dispatcher = Prism::Dispatcher.new
172
- finder = RubyIndexer::ReferenceFinder.new(target, @global_state.index, dispatcher)
182
+ finder = RubyIndexer::ReferenceFinder.new(target, @global_state.index, dispatcher, uri)
173
183
  dispatcher.visit(parse_result.value)
174
184
 
175
185
  finder.references.map do |reference|
@@ -17,7 +17,7 @@ module RubyLsp
17
17
  sig { returns(Interface::SemanticTokensRegistrationOptions) }
18
18
  def provider
19
19
  Interface::SemanticTokensRegistrationOptions.new(
20
- document_selector: [{ language: "ruby" }, { language: "erb" }],
20
+ document_selector: nil,
21
21
  legend: Interface::SemanticTokensLegend.new(
22
22
  token_types: ResponseBuilders::SemanticHighlighting::TOKEN_TYPES.keys,
23
23
  token_modifiers: ResponseBuilders::SemanticHighlighting::TOKEN_MODIFIERS.keys,
@@ -31,10 +31,7 @@ module RubyLsp
31
31
  sig { returns(String) }
32
32
  def ast_for_range
33
33
  range = T.must(@range)
34
-
35
- scanner = @document.create_scanner
36
- start_char = scanner.find_char_position(range[:start])
37
- end_char = scanner.find_char_position(range[:end])
34
+ start_char, end_char = @document.find_index_by_position(range[:start], range[:end])
38
35
 
39
36
  queue = @tree.statements.body.dup
40
37
  found_nodes = []
@@ -36,7 +36,7 @@ module RubyLsp
36
36
  def initialize(document, global_state, position, context, dispatcher, sorbet_level) # rubocop:disable Metrics/ParameterLists
37
37
  super()
38
38
 
39
- char_position = document.create_scanner.find_char_position(position)
39
+ char_position, _ = document.find_index_by_position(position)
40
40
  delegate_request_if_needed!(global_state, document, char_position)
41
41
 
42
42
  node_context = RubyDocument.locate(
@@ -93,11 +93,7 @@ module RubyLsp
93
93
  # based, which is why instead of the usual subtraction of 1 to line numbers, we are actually adding 1 to
94
94
  # columns. The format for VS Code file URIs is
95
95
  # `file:///path/to/file.rb#Lstart_line,start_column-end_line,end_column`
96
- uri = URI::Generic.from_path(
97
- path: entry.file_path,
98
- fragment: "L#{loc.start_line},#{loc.start_column + 1}-#{loc.end_line},#{loc.end_column + 1}",
99
- )
100
-
96
+ uri = "#{entry.uri}#L#{loc.start_line},#{loc.start_column + 1}-#{loc.end_line},#{loc.end_column + 1}"
101
97
  definitions << "[#{entry.file_name}](#{uri})"
102
98
  content << "\n\n#{entry.comments}" unless entry.comments.empty?
103
99
  end
@@ -149,10 +145,7 @@ module RubyLsp
149
145
  ).returns(T.nilable(String))
150
146
  end
151
147
  def constant_name(node)
152
- node.full_name
153
- rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError,
154
- Prism::ConstantPathNode::MissingNodesInConstantPathError
155
- nil
148
+ RubyIndexer::Index.constant_name(node)
156
149
  end
157
150
 
158
151
  sig { params(node: T.any(Prism::ModuleNode, Prism::ClassNode)).returns(T.nilable(String)) }
@@ -31,7 +31,7 @@ module RubyLsp
31
31
 
32
32
  # TODO: avoid passing document once we have alternative ways to get at
33
33
  # encoding and file source
34
- sig { params(document: RubyDocument, offense: RuboCop::Cop::Offense, uri: URI::Generic).void }
34
+ sig { params(document: RubyDocument, offense: ::RuboCop::Cop::Offense, uri: URI::Generic).void }
35
35
  def initialize(document, offense, uri)
36
36
  @document = document
37
37
  @offense = offense
@@ -48,7 +48,7 @@ module RubyLsp
48
48
  code_actions
49
49
  end
50
50
 
51
- sig { params(config: RuboCop::Config).returns(Interface::Diagnostic) }
51
+ sig { params(config: ::RuboCop::Config).returns(Interface::Diagnostic) }
52
52
  def to_lsp_diagnostic(config)
53
53
  # highlighted_area contains the begin and end position of the first line
54
54
  # This ensures that multiline offenses don't clutter the editor
@@ -90,7 +90,7 @@ module RubyLsp
90
90
  RUBOCOP_TO_LSP_SEVERITY[@offense.severity.name]
91
91
  end
92
92
 
93
- sig { params(config: RuboCop::Config).returns(T.nilable(Interface::CodeDescription)) }
93
+ sig { params(config: ::RuboCop::Config).returns(T.nilable(Interface::CodeDescription)) }
94
94
  def code_description(config)
95
95
  cop = RuboCopRunner.find_cop_by_name(@offense.cop_name)
96
96
  return unless cop
@@ -40,10 +40,10 @@ module RubyLsp
40
40
  For more details, run RuboCop on the command line.
41
41
  EOS
42
42
 
43
- sig { params(rubocop_error: T.any(RuboCop::ErrorWithAnalyzedFileLocation, StandardError)).void }
43
+ sig { params(rubocop_error: T.any(::RuboCop::ErrorWithAnalyzedFileLocation, StandardError)).void }
44
44
  def initialize(rubocop_error)
45
45
  message = case rubocop_error
46
- when RuboCop::ErrorWithAnalyzedFileLocation
46
+ when ::RuboCop::ErrorWithAnalyzedFileLocation
47
47
  format(MESSAGE, "for the #{rubocop_error.cop.name} cop")
48
48
  when StandardError
49
49
  format(MESSAGE, rubocop_error.message)
@@ -53,7 +53,7 @@ module RubyLsp
53
53
  end
54
54
 
55
55
  # :nodoc:
56
- class RuboCopRunner < RuboCop::Runner
56
+ class RuboCopRunner < ::RuboCop::Runner
57
57
  extend T::Sig
58
58
 
59
59
  class ConfigurationError < StandardError; end
@@ -68,14 +68,14 @@ module RubyLsp
68
68
  T::Array[String],
69
69
  )
70
70
 
71
- sig { returns(T::Array[RuboCop::Cop::Offense]) }
71
+ sig { returns(T::Array[::RuboCop::Cop::Offense]) }
72
72
  attr_reader :offenses
73
73
 
74
74
  sig { returns(::RuboCop::Config) }
75
75
  attr_reader :config_for_working_directory
76
76
 
77
77
  begin
78
- RuboCop::Options.new.parse(["--raise-cop-error"])
78
+ ::RuboCop::Options.new.parse(["--raise-cop-error"])
79
79
  DEFAULT_ARGS << "--raise-cop-error"
80
80
  rescue OptionParser::InvalidOption
81
81
  # older versions of RuboCop don't support this flag
@@ -85,7 +85,7 @@ module RubyLsp
85
85
  sig { params(args: String).void }
86
86
  def initialize(*args)
87
87
  @options = T.let({}, T::Hash[Symbol, T.untyped])
88
- @offenses = T.let([], T::Array[RuboCop::Cop::Offense])
88
+ @offenses = T.let([], T::Array[::RuboCop::Cop::Offense])
89
89
  @errors = T.let([], T::Array[String])
90
90
  @warnings = T.let([], T::Array[String])
91
91
 
@@ -113,9 +113,9 @@ module RubyLsp
113
113
  # RuboCop rescues interrupts and then sets the `@aborting` variable to true. We don't want them to be rescued,
114
114
  # so here we re-raise in case RuboCop received an interrupt.
115
115
  raise Interrupt if aborting?
116
- rescue RuboCop::Runner::InfiniteCorrectionLoop => error
116
+ rescue ::RuboCop::Runner::InfiniteCorrectionLoop => error
117
117
  raise Formatting::Error, error.message
118
- rescue RuboCop::ValidationError => error
118
+ rescue ::RuboCop::ValidationError => error
119
119
  raise ConfigurationError, error.message
120
120
  rescue StandardError => error
121
121
  raise InternalRuboCopError, error
@@ -129,25 +129,25 @@ module RubyLsp
129
129
  class << self
130
130
  extend T::Sig
131
131
 
132
- sig { params(cop_name: String).returns(T.nilable(T.class_of(RuboCop::Cop::Base))) }
132
+ sig { params(cop_name: String).returns(T.nilable(T.class_of(::RuboCop::Cop::Base))) }
133
133
  def find_cop_by_name(cop_name)
134
134
  cop_registry[cop_name]&.first
135
135
  end
136
136
 
137
137
  private
138
138
 
139
- sig { returns(T::Hash[String, [T.class_of(RuboCop::Cop::Base)]]) }
139
+ sig { returns(T::Hash[String, [T.class_of(::RuboCop::Cop::Base)]]) }
140
140
  def cop_registry
141
141
  @cop_registry ||= T.let(
142
- RuboCop::Cop::Registry.global.to_h,
143
- T.nilable(T::Hash[String, [T.class_of(RuboCop::Cop::Base)]]),
142
+ ::RuboCop::Cop::Registry.global.to_h,
143
+ T.nilable(T::Hash[String, [T.class_of(::RuboCop::Cop::Base)]]),
144
144
  )
145
145
  end
146
146
  end
147
147
 
148
148
  private
149
149
 
150
- sig { params(_file: String, offenses: T::Array[RuboCop::Cop::Offense]).void }
150
+ sig { params(_file: String, offenses: T::Array[::RuboCop::Cop::Offense]).void }
151
151
  def file_finished(_file, offenses)
152
152
  @offenses = offenses
153
153
  end
@@ -65,7 +65,7 @@ module RubyLsp
65
65
  Interface::TypeHierarchyItem.new(
66
66
  name: entry.name,
67
67
  kind: kind_for_entry(entry),
68
- uri: URI::Generic.from_path(path: entry.file_path).to_s,
68
+ uri: entry.uri.to_s,
69
69
  range: range_from_location(entry.location),
70
70
  selection_range: range_from_location(entry.name_location),
71
71
  detail: entry.file_name,
@@ -21,10 +21,11 @@ module RubyLsp
21
21
  sig { override.returns(T::Array[Interface::WorkspaceSymbol]) }
22
22
  def perform
23
23
  @index.fuzzy_search(@query).filter_map do |entry|
24
- file_path = entry.file_path
24
+ uri = entry.uri
25
+ file_path = uri.full_path
25
26
 
26
27
  # We only show symbols declared in the workspace
27
- in_dependencies = !not_in_dependencies?(file_path)
28
+ in_dependencies = file_path && !not_in_dependencies?(file_path)
28
29
  next if in_dependencies
29
30
 
30
31
  # We should never show private symbols when searching the entire workspace
@@ -43,7 +44,7 @@ module RubyLsp
43
44
  container_name: container.join("::"),
44
45
  kind: kind,
45
46
  location: Interface::Location.new(
46
- uri: URI::Generic.from_path(path: file_path).to_s,
47
+ uri: uri.to_s,
47
48
  range: Interface::Range.new(
48
49
  start: Interface::Position.new(line: loc.start_line - 1, character: loc.start_column),
49
50
  end: Interface::Position.new(line: loc.end_line - 1, character: loc.end_column),