@@ -26,9 +26,10 @@ class << self
2626 node : Prism ::Node ,
2727 char_position : Integer ,
2828 node_types : T ::Array [ T . class_of ( Prism ::Node ) ] ,
29+ encoding : Encoding ,
2930 ) . returns ( NodeContext )
3031 end
31- def locate ( node , char_position , node_types : [ ] )
32+ def locate ( node , char_position , node_types : [ ] , encoding : Encoding :: UTF_8 )
3233 queue = T . let ( node . child_nodes . compact , T ::Array [ T . nilable ( Prism ::Node ) ] )
3334 closest = node
3435 parent = T . let ( nil , T . nilable ( Prism ::Node ) )
@@ -61,16 +62,21 @@ def locate(node, char_position, node_types: [])
6162
6263 # Skip if the current node doesn't cover the desired position
6364 loc = candidate . location
64- next unless ( loc . start_offset ...loc . end_offset ) . cover? ( char_position )
65+ loc_start_offset = loc . start_code_units_offset ( encoding )
66+ loc_end_offset = loc . end_code_units_offset ( encoding )
67+ next unless ( loc_start_offset ...loc_end_offset ) . cover? ( char_position )
6568
6669 # If the node's start character is already past the position, then we should've found the closest node
6770 # already
68- break if char_position < loc . start_offset
71+ break if char_position < loc_start_offset
6972
7073 # If the candidate starts after the end of the previous nesting level, then we've exited that nesting level
7174 # and need to pop the stack
7275 previous_level = nesting_nodes . last
73- nesting_nodes . pop if previous_level && loc . start_offset > previous_level . location . end_offset
76+ if previous_level &&
77+ ( loc_start_offset > previous_level . location . end_code_units_offset ( encoding ) )
78+ nesting_nodes . pop
79+ end
7480
7581 # Keep track of the nesting where we found the target. This is used to determine the fully qualified name of
7682 # the target when it is a constant
@@ -83,8 +89,10 @@ def locate(node, char_position, node_types: [])
8389 if candidate . is_a? ( Prism ::CallNode )
8490 arg_loc = candidate . arguments &.location
8591 blk_loc = candidate . block &.location
86- if ( arg_loc && ( arg_loc . start_offset ...arg_loc . end_offset ) . cover? ( char_position ) ) ||
87- ( blk_loc && ( blk_loc . start_offset ...blk_loc . end_offset ) . cover? ( char_position ) )
92+ if ( arg_loc && ( arg_loc . start_code_units_offset ( encoding ) ...
93+ arg_loc . end_code_units_offset ( encoding ) ) . cover? ( char_position ) ) ||
94+ ( blk_loc && ( blk_loc . start_code_units_offset ( encoding ) ...
95+ blk_loc . end_code_units_offset ( encoding ) ) . cover? ( char_position ) )
8896 call_node = candidate
8997 end
9098 end
@@ -94,7 +102,9 @@ def locate(node, char_position, node_types: [])
94102
95103 # If the current node is narrower than or equal to the previous closest node, then it is more precise
96104 closest_loc = closest . location
97- if loc . end_offset - loc . start_offset <= closest_loc . end_offset - closest_loc . start_offset
105+ closest_node_start_offset = closest_loc . start_code_units_offset ( encoding )
106+ closest_node_end_offset = closest_loc . end_code_units_offset ( encoding )
107+ if loc_end_offset - loc_start_offset <= closest_node_end_offset - closest_node_start_offset
98108 parent = closest
99109 closest = candidate
100110 end
@@ -201,7 +211,12 @@ def locate_first_within_range(range, node_types: [])
201211 ) . returns ( NodeContext )
202212 end
203213 def locate_node ( position , node_types : [ ] )
204- RubyDocument . locate ( @parse_result . value , create_scanner . find_char_position ( position ) , node_types : node_types )
214+ RubyDocument . locate (
215+ @parse_result . value ,
216+ create_scanner . find_char_position ( position ) ,
217+ node_types : node_types ,
218+ encoding : @encoding ,
219+ )
205220 end
206221 end
207222end
0 commit comments