@@ -12,10 +12,13 @@ class LanguageId < T::Enum
12
12
13
13
extend T ::Sig
14
14
extend T ::Helpers
15
+ extend T ::Generic
16
+
17
+ ParseResultType = type_member
15
18
16
19
abstract!
17
20
18
- sig { returns ( Prism :: ParseResult ) }
21
+ sig { returns ( ParseResultType ) }
19
22
attr_reader :parse_result
20
23
21
24
sig { returns ( String ) }
@@ -38,10 +41,10 @@ def initialize(source:, version:, uri:, encoding: Encoding::UTF_8)
38
41
@version = T . let ( version , Integer )
39
42
@uri = T . let ( uri , URI ::Generic )
40
43
@needs_parsing = T . let ( true , T ::Boolean )
41
- @parse_result = T . let ( parse , Prism :: ParseResult )
44
+ @parse_result = T . let ( parse , ParseResultType )
42
45
end
43
46
44
- sig { params ( other : Document ) . returns ( T ::Boolean ) }
47
+ sig { params ( other : Document [ T . untyped ] ) . returns ( T ::Boolean ) }
45
48
def ==( other )
46
49
self . class == other . class && uri == other . uri && @source == other . source
47
50
end
@@ -54,7 +57,7 @@ def language_id; end
54
57
type_parameters ( :T )
55
58
. params (
56
59
request_name : String ,
57
- block : T . proc . params ( document : Document ) . returns ( T . type_parameter ( :T ) ) ,
60
+ block : T . proc . params ( document : Document [ ParseResultType ] ) . returns ( T . type_parameter ( :T ) ) ,
58
61
) . returns ( T . type_parameter ( :T ) )
59
62
end
60
63
def cache_fetch ( request_name , &block )
@@ -93,7 +96,7 @@ def push_edits(edits, version:)
93
96
@cache . clear
94
97
end
95
98
96
- sig { abstract . returns ( Prism :: ParseResult ) }
99
+ sig { abstract . returns ( ParseResultType ) }
97
100
def parse ; end
98
101
99
102
sig { abstract . returns ( T ::Boolean ) }
@@ -104,115 +107,6 @@ def create_scanner
104
107
Scanner . new ( @source , @encoding )
105
108
end
106
109
107
- sig do
108
- params (
109
- position : T ::Hash [ Symbol , T . untyped ] ,
110
- node_types : T ::Array [ T . class_of ( Prism ::Node ) ] ,
111
- ) . returns ( NodeContext )
112
- end
113
- def locate_node ( position , node_types : [ ] )
114
- locate ( @parse_result . value , create_scanner . find_char_position ( position ) , node_types : node_types )
115
- end
116
-
117
- sig do
118
- params (
119
- node : Prism ::Node ,
120
- char_position : Integer ,
121
- node_types : T ::Array [ T . class_of ( Prism ::Node ) ] ,
122
- ) . returns ( NodeContext )
123
- end
124
- def locate ( node , char_position , node_types : [ ] )
125
- queue = T . let ( node . child_nodes . compact , T ::Array [ T . nilable ( Prism ::Node ) ] )
126
- closest = node
127
- parent = T . let ( nil , T . nilable ( Prism ::Node ) )
128
- nesting_nodes = T . let (
129
- [ ] ,
130
- T ::Array [ T . any (
131
- Prism ::ClassNode ,
132
- Prism ::ModuleNode ,
133
- Prism ::SingletonClassNode ,
134
- Prism ::DefNode ,
135
- Prism ::BlockNode ,
136
- Prism ::LambdaNode ,
137
- Prism ::ProgramNode ,
138
- ) ] ,
139
- )
140
-
141
- nesting_nodes << node if node . is_a? ( Prism ::ProgramNode )
142
- call_node = T . let ( nil , T . nilable ( Prism ::CallNode ) )
143
-
144
- until queue . empty?
145
- candidate = queue . shift
146
-
147
- # Skip nil child nodes
148
- next if candidate . nil?
149
-
150
- # Add the next child_nodes to the queue to be processed. The order here is important! We want to move in the
151
- # same order as the visiting mechanism, which means searching the child nodes before moving on to the next
152
- # sibling
153
- T . unsafe ( queue ) . unshift ( *candidate . child_nodes )
154
-
155
- # Skip if the current node doesn't cover the desired position
156
- loc = candidate . location
157
- next unless ( loc . start_offset ...loc . end_offset ) . cover? ( char_position )
158
-
159
- # If the node's start character is already past the position, then we should've found the closest node
160
- # already
161
- break if char_position < loc . start_offset
162
-
163
- # If the candidate starts after the end of the previous nesting level, then we've exited that nesting level and
164
- # need to pop the stack
165
- previous_level = nesting_nodes . last
166
- nesting_nodes . pop if previous_level && loc . start_offset > previous_level . location . end_offset
167
-
168
- # Keep track of the nesting where we found the target. This is used to determine the fully qualified name of the
169
- # target when it is a constant
170
- case candidate
171
- when Prism ::ClassNode , Prism ::ModuleNode , Prism ::SingletonClassNode , Prism ::DefNode , Prism ::BlockNode ,
172
- Prism ::LambdaNode
173
- nesting_nodes << candidate
174
- end
175
-
176
- if candidate . is_a? ( Prism ::CallNode )
177
- arg_loc = candidate . arguments &.location
178
- blk_loc = candidate . block &.location
179
- if ( arg_loc && ( arg_loc . start_offset ...arg_loc . end_offset ) . cover? ( char_position ) ) ||
180
- ( blk_loc && ( blk_loc . start_offset ...blk_loc . end_offset ) . cover? ( char_position ) )
181
- call_node = candidate
182
- end
183
- end
184
-
185
- # If there are node types to filter by, and the current node is not one of those types, then skip it
186
- next if node_types . any? && node_types . none? { |type | candidate . class == type }
187
-
188
- # If the current node is narrower than or equal to the previous closest node, then it is more precise
189
- closest_loc = closest . location
190
- if loc . end_offset - loc . start_offset <= closest_loc . end_offset - closest_loc . start_offset
191
- parent = closest
192
- closest = candidate
193
- end
194
- end
195
-
196
- # When targeting the constant part of a class/module definition, we do not want the nesting to be duplicated. That
197
- # is, when targeting Bar in the following example:
198
- #
199
- # ```ruby
200
- # class Foo::Bar; end
201
- # ```
202
- # The correct target is `Foo::Bar` with an empty nesting. `Foo::Bar` should not appear in the nesting stack, even
203
- # though the class/module node does indeed enclose the target, because it would lead to incorrect behavior
204
- if closest . is_a? ( Prism ::ConstantReadNode ) || closest . is_a? ( Prism ::ConstantPathNode )
205
- last_level = nesting_nodes . last
206
-
207
- if ( last_level . is_a? ( Prism ::ModuleNode ) || last_level . is_a? ( Prism ::ClassNode ) ) &&
208
- last_level . constant_path == closest
209
- nesting_nodes . pop
210
- end
211
- end
212
-
213
- NodeContext . new ( closest , parent , nesting_nodes , call_node )
214
- end
215
-
216
110
class Scanner
217
111
extend T ::Sig
218
112
0 commit comments