ruby-lsp 0.13.3 → 0.14.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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -2
  3. data/VERSION +1 -1
  4. data/exe/ruby-lsp-doctor +2 -0
  5. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +4 -8
  6. data/lib/ruby_indexer/lib/ruby_indexer/collector.rb +5 -1
  7. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +4 -2
  8. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +10 -5
  9. data/lib/ruby_indexer/test/classes_and_modules_test.rb +9 -0
  10. data/lib/ruby_indexer/test/index_test.rb +54 -3
  11. data/lib/ruby_lsp/addon.rb +34 -17
  12. data/lib/ruby_lsp/check_docs.rb +8 -8
  13. data/lib/ruby_lsp/executor.rb +28 -10
  14. data/lib/ruby_lsp/internal.rb +8 -6
  15. data/lib/ruby_lsp/listeners/code_lens.rb +54 -55
  16. data/lib/ruby_lsp/listeners/completion.rb +22 -18
  17. data/lib/ruby_lsp/listeners/definition.rb +31 -29
  18. data/lib/ruby_lsp/listeners/document_highlight.rb +6 -11
  19. data/lib/ruby_lsp/listeners/document_link.rb +6 -12
  20. data/lib/ruby_lsp/listeners/document_symbol.rb +194 -55
  21. data/lib/ruby_lsp/listeners/folding_ranges.rb +19 -23
  22. data/lib/ruby_lsp/listeners/hover.rb +36 -34
  23. data/lib/ruby_lsp/listeners/inlay_hints.rb +7 -13
  24. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +54 -124
  25. data/lib/ruby_lsp/listeners/signature_help.rb +15 -14
  26. data/lib/ruby_lsp/requests/code_lens.rb +11 -19
  27. data/lib/ruby_lsp/requests/completion.rb +7 -9
  28. data/lib/ruby_lsp/requests/definition.rb +10 -22
  29. data/lib/ruby_lsp/requests/document_highlight.rb +7 -5
  30. data/lib/ruby_lsp/requests/document_link.rb +7 -6
  31. data/lib/ruby_lsp/requests/document_symbol.rb +5 -11
  32. data/lib/ruby_lsp/requests/folding_ranges.rb +11 -6
  33. data/lib/ruby_lsp/requests/hover.rb +18 -24
  34. data/lib/ruby_lsp/requests/inlay_hints.rb +7 -8
  35. data/lib/ruby_lsp/requests/on_type_formatting.rb +12 -2
  36. data/lib/ruby_lsp/requests/semantic_highlighting.rb +10 -8
  37. data/lib/ruby_lsp/requests/signature_help.rb +53 -18
  38. data/lib/ruby_lsp/requests/support/common.rb +38 -10
  39. data/lib/ruby_lsp/requests/support/dependency_detector.rb +5 -1
  40. data/lib/ruby_lsp/requests.rb +0 -1
  41. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +29 -0
  42. data/lib/ruby_lsp/response_builders/document_symbol.rb +57 -0
  43. data/lib/ruby_lsp/response_builders/hover.rb +49 -0
  44. data/lib/ruby_lsp/response_builders/response_builder.rb +16 -0
  45. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +199 -0
  46. data/lib/ruby_lsp/response_builders/signature_help.rb +28 -0
  47. data/lib/ruby_lsp/response_builders.rb +13 -0
  48. data/lib/ruby_lsp/server.rb +3 -3
  49. data/lib/ruby_lsp/setup_bundler.rb +64 -23
  50. data/lib/ruby_lsp/store.rb +4 -4
  51. metadata +17 -11
  52. data/lib/ruby_lsp/listener.rb +0 -33
  53. data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +0 -73
@@ -0,0 +1,199 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RubyLsp
5
+ module ResponseBuilders
6
+ class SemanticHighlighting < ResponseBuilder
7
+ class UndefinedTokenType < StandardError; end
8
+
9
+ TOKEN_TYPES = T.let(
10
+ {
11
+ namespace: 0,
12
+ type: 1,
13
+ class: 2,
14
+ enum: 3,
15
+ interface: 4,
16
+ struct: 5,
17
+ typeParameter: 6,
18
+ parameter: 7,
19
+ variable: 8,
20
+ property: 9,
21
+ enumMember: 10,
22
+ event: 11,
23
+ function: 12,
24
+ method: 13,
25
+ macro: 14,
26
+ keyword: 15,
27
+ modifier: 16,
28
+ comment: 17,
29
+ string: 18,
30
+ number: 19,
31
+ regexp: 20,
32
+ operator: 21,
33
+ decorator: 22,
34
+ }.freeze,
35
+ T::Hash[Symbol, Integer],
36
+ )
37
+
38
+ TOKEN_MODIFIERS = T.let(
39
+ {
40
+ declaration: 0,
41
+ definition: 1,
42
+ readonly: 2,
43
+ static: 3,
44
+ deprecated: 4,
45
+ abstract: 5,
46
+ async: 6,
47
+ modification: 7,
48
+ documentation: 8,
49
+ default_library: 9,
50
+ }.freeze,
51
+ T::Hash[Symbol, Integer],
52
+ )
53
+
54
+ extend T::Sig
55
+
56
+ ResponseType = type_member { { fixed: Interface::SemanticTokens } }
57
+
58
+ sig { void }
59
+ def initialize
60
+ super
61
+ @stack = T.let([], T::Array[SemanticToken])
62
+ end
63
+
64
+ sig { params(location: Prism::Location, type: Symbol, modifiers: T::Array[Symbol]).void }
65
+ def add_token(location, type, modifiers = [])
66
+ length = location.end_offset - location.start_offset
67
+ modifiers_indices = modifiers.filter_map { |modifier| TOKEN_MODIFIERS[modifier] }
68
+ @stack.push(
69
+ SemanticToken.new(
70
+ location: location,
71
+ length: length,
72
+ type: T.must(TOKEN_TYPES[type]),
73
+ modifier: modifiers_indices,
74
+ ),
75
+ )
76
+ end
77
+
78
+ sig { returns(T.nilable(SemanticToken)) }
79
+ def last
80
+ @stack.last
81
+ end
82
+
83
+ sig { override.returns(Interface::SemanticTokens) }
84
+ def response
85
+ SemanticTokenEncoder.new.encode(@stack)
86
+ end
87
+
88
+ class SemanticToken
89
+ extend T::Sig
90
+
91
+ sig { returns(Prism::Location) }
92
+ attr_reader :location
93
+
94
+ sig { returns(Integer) }
95
+ attr_reader :length
96
+
97
+ sig { returns(Integer) }
98
+ attr_reader :type
99
+
100
+ sig { returns(T::Array[Integer]) }
101
+ attr_reader :modifier
102
+
103
+ sig { params(location: Prism::Location, length: Integer, type: Integer, modifier: T::Array[Integer]).void }
104
+ def initialize(location:, length:, type:, modifier:)
105
+ @location = location
106
+ @length = length
107
+ @type = type
108
+ @modifier = modifier
109
+ end
110
+
111
+ sig { params(type_symbol: Symbol).void }
112
+ def replace_type(type_symbol)
113
+ type_int = TOKEN_TYPES[type_symbol]
114
+ raise UndefinedTokenType, "Undefined token type: #{type_symbol}" unless type_int
115
+
116
+ @type = type_int
117
+ end
118
+
119
+ sig { params(modifier_symbols: T::Array[Symbol]).void }
120
+ def replace_modifier(modifier_symbols)
121
+ @modifier = modifier_symbols.filter_map do |modifier_symbol|
122
+ modifier_index = TOKEN_MODIFIERS[modifier_symbol]
123
+ raise UndefinedTokenType, "Undefined token modifier: #{modifier_symbol}" unless modifier_index
124
+
125
+ modifier_index
126
+ end
127
+ end
128
+ end
129
+
130
+ class SemanticTokenEncoder
131
+ extend T::Sig
132
+
133
+ sig { void }
134
+ def initialize
135
+ @current_row = T.let(0, Integer)
136
+ @current_column = T.let(0, Integer)
137
+ end
138
+
139
+ sig do
140
+ params(
141
+ tokens: T::Array[SemanticToken],
142
+ ).returns(Interface::SemanticTokens)
143
+ end
144
+ def encode(tokens)
145
+ sorted_tokens = tokens.sort_by.with_index do |token, index|
146
+ # Enumerable#sort_by is not deterministic when the compared values are equal.
147
+ # When that happens, we need to use the index as a tie breaker to ensure
148
+ # that the order of the tokens is always the same.
149
+ [token.location.start_line, token.location.start_column, index]
150
+ end
151
+
152
+ delta = sorted_tokens.flat_map do |token|
153
+ compute_delta(token)
154
+ end
155
+
156
+ Interface::SemanticTokens.new(data: delta)
157
+ end
158
+
159
+ # The delta array is computed according to the LSP specification:
160
+ # > The protocol for the token format relative uses relative
161
+ # > positions, because most tokens remain stable relative to
162
+ # > each other when edits are made in a file. This simplifies
163
+ # > the computation of a delta if a server supports it. So each
164
+ # > token is represented using 5 integers.
165
+
166
+ # For more information on how each number is calculated, read:
167
+ # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_semanticTokens
168
+ sig { params(token: SemanticToken).returns(T::Array[Integer]) }
169
+ def compute_delta(token)
170
+ row = token.location.start_line - 1
171
+ column = token.location.start_column
172
+
173
+ begin
174
+ delta_line = row - @current_row
175
+
176
+ delta_column = column
177
+ delta_column -= @current_column if delta_line == 0
178
+
179
+ [delta_line, delta_column, token.length, token.type, encode_modifiers(token.modifier)]
180
+ ensure
181
+ @current_row = row
182
+ @current_column = column
183
+ end
184
+ end
185
+
186
+ # Encode an array of modifiers to positions onto a bit flag
187
+ # For example, [:default_library] will be encoded as
188
+ # 0b1000000000, as :default_library is the 10th bit according
189
+ # to the token modifiers index map.
190
+ sig { params(modifiers: T::Array[Integer]).returns(Integer) }
191
+ def encode_modifiers(modifiers)
192
+ modifiers.inject(0) do |encoded_modifiers, modifier|
193
+ encoded_modifiers | (1 << modifier)
194
+ end
195
+ end
196
+ end
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,28 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RubyLsp
5
+ module ResponseBuilders
6
+ class SignatureHelp < ResponseBuilder
7
+ ResponseType = type_member { { fixed: T.nilable(Interface::SignatureHelp) } }
8
+
9
+ extend T::Sig
10
+
11
+ sig { void }
12
+ def initialize
13
+ super
14
+ @signature_help = T.let(nil, ResponseType)
15
+ end
16
+
17
+ sig { params(signature_help: ResponseType).void }
18
+ def replace(signature_help)
19
+ @signature_help = signature_help
20
+ end
21
+
22
+ sig { override.returns(ResponseType) }
23
+ def response
24
+ @signature_help
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RubyLsp
5
+ module ResponseBuilders
6
+ autoload :CollectionResponseBuilder, "ruby_lsp/response_builders/collection_response_builder"
7
+ autoload :DocumentSymbol, "ruby_lsp/response_builders/document_symbol"
8
+ autoload :Hover, "ruby_lsp/response_builders/hover"
9
+ autoload :ResponseBuilder, "ruby_lsp/response_builders/response_builder"
10
+ autoload :SemanticHighlighting, "ruby_lsp/response_builders/semantic_highlighting"
11
+ autoload :SignatureHelp, "ruby_lsp/response_builders/signature_help"
12
+ end
13
+ end
@@ -58,7 +58,7 @@ module RubyLsp
58
58
 
59
59
  sig { void }
60
60
  def start
61
- warn("Starting Ruby LSP v#{VERSION}...")
61
+ $stderr.puts("Starting Ruby LSP v#{VERSION}...")
62
62
 
63
63
  # Requests that have to be executed sequentially or in the main process are implemented here. All other requests
64
64
  # fall under the else branch which just pushes requests to the queue
@@ -73,7 +73,7 @@ module RubyLsp
73
73
  when "$/setTrace"
74
74
  VOID
75
75
  when "shutdown"
76
- warn("Shutting down Ruby LSP...")
76
+ $stderr.puts("Shutting down Ruby LSP...")
77
77
 
78
78
  @message_queue.close
79
79
  # Close the queue so that we can no longer receive items
@@ -92,7 +92,7 @@ module RubyLsp
92
92
  # We return zero if shutdown has already been received or one otherwise as per the recommendation in the spec
93
93
  # https://microsoft.github.io/language-server-protocol/specification/#exit
94
94
  status = @store.empty? ? 0 : 1
95
- warn("Shutdown complete with status #{status}")
95
+ $stderr.puts("Shutdown complete with status #{status}")
96
96
  exit(status)
97
97
  else
98
98
  # Default case: push the request to the queue to be executed by the worker
@@ -57,13 +57,18 @@ module RubyLsp
57
57
  def setup!
58
58
  raise BundleNotLocked if @gemfile&.exist? && !@lockfile&.exist?
59
59
 
60
- # Do not setup a custom bundle if both `ruby-lsp` and `debug` are already in the Gemfile
61
- if @dependencies["ruby-lsp"] && @dependencies["debug"]
62
- warn("Ruby LSP> Skipping custom bundle setup since both `ruby-lsp` and `debug` are already in #{@gemfile}")
63
-
64
- # If the user decided to add the `ruby-lsp` and `debug` to their Gemfile after having already run the Ruby LSP,
65
- # then we need to remove the `.ruby-lsp` folder, otherwise we will run `bundle install` for the top level and
66
- # try to execute the Ruby LSP using the custom bundle, which will fail since the gems are not installed there
60
+ # Do not set up a custom bundle if LSP dependencies are already in the Gemfile
61
+ if @dependencies["ruby-lsp"] &&
62
+ @dependencies["debug"] &&
63
+ (@dependencies["rails"] ? @dependencies["ruby-lsp-rails"] : true)
64
+ $stderr.puts(
65
+ "Ruby LSP> Skipping custom bundle setup since LSP dependencies are already in #{@gemfile}",
66
+ )
67
+
68
+ # If the user decided to add `ruby-lsp` and `debug` (and potentially `ruby-lsp-rails`) to their Gemfile after
69
+ # having already run the Ruby LSP, then we need to remove the `.ruby-lsp` folder, otherwise we will run `bundle
70
+ # install` for the top level and try to execute the Ruby LSP using the custom bundle, which will fail since the
71
+ # gems are not installed there
67
72
  @custom_dir.rmtree if @custom_dir.exist?
68
73
  return run_bundle_install
69
74
  end
@@ -76,7 +81,7 @@ module RubyLsp
76
81
  write_custom_gemfile
77
82
 
78
83
  unless @gemfile&.exist? && @lockfile&.exist?
79
- warn("Ruby LSP> Skipping lockfile copies because there's no top level bundle")
84
+ $stderr.puts("Ruby LSP> Skipping lockfile copies because there's no top level bundle")
80
85
  return run_bundle_install(@custom_gemfile)
81
86
  end
82
87
 
@@ -84,11 +89,14 @@ module RubyLsp
84
89
  current_lockfile_hash = Digest::SHA256.hexdigest(lockfile_contents)
85
90
 
86
91
  if @custom_lockfile.exist? && @lockfile_hash_path.exist? && @lockfile_hash_path.read == current_lockfile_hash
87
- warn("Ruby LSP> Skipping custom bundle setup since #{@custom_lockfile} already exists and is up to date")
92
+ $stderr.puts(
93
+ "Ruby LSP> Skipping custom bundle setup since #{@custom_lockfile} already exists and is up to date",
94
+ )
88
95
  return run_bundle_install(@custom_gemfile)
89
96
  end
90
97
 
91
98
  FileUtils.cp(@lockfile.to_s, @custom_lockfile.to_s)
99
+ correct_relative_remote_paths
92
100
  @lockfile_hash_path.write(current_lockfile_hash)
93
101
  run_bundle_install(@custom_gemfile)
94
102
  end
@@ -138,6 +146,10 @@ module RubyLsp
138
146
  parts << 'gem "debug", require: false, group: :development, platforms: :mri'
139
147
  end
140
148
 
149
+ if @dependencies["rails"] && !@dependencies["ruby-lsp-rails"]
150
+ parts << 'gem "ruby-lsp-rails", require: false, group: :development'
151
+ end
152
+
141
153
  content = parts.join("\n")
142
154
  @custom_gemfile.write(content) unless @custom_gemfile.exist? && @custom_gemfile.read == content
143
155
  end
@@ -178,22 +190,24 @@ module RubyLsp
178
190
  local_config_path = File.join(Dir.pwd, ".bundle")
179
191
  env["BUNDLE_APP_CONFIG"] = local_config_path if Dir.exist?(local_config_path)
180
192
 
181
- # If both `ruby-lsp` and `debug` are already in the Gemfile, then we shouldn't try to upgrade them or else we'll
182
- # produce undesired source control changes. If the custom bundle was just created and either `ruby-lsp` or `debug`
183
- # weren't a part of the Gemfile, then we need to run `bundle install` for the first time to generate the
184
- # Gemfile.lock with them included or else Bundler will complain that they're missing. We can only update if the
185
- # custom `.ruby-lsp/Gemfile.lock` already exists and includes both gems
193
+ # If `ruby-lsp` and `debug` (and potentially `ruby-lsp-rails`) are already in the Gemfile, then we shouldn't try
194
+ # to upgrade them or else we'll produce undesired source control changes. If the custom bundle was just created
195
+ # and any of `ruby-lsp`, `ruby-lsp-rails` or `debug` weren't a part of the Gemfile, then we need to run `bundle
196
+ # install` for the first time to generate the Gemfile.lock with them included or else Bundler will complain that
197
+ # they're missing. We can only update if the custom `.ruby-lsp/Gemfile.lock` already exists and includes all gems
186
198
 
187
199
  # When not updating, we run `(bundle check || bundle install)`
188
200
  # When updating, we run `((bundle check && bundle update ruby-lsp debug) || bundle install)`
189
201
  command = +"(bundle check"
190
202
 
191
203
  if should_bundle_update?
192
- # If ruby-lsp or debug are not in the Gemfile, try to update them to the latest version
204
+ # If any of `ruby-lsp`, `ruby-lsp-rails` or `debug` are not in the Gemfile, try to update them to the latest
205
+ # version
193
206
  command.prepend("(")
194
207
  command << " && bundle update "
195
208
  command << "ruby-lsp " unless @dependencies["ruby-lsp"]
196
209
  command << "debug " unless @dependencies["debug"]
210
+ command << "ruby-lsp-rails " if @dependencies["rails"] && !@dependencies["ruby-lsp-rails"]
197
211
  command << "--pre" if @experimental
198
212
  command.delete_suffix!(" ")
199
213
  command << ")"
@@ -208,24 +222,51 @@ module RubyLsp
208
222
  command << "1>&2"
209
223
 
210
224
  # Add bundle update
211
- warn("Ruby LSP> Running bundle install for the custom bundle. This may take a while...")
212
- warn("Ruby LSP> Command: #{command}")
225
+ $stderr.puts("Ruby LSP> Running bundle install for the custom bundle. This may take a while...")
226
+ $stderr.puts("Ruby LSP> Command: #{command}")
213
227
  system(env, command)
214
228
  [bundle_gemfile.to_s, expanded_path, env["BUNDLE_APP_CONFIG"]]
215
229
  end
216
230
 
217
231
  sig { returns(T::Boolean) }
218
232
  def should_bundle_update?
219
- # If both `ruby-lsp` and `debug` are in the Gemfile, then we shouldn't try to upgrade them or else it will produce
220
- # version control changes
221
- return false if @dependencies["ruby-lsp"] && @dependencies["debug"]
233
+ # If `ruby-lsp`, `ruby-lsp-rails` and `debug` are in the Gemfile, then we shouldn't try to upgrade them or else it
234
+ # will produce version control changes
235
+ if @dependencies["rails"]
236
+ return false if @dependencies.values_at("ruby-lsp", "ruby-lsp-rails", "debug").all?
237
+
238
+ # If the custom lockfile doesn't include `ruby-lsp`, `ruby-lsp-rails` or `debug`, we need to run bundle install
239
+ # before updating
240
+ return false if custom_bundle_dependencies.values_at("ruby-lsp", "debug", "ruby-lsp-rails").any?(&:nil?)
241
+ else
242
+ return false if @dependencies.values_at("ruby-lsp", "debug").all?
222
243
 
223
- # If the custom lockfile doesn't include either the `ruby-lsp` or `debug`, we need to run bundle install before
224
- # updating
225
- return false if custom_bundle_dependencies["ruby-lsp"].nil? || custom_bundle_dependencies["debug"].nil?
244
+ # If the custom lockfile doesn't include `ruby-lsp` or `debug`, we need to run bundle install before updating
245
+ return false if custom_bundle_dependencies.values_at("ruby-lsp", "debug").any?(&:nil?)
246
+ end
226
247
 
227
248
  # If the last updated file doesn't exist or was updated more than 4 hours ago, we should update
228
249
  !@last_updated_path.exist? || Time.parse(@last_updated_path.read) < (Time.now - FOUR_HOURS)
229
250
  end
251
+
252
+ # When a lockfile has remote references based on relative file paths, we need to ensure that they are pointing to
253
+ # the correct place since after copying the relative path is no longer valid
254
+ sig { void }
255
+ def correct_relative_remote_paths
256
+ content = @custom_lockfile.read
257
+ content.gsub!(/remote: (.*)/) do |match|
258
+ path = T.must(Regexp.last_match)[1]
259
+
260
+ # We should only apply the correction if the remote is a relative path. It might also be a URI, like
261
+ # `https://rubygems.org` or an absolute path, in which case we shouldn't do anything
262
+ if path&.start_with?(".")
263
+ "remote: #{File.expand_path(path, T.must(@gemfile).dirname)}"
264
+ else
265
+ match
266
+ end
267
+ end
268
+
269
+ @custom_lockfile.write(content)
270
+ end
230
271
  end
231
272
  end
@@ -23,6 +23,9 @@ module RubyLsp
23
23
  sig { returns(T::Hash[Symbol, RequestConfig]) }
24
24
  attr_accessor :features_configuration
25
25
 
26
+ sig { returns(String) }
27
+ attr_accessor :client_name
28
+
26
29
  sig { void }
27
30
  def initialize
28
31
  @state = T.let({}, T::Hash[String, Document])
@@ -33,10 +36,6 @@ module RubyLsp
33
36
  @workspace_uri = T.let(URI::Generic.from_path(path: Dir.pwd), URI::Generic)
34
37
  @features_configuration = T.let(
35
38
  {
36
- codeLens: RequestConfig.new({
37
- enableAll: false,
38
- gemfileLinks: true,
39
- }),
40
39
  inlayHint: RequestConfig.new({
41
40
  enableAll: false,
42
41
  implicitRescue: false,
@@ -45,6 +44,7 @@ module RubyLsp
45
44
  },
46
45
  T::Hash[Symbol, RequestConfig],
47
46
  )
47
+ @client_name = T.let("Unknown", String)
48
48
  end
49
49
 
50
50
  sig { params(uri: URI::Generic).returns(Document) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-lsp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.3
4
+ version: 0.14.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-01-11 00:00:00.000000000 Z
11
+ date: 2024-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: language_server-protocol
@@ -30,34 +30,34 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.19.0
33
+ version: 0.22.0
34
34
  - - "<"
35
35
  - !ruby/object:Gem::Version
36
- version: '0.20'
36
+ version: '0.25'
37
37
  type: :runtime
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
40
40
  requirements:
41
41
  - - ">="
42
42
  - !ruby/object:Gem::Version
43
- version: 0.19.0
43
+ version: 0.22.0
44
44
  - - "<"
45
45
  - !ruby/object:Gem::Version
46
- version: '0.20'
46
+ version: '0.25'
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: sorbet-runtime
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: 0.5.5685
53
+ version: 0.5.10782
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: 0.5.5685
60
+ version: 0.5.10782
61
61
  description: An opinionated language server for Ruby
62
62
  email:
63
63
  - ruby@shopify.com
@@ -97,7 +97,6 @@ files:
97
97
  - lib/ruby_lsp/document.rb
98
98
  - lib/ruby_lsp/executor.rb
99
99
  - lib/ruby_lsp/internal.rb
100
- - lib/ruby_lsp/listener.rb
101
100
  - lib/ruby_lsp/listeners/code_lens.rb
102
101
  - lib/ruby_lsp/listeners/completion.rb
103
102
  - lib/ruby_lsp/listeners/definition.rb
@@ -139,11 +138,17 @@ files:
139
138
  - lib/ruby_lsp/requests/support/rubocop_formatting_runner.rb
140
139
  - lib/ruby_lsp/requests/support/rubocop_runner.rb
141
140
  - lib/ruby_lsp/requests/support/selection_range.rb
142
- - lib/ruby_lsp/requests/support/semantic_token_encoder.rb
143
141
  - lib/ruby_lsp/requests/support/sorbet.rb
144
142
  - lib/ruby_lsp/requests/support/source_uri.rb
145
143
  - lib/ruby_lsp/requests/support/syntax_tree_formatting_runner.rb
146
144
  - lib/ruby_lsp/requests/workspace_symbol.rb
145
+ - lib/ruby_lsp/response_builders.rb
146
+ - lib/ruby_lsp/response_builders/collection_response_builder.rb
147
+ - lib/ruby_lsp/response_builders/document_symbol.rb
148
+ - lib/ruby_lsp/response_builders/hover.rb
149
+ - lib/ruby_lsp/response_builders/response_builder.rb
150
+ - lib/ruby_lsp/response_builders/semantic_highlighting.rb
151
+ - lib/ruby_lsp/response_builders/signature_help.rb
147
152
  - lib/ruby_lsp/ruby_document.rb
148
153
  - lib/ruby_lsp/server.rb
149
154
  - lib/ruby_lsp/setup_bundler.rb
@@ -154,6 +159,7 @@ licenses:
154
159
  - MIT
155
160
  metadata:
156
161
  allowed_push_host: https://rubygems.org
162
+ documentation_uri: https://shopify.github.io/ruby-lsp/
157
163
  post_install_message:
158
164
  rdoc_options: []
159
165
  require_paths:
@@ -169,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
169
175
  - !ruby/object:Gem::Version
170
176
  version: '0'
171
177
  requirements: []
172
- rubygems_version: 3.5.4
178
+ rubygems_version: 3.5.6
173
179
  signing_key:
174
180
  specification_version: 4
175
181
  summary: An opinionated language server for Ruby
@@ -1,33 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module RubyLsp
5
- # Listener is an abstract class to be used by requests for listening to events emitted when visiting an AST using the
6
- # Prism::Dispatcher.
7
- class Listener
8
- extend T::Sig
9
- extend T::Helpers
10
- extend T::Generic
11
- include Requests::Support::Common
12
-
13
- ResponseType = type_member
14
-
15
- abstract!
16
-
17
- sig { params(dispatcher: Prism::Dispatcher).void }
18
- def initialize(dispatcher)
19
- super()
20
- @dispatcher = dispatcher
21
- end
22
-
23
- sig { returns(ResponseType) }
24
- def response
25
- _response
26
- end
27
-
28
- # Override this method with an attr_reader that returns the response of your listener. The listener should
29
- # accumulate results in a @response variable and then provide the reader so that it is accessible
30
- sig { abstract.returns(ResponseType) }
31
- def _response; end
32
- end
33
- end
@@ -1,73 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module RubyLsp
5
- module Requests
6
- module Support
7
- class SemanticTokenEncoder
8
- extend T::Sig
9
-
10
- sig { void }
11
- def initialize
12
- @current_row = T.let(0, Integer)
13
- @current_column = T.let(0, Integer)
14
- end
15
-
16
- sig do
17
- params(
18
- tokens: T::Array[Listeners::SemanticHighlighting::SemanticToken],
19
- ).returns(Interface::SemanticTokens)
20
- end
21
- def encode(tokens)
22
- delta = tokens
23
- .sort_by do |token|
24
- [token.location.start_line, token.location.start_column]
25
- end
26
- .flat_map do |token|
27
- compute_delta(token)
28
- end
29
-
30
- Interface::SemanticTokens.new(data: delta)
31
- end
32
-
33
- # The delta array is computed according to the LSP specification:
34
- # > The protocol for the token format relative uses relative
35
- # > positions, because most tokens remain stable relative to
36
- # > each other when edits are made in a file. This simplifies
37
- # > the computation of a delta if a server supports it. So each
38
- # > token is represented using 5 integers.
39
-
40
- # For more information on how each number is calculated, read:
41
- # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_semanticTokens
42
- sig { params(token: Listeners::SemanticHighlighting::SemanticToken).returns(T::Array[Integer]) }
43
- def compute_delta(token)
44
- row = token.location.start_line - 1
45
- column = token.location.start_column
46
-
47
- begin
48
- delta_line = row - @current_row
49
-
50
- delta_column = column
51
- delta_column -= @current_column if delta_line == 0
52
-
53
- [delta_line, delta_column, token.length, token.type, encode_modifiers(token.modifier)]
54
- ensure
55
- @current_row = row
56
- @current_column = column
57
- end
58
- end
59
-
60
- # Encode an array of modifiers to positions onto a bit flag
61
- # For example, [:default_library] will be encoded as
62
- # 0b1000000000, as :default_library is the 10th bit according
63
- # to the token modifiers index map.
64
- sig { params(modifiers: T::Array[Integer]).returns(Integer) }
65
- def encode_modifiers(modifiers)
66
- modifiers.inject(0) do |encoded_modifiers, modifier|
67
- encoded_modifiers | (1 << modifier)
68
- end
69
- end
70
- end
71
- end
72
- end
73
- end