Skip to content

Commit

Permalink
Refactored the convert_to_byte_offset_position function
Browse files Browse the repository at this point in the history
  • Loading branch information
NotFounds committed Jun 4, 2024
1 parent be648a6 commit a661b98
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 38 deletions.
14 changes: 1 addition & 13 deletions lib/ruby_lsp/document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def locate(node, char_position, node_types: [])

# Skip if the current node doesn't cover the desired position
loc = candidate.location
char_byte_offset = convert_to_byte_offset(char_position)
char_byte_offset = RubyLsp.convert_to_byte_offset_position(source, char_position, encoding)
next unless (loc.start_offset...loc.end_offset).cover?(char_byte_offset)

# If the node's start character is already past the position, then we should've found the closest node
Expand Down Expand Up @@ -181,18 +181,6 @@ def sorbet_sigil_is_true_or_higher
end
end

sig { params(char_position: Integer).returns(Integer) }
def convert_to_byte_offset(char_position)
case encoding
when Encoding::UTF_8
source.slice(0, char_position).bytesize
when Encoding::UTF_16, Encoding::UTF_16LE, Encoding::UTF_16BE
char_position * 2
when Encoding::UTF_32
char_position * 4
end
end

class Scanner
extend T::Sig

Expand Down
4 changes: 3 additions & 1 deletion lib/ruby_lsp/requests/definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ def initialize(document, global_state, position, dispatcher, typechecker_enabled
node_types: [Prism::CallNode, Prism::ConstantReadNode, Prism::ConstantPathNode, Prism::BlockArgumentNode],
)

byte_offset_position = convert_to_byte_offset_position(document.source, position, global_state.encoding)
character = T.let(position[:character], Integer)
byte_offset = RubyLsp.convert_to_byte_offset_position(document.source, character, global_state.encoding)
byte_offset_position = T.let({ line: position[:line], character: byte_offset }, T::Hash[Symbol, Integer])
if target.is_a?(Prism::ConstantReadNode) && parent.is_a?(Prism::ConstantPathNode)
# If the target is part of a constant path node, we need to find the exact portion of the constant that the
# user is requesting to go to definition for
Expand Down
4 changes: 3 additions & 1 deletion lib/ruby_lsp/requests/hover.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ def initialize(document, global_state, position, dispatcher, typechecker_enabled
node_types: Listeners::Hover::ALLOWED_TARGETS,
)

byte_offset_position = convert_to_byte_offset_position(document.source, position, global_state.encoding)
character = T.let(position[:character], Integer)
byte_offset = RubyLsp.convert_to_byte_offset_position(document.source, character, global_state.encoding)
byte_offset_position = T.let({ line: position[:line], character: byte_offset }, T::Hash[Symbol, Integer])
if (Listeners::Hover::ALLOWED_TARGETS.include?(parent.class) &&
!Listeners::Hover::ALLOWED_TARGETS.include?(target.class)) ||
(parent.is_a?(Prism::ConstantPathNode) && target.is_a?(Prism::ConstantReadNode))
Expand Down
23 changes: 0 additions & 23 deletions lib/ruby_lsp/requests/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,29 +34,6 @@ def cover?(location, position)
start_covered && end_covered
end

sig do
params(source: String, position: T::Hash[Symbol, Integer], encoding: Encoding).returns(T::Hash[Symbol, Integer])
end
def convert_to_byte_offset_position(source, position, encoding)
char_position = position[:character]

byte_offset_pos = case encoding
when Encoding::UTF_8
source.slice(0, char_position).bytesize
when Encoding::UTF_16, Encoding::UTF_16LE, Encoding::UTF_16BE
char_position * 2
when Encoding::UTF_32
char_position * 4
else
raise InvalidFormatter, "Unsupported encoding: #{encoding}"
end

{
line: position[:line],
character: byte_offset_pos,
}
end

# Based on a constant node target, a constant path node parent and a position, this method will find the exact
# portion of the constant path that matches the requested position, for higher precision in hover and
# definition. For example:
Expand Down
18 changes: 18 additions & 0 deletions lib/ruby_lsp/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# frozen_string_literal: true

module RubyLsp
extend T::Sig

# rubocop:disable RubyLsp/UseLanguageServerAliases
Interface = LanguageServer::Protocol::Interface
Constant = LanguageServer::Protocol::Constant
Expand All @@ -26,6 +28,22 @@ module RubyLsp
String,
)

module_function

sig { params(source: String, char_position: Integer, encoding: Encoding).returns(Integer) }
def convert_to_byte_offset_position(source, char_position, encoding)
case encoding
when Encoding::UTF_8
source.slice(0, char_position)&.bytesize || 0
when Encoding::UTF_16, Encoding::UTF_16LE, Encoding::UTF_16BE
char_position * 2
when Encoding::UTF_32
char_position * 4
else
Kernel.raise RubyLsp::Requests::Request::InvalidFormatter, "Unsupported encoding: #{encoding}"
end
end

# A notification to be sent to the client
class Message
extend T::Sig
Expand Down

0 comments on commit a661b98

Please sign in to comment.