hind 0.1.6 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,255 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Hind
4
- module LSIF
5
- class Visitor < Prism::Visitor
6
- def initialize(generator)
7
- @generator = generator
8
- @current_scope = []
9
- end
10
-
11
- def visit_def_node(node)
12
- method_name = node.name.to_s
13
- qualified_name = current_scope_name.empty? ? method_name : "#{current_scope_name}##{method_name}"
14
-
15
- range_id = @generator.create_range(node.location, node.location)
16
- result_set_id = @generator.emit_vertex('resultSet')
17
- @generator.emit_edge('next', range_id, result_set_id)
18
-
19
- def_result_id = @generator.emit_vertex('definitionResult')
20
- @generator.emit_edge('textDocument/definition', result_set_id, def_result_id)
21
- @generator.emit_edge('item', def_result_id, [range_id], 'definitions')
22
-
23
- # Generate method signature for hover
24
- sig = []
25
- sig << "def #{qualified_name}"
26
- sig << "(#{node.parameters.slice})" if node.parameters
27
-
28
- hover_id = @generator.emit_vertex('hoverResult', {
29
- contents: [{
30
- language: 'ruby',
31
- value: sig.join
32
- }]
33
- })
34
- @generator.emit_edge('textDocument/hover', result_set_id, hover_id)
35
-
36
- @generator.add_to_global_state(qualified_name, result_set_id, range_id)
37
-
38
- super
39
- end
40
-
41
- def visit_class_node(node)
42
- @current_scope.push(node.constant_path.slice)
43
- class_name = current_scope_name
44
-
45
- range_id = @generator.create_range(node.location, node.location)
46
- result_set_id = @generator.emit_vertex('resultSet')
47
- @generator.emit_edge('next', range_id, result_set_id)
48
-
49
- def_result_id = @generator.emit_vertex('definitionResult')
50
- @generator.emit_edge('textDocument/definition', result_set_id, def_result_id)
51
- @generator.emit_edge('item', def_result_id, [range_id], 'definitions')
52
-
53
- # Generate hover with inheritance info
54
- hover = []
55
- class_def = "class #{class_name}"
56
- class_def += " < #{node.superclass.slice}" if node.superclass
57
-
58
- hover << if node.superclass
59
- "#{class_def}\n\nInherits from: #{node.superclass.slice}"
60
- else
61
- class_def
62
- end
63
-
64
- hover_id = @generator.emit_vertex('hoverResult', {
65
- contents: [{
66
- language: 'ruby',
67
- value: hover.join("\n")
68
- }]
69
- })
70
- @generator.emit_edge('textDocument/hover', result_set_id, hover_id)
71
-
72
- @generator.add_to_global_state(class_name, result_set_id, range_id)
73
-
74
- # Handle inheritance
75
- visit_inheritance(node.superclass) if node.superclass
76
-
77
- super
78
- @current_scope.pop
79
- end
80
-
81
- def visit_module_node(node)
82
- @current_scope.push(node.constant_path.slice)
83
- module_name = current_scope_name
84
-
85
- range_id = @generator.create_range(node.location, node.location)
86
- result_set_id = @generator.emit_vertex('resultSet')
87
- @generator.emit_edge('next', range_id, result_set_id)
88
-
89
- def_result_id = @generator.emit_vertex('definitionResult')
90
- @generator.emit_edge('textDocument/definition', result_set_id, def_result_id)
91
- @generator.emit_edge('item', def_result_id, [range_id], 'definitions')
92
-
93
- hover_id = @generator.emit_vertex('hoverResult', {
94
- contents: [{
95
- language: 'ruby',
96
- value: "module #{module_name}"
97
- }]
98
- })
99
- @generator.emit_edge('textDocument/hover', result_set_id, hover_id)
100
-
101
- @generator.add_to_global_state(module_name, result_set_id, range_id)
102
-
103
- super
104
- @current_scope.pop
105
- end
106
-
107
- def visit_call_node(node)
108
- return unless node.name && node.location
109
-
110
- method_name = node.name.to_s
111
- qualified_names = []
112
-
113
- # Try with current scope first
114
- qualified_names << "#{current_scope_name}##{method_name}" unless current_scope_name.empty?
115
-
116
- # Try with receiver's type if available
117
- if node.receiver
118
- case node.receiver.type
119
- when :constant_read
120
- qualified_names << "#{node.receiver.name}##{method_name}"
121
- when :call
122
- # Handle method chaining
123
- qualified_names << "#{node.receiver.name}##{method_name}" if node.receiver.name
124
- when :instance_variable_read
125
- # Handle instance variable calls
126
- qualified_names << "#{current_scope_name}##{method_name}" if current_scope_name
127
- end
128
- end
129
-
130
- # Try as a standalone method
131
- qualified_names << method_name
132
-
133
- # Add references for matching qualified names
134
- qualified_names.each do |qualified_name|
135
- next unless @generator.global_state.result_sets[qualified_name]
136
-
137
- range_id = @generator.create_range(node.location, node.location)
138
- @generator.global_state.add_reference(qualified_name, @generator.metadata[:uri], range_id)
139
- @generator.emit_edge('next', range_id, @generator.global_state.result_sets[qualified_name])
140
- break # Stop after finding first match
141
- end
142
-
143
- super
144
- end
145
-
146
- def visit_constant_read_node(node)
147
- return unless node.name
148
-
149
- constant_name = node.name.to_s
150
- qualified_name = @current_scope.empty? ? constant_name : "#{current_scope_name}::#{constant_name}"
151
-
152
- return unless @generator.global_state.result_sets[qualified_name]
153
-
154
- range_id = @generator.create_range(node.location, node.location)
155
- @generator.global_state.add_reference(qualified_name, @generator.metadata[:uri], range_id)
156
- @generator.emit_edge('next', range_id, @generator.global_state.result_sets[qualified_name])
157
-
158
- super
159
- end
160
-
161
- def visit_constant_write_node(node)
162
- return unless node.name
163
-
164
- constant_name = node.name.to_s
165
- qualified_name = @current_scope.empty? ? constant_name : "#{current_scope_name}::#{constant_name}"
166
-
167
- range_id = @generator.create_range(node.location, node.location)
168
- result_set_id = @generator.emit_vertex('resultSet')
169
- @generator.emit_edge('next', range_id, result_set_id)
170
-
171
- def_result_id = @generator.emit_vertex('definitionResult')
172
- @generator.emit_edge('textDocument/definition', result_set_id, def_result_id)
173
- @generator.emit_edge('item', def_result_id, [range_id], 'definitions')
174
-
175
- hover_id = @generator.emit_vertex('hoverResult', {
176
- contents: [{
177
- language: 'ruby',
178
- value: "#{qualified_name} = ..."
179
- }]
180
- })
181
- @generator.emit_edge('textDocument/hover', result_set_id, hover_id)
182
-
183
- @generator.add_to_global_state(qualified_name, result_set_id, range_id)
184
-
185
- super
186
- end
187
-
188
- def visit_instance_variable_read_node(node)
189
- return unless node.name && current_scope_name
190
-
191
- var_name = node.name.to_s
192
- qualified_name = "#{current_scope_name}##{var_name}"
193
-
194
- return unless @generator.global_state.result_sets[qualified_name]
195
-
196
- range_id = @generator.create_range(node.location, node.location)
197
- @generator.global_state.add_reference(qualified_name, @generator.metadata[:uri], range_id)
198
- @generator.emit_edge('next', range_id, @generator.global_state.result_sets[qualified_name])
199
-
200
- super
201
- end
202
-
203
- def visit_instance_variable_write_node(node)
204
- return unless node.name && current_scope_name
205
-
206
- var_name = node.name.to_s
207
- qualified_name = "#{current_scope_name}##{var_name}"
208
-
209
- range_id = @generator.create_range(node.location, node.location)
210
- result_set_id = @generator.emit_vertex('resultSet')
211
- @generator.emit_edge('next', range_id, result_set_id)
212
-
213
- def_result_id = @generator.emit_vertex('definitionResult')
214
- @generator.emit_edge('textDocument/definition', result_set_id, def_result_id)
215
- @generator.emit_edge('item', def_result_id, [range_id], 'definitions')
216
-
217
- hover_id = @generator.emit_vertex('hoverResult', {
218
- contents: [{
219
- language: 'ruby',
220
- value: "Instance variable #{var_name} in #{current_scope_name}"
221
- }]
222
- })
223
- @generator.emit_edge('textDocument/hover', result_set_id, hover_id)
224
-
225
- @generator.add_to_global_state(qualified_name, result_set_id, range_id)
226
-
227
- super
228
- end
229
-
230
- private
231
-
232
- def current_scope_name
233
- @current_scope.join('::')
234
- end
235
-
236
- def visit_inheritance(node)
237
- case node.type
238
- when :constant_read_node, :constant_path_node
239
- range_id = @generator.create_range(node.location, node.location)
240
- qualified_name = case node.type
241
- when :constant_read_node
242
- node.name.to_s
243
- when :constant_path_node
244
- node.slice
245
- end
246
-
247
- return unless @generator.global_state.result_sets[qualified_name]
248
-
249
- @generator.global_state.add_reference(qualified_name, @generator.metadata[:uri], range_id)
250
- @generator.emit_edge('next', range_id, @generator.global_state.result_sets[qualified_name])
251
- end
252
- end
253
- end
254
- end
255
- end