hind 0.1.5 → 0.1.6
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.
- checksums.yaml +4 -4
- data/exe/hind +2 -2
- data/lib/hind/cli.rb +189 -68
- data/lib/hind/lsif/generator.rb +219 -91
- data/lib/hind/lsif/global_state.rb +150 -11
- data/lib/hind/lsif/visitor.rb +28 -41
- data/lib/hind/lsif/visitors/declaration_visitor.rb +239 -0
- data/lib/hind/lsif/visitors/reference_visitor.rb +221 -0
- data/lib/hind/version.rb +1 -1
- metadata +4 -2
data/lib/hind/lsif/visitor.rb
CHANGED
@@ -1,31 +1,14 @@
|
|
1
|
-
# lib/hind/lsif/visitor.rb
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
module Hind
|
5
4
|
module LSIF
|
6
|
-
class Visitor
|
5
|
+
class Visitor < Prism::Visitor
|
7
6
|
def initialize(generator)
|
8
7
|
@generator = generator
|
9
8
|
@current_scope = []
|
10
9
|
end
|
11
10
|
|
12
|
-
def
|
13
|
-
return unless node
|
14
|
-
|
15
|
-
method_name = "visit_#{node.class.name.split("::").last.downcase}"
|
16
|
-
if respond_to?(method_name)
|
17
|
-
send(method_name, node)
|
18
|
-
else
|
19
|
-
visit_children(node)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def visit_children(node)
|
24
|
-
node.child_nodes.each { |child| visit(child) if child }
|
25
|
-
end
|
26
|
-
|
27
|
-
def visit_defnode(node)
|
28
|
-
# Handle method definitions
|
11
|
+
def visit_def_node(node)
|
29
12
|
method_name = node.name.to_s
|
30
13
|
qualified_name = current_scope_name.empty? ? method_name : "#{current_scope_name}##{method_name}"
|
31
14
|
|
@@ -52,10 +35,10 @@ module Hind
|
|
52
35
|
|
53
36
|
@generator.add_to_global_state(qualified_name, result_set_id, range_id)
|
54
37
|
|
55
|
-
|
38
|
+
super
|
56
39
|
end
|
57
40
|
|
58
|
-
def
|
41
|
+
def visit_class_node(node)
|
59
42
|
@current_scope.push(node.constant_path.slice)
|
60
43
|
class_name = current_scope_name
|
61
44
|
|
@@ -91,11 +74,11 @@ module Hind
|
|
91
74
|
# Handle inheritance
|
92
75
|
visit_inheritance(node.superclass) if node.superclass
|
93
76
|
|
94
|
-
|
77
|
+
super
|
95
78
|
@current_scope.pop
|
96
79
|
end
|
97
80
|
|
98
|
-
def
|
81
|
+
def visit_module_node(node)
|
99
82
|
@current_scope.push(node.constant_path.slice)
|
100
83
|
module_name = current_scope_name
|
101
84
|
|
@@ -117,11 +100,11 @@ module Hind
|
|
117
100
|
|
118
101
|
@generator.add_to_global_state(module_name, result_set_id, range_id)
|
119
102
|
|
120
|
-
|
103
|
+
super
|
121
104
|
@current_scope.pop
|
122
105
|
end
|
123
106
|
|
124
|
-
def
|
107
|
+
def visit_call_node(node)
|
125
108
|
return unless node.name && node.location
|
126
109
|
|
127
110
|
method_name = node.name.to_s
|
@@ -132,13 +115,13 @@ module Hind
|
|
132
115
|
|
133
116
|
# Try with receiver's type if available
|
134
117
|
if node.receiver
|
135
|
-
case node.receiver
|
136
|
-
when
|
118
|
+
case node.receiver.type
|
119
|
+
when :constant_read
|
137
120
|
qualified_names << "#{node.receiver.name}##{method_name}"
|
138
|
-
when
|
121
|
+
when :call
|
139
122
|
# Handle method chaining
|
140
123
|
qualified_names << "#{node.receiver.name}##{method_name}" if node.receiver.name
|
141
|
-
when
|
124
|
+
when :instance_variable_read
|
142
125
|
# Handle instance variable calls
|
143
126
|
qualified_names << "#{current_scope_name}##{method_name}" if current_scope_name
|
144
127
|
end
|
@@ -157,10 +140,10 @@ module Hind
|
|
157
140
|
break # Stop after finding first match
|
158
141
|
end
|
159
142
|
|
160
|
-
|
143
|
+
super
|
161
144
|
end
|
162
145
|
|
163
|
-
def
|
146
|
+
def visit_constant_read_node(node)
|
164
147
|
return unless node.name
|
165
148
|
|
166
149
|
constant_name = node.name.to_s
|
@@ -171,9 +154,11 @@ module Hind
|
|
171
154
|
range_id = @generator.create_range(node.location, node.location)
|
172
155
|
@generator.global_state.add_reference(qualified_name, @generator.metadata[:uri], range_id)
|
173
156
|
@generator.emit_edge('next', range_id, @generator.global_state.result_sets[qualified_name])
|
157
|
+
|
158
|
+
super
|
174
159
|
end
|
175
160
|
|
176
|
-
def
|
161
|
+
def visit_constant_write_node(node)
|
177
162
|
return unless node.name
|
178
163
|
|
179
164
|
constant_name = node.name.to_s
|
@@ -197,10 +182,10 @@ module Hind
|
|
197
182
|
|
198
183
|
@generator.add_to_global_state(qualified_name, result_set_id, range_id)
|
199
184
|
|
200
|
-
|
185
|
+
super
|
201
186
|
end
|
202
187
|
|
203
|
-
def
|
188
|
+
def visit_instance_variable_read_node(node)
|
204
189
|
return unless node.name && current_scope_name
|
205
190
|
|
206
191
|
var_name = node.name.to_s
|
@@ -211,9 +196,11 @@ module Hind
|
|
211
196
|
range_id = @generator.create_range(node.location, node.location)
|
212
197
|
@generator.global_state.add_reference(qualified_name, @generator.metadata[:uri], range_id)
|
213
198
|
@generator.emit_edge('next', range_id, @generator.global_state.result_sets[qualified_name])
|
199
|
+
|
200
|
+
super
|
214
201
|
end
|
215
202
|
|
216
|
-
def
|
203
|
+
def visit_instance_variable_write_node(node)
|
217
204
|
return unless node.name && current_scope_name
|
218
205
|
|
219
206
|
var_name = node.name.to_s
|
@@ -237,7 +224,7 @@ module Hind
|
|
237
224
|
|
238
225
|
@generator.add_to_global_state(qualified_name, result_set_id, range_id)
|
239
226
|
|
240
|
-
|
227
|
+
super
|
241
228
|
end
|
242
229
|
|
243
230
|
private
|
@@ -247,13 +234,13 @@ module Hind
|
|
247
234
|
end
|
248
235
|
|
249
236
|
def visit_inheritance(node)
|
250
|
-
case node
|
251
|
-
when
|
237
|
+
case node.type
|
238
|
+
when :constant_read_node, :constant_path_node
|
252
239
|
range_id = @generator.create_range(node.location, node.location)
|
253
|
-
qualified_name = case node
|
254
|
-
when
|
240
|
+
qualified_name = case node.type
|
241
|
+
when :constant_read_node
|
255
242
|
node.name.to_s
|
256
|
-
when
|
243
|
+
when :constant_path_node
|
257
244
|
node.slice
|
258
245
|
end
|
259
246
|
|
@@ -0,0 +1,239 @@
|
|
1
|
+
# lib/hind/lsif/visitors/declaration_visitor.rb
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Hind
|
5
|
+
module LSIF
|
6
|
+
class DeclarationVisitor < Prism::Visitor
|
7
|
+
attr_reader :current_scope
|
8
|
+
|
9
|
+
def initialize(generator, file_path)
|
10
|
+
@generator = generator
|
11
|
+
@file_path = file_path
|
12
|
+
@current_scope = []
|
13
|
+
@current_visibility = :public
|
14
|
+
@visibility_stack = []
|
15
|
+
@in_singleton_class = false
|
16
|
+
end
|
17
|
+
|
18
|
+
def visit_class_node(node)
|
19
|
+
@current_scope.push(node.constant_path.slice)
|
20
|
+
class_name = current_scope_name
|
21
|
+
|
22
|
+
# Register class declaration
|
23
|
+
@generator.register_declaration({
|
24
|
+
type: :class,
|
25
|
+
name: class_name,
|
26
|
+
node: node,
|
27
|
+
scope: @current_scope[0..-2].join('::'),
|
28
|
+
superclass: node.superclass&.slice
|
29
|
+
})
|
30
|
+
|
31
|
+
# Process the class body with proper scope and visibility
|
32
|
+
push_visibility(:public)
|
33
|
+
super
|
34
|
+
pop_visibility
|
35
|
+
@current_scope.pop
|
36
|
+
end
|
37
|
+
|
38
|
+
def visit_module_node(node)
|
39
|
+
@current_scope.push(node.constant_path.slice)
|
40
|
+
module_name = current_scope_name
|
41
|
+
|
42
|
+
@generator.register_declaration({
|
43
|
+
type: :module,
|
44
|
+
name: module_name,
|
45
|
+
node: node,
|
46
|
+
scope: @current_scope[0..-2].join('::')
|
47
|
+
})
|
48
|
+
|
49
|
+
push_visibility(:public)
|
50
|
+
super
|
51
|
+
pop_visibility
|
52
|
+
@current_scope.pop
|
53
|
+
end
|
54
|
+
|
55
|
+
def visit_def_node(node)
|
56
|
+
method_name = node.name.to_s
|
57
|
+
# Use '#' for instance methods
|
58
|
+
qualified_name = @in_singleton_class ?
|
59
|
+
"#{current_scope_name}.#{method_name}" :
|
60
|
+
"#{current_scope_name}##{method_name}"
|
61
|
+
|
62
|
+
@generator.register_declaration({
|
63
|
+
type: :method,
|
64
|
+
name: qualified_name,
|
65
|
+
node: node,
|
66
|
+
scope: current_scope_name,
|
67
|
+
visibility: current_visibility,
|
68
|
+
params: node.parameters&.slice,
|
69
|
+
instance_method: !@in_singleton_class
|
70
|
+
})
|
71
|
+
|
72
|
+
super
|
73
|
+
end
|
74
|
+
|
75
|
+
def visit_constant_write_node(node)
|
76
|
+
return unless node.name
|
77
|
+
|
78
|
+
constant_name = node.name.to_s
|
79
|
+
qualified_name = @current_scope.empty? ? constant_name : "#{current_scope_name}::#{constant_name}"
|
80
|
+
|
81
|
+
@generator.register_declaration({
|
82
|
+
type: :constant,
|
83
|
+
name: qualified_name,
|
84
|
+
node: node,
|
85
|
+
scope: current_scope_name
|
86
|
+
})
|
87
|
+
|
88
|
+
super
|
89
|
+
end
|
90
|
+
|
91
|
+
def visit_singleton_class_node(node)
|
92
|
+
if node.expression.is_a?(Prism::SelfNode)
|
93
|
+
# class << self
|
94
|
+
@in_singleton_class = true
|
95
|
+
super
|
96
|
+
@in_singleton_class = false
|
97
|
+
else
|
98
|
+
# Process regular singleton class
|
99
|
+
super
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def visit_call_node(node)
|
104
|
+
method_name = node.name.to_s
|
105
|
+
case method_name
|
106
|
+
when 'private', 'protected', 'public'
|
107
|
+
handle_visibility_method(node)
|
108
|
+
when 'attr_reader', 'attr_writer', 'attr_accessor'
|
109
|
+
handle_attribute_method(node)
|
110
|
+
end
|
111
|
+
|
112
|
+
super
|
113
|
+
end
|
114
|
+
|
115
|
+
def visit_class_variable_write_node(node)
|
116
|
+
return unless node.name
|
117
|
+
|
118
|
+
var_name = node.name.to_s
|
119
|
+
qualified_name = "#{current_scope_name}::#{var_name}"
|
120
|
+
|
121
|
+
@generator.register_declaration({
|
122
|
+
type: :class_variable,
|
123
|
+
name: qualified_name,
|
124
|
+
node: node,
|
125
|
+
scope: current_scope_name
|
126
|
+
})
|
127
|
+
|
128
|
+
super
|
129
|
+
end
|
130
|
+
|
131
|
+
def visit_instance_variable_write_node(node)
|
132
|
+
return unless node.name && current_scope_name
|
133
|
+
|
134
|
+
var_name = node.name.to_s
|
135
|
+
qualified_name = "#{current_scope_name}##{var_name}"
|
136
|
+
|
137
|
+
@generator.register_declaration({
|
138
|
+
type: :instance_variable,
|
139
|
+
name: qualified_name,
|
140
|
+
node: node,
|
141
|
+
scope: current_scope_name
|
142
|
+
})
|
143
|
+
|
144
|
+
super
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def current_scope_name
|
150
|
+
@current_scope.join('::')
|
151
|
+
end
|
152
|
+
|
153
|
+
def current_visibility
|
154
|
+
@current_visibility
|
155
|
+
end
|
156
|
+
|
157
|
+
def push_visibility(visibility)
|
158
|
+
@visibility_stack.push(@current_visibility)
|
159
|
+
@current_visibility = visibility
|
160
|
+
end
|
161
|
+
|
162
|
+
def pop_visibility
|
163
|
+
@current_visibility = @visibility_stack.pop || :public
|
164
|
+
end
|
165
|
+
|
166
|
+
def handle_visibility_method(node)
|
167
|
+
visibility = node.name.to_sym
|
168
|
+
|
169
|
+
if node.arguments&.arguments&.empty?
|
170
|
+
# Global visibility change
|
171
|
+
@current_visibility = visibility
|
172
|
+
elsif node.arguments
|
173
|
+
# Per-method visibility change
|
174
|
+
node.arguments.arguments.each do |arg|
|
175
|
+
next unless arg.is_a?(Prism::SymbolNode) || arg.is_a?(Prism::StringNode)
|
176
|
+
|
177
|
+
method_name = arg.value.to_s
|
178
|
+
qualified_name = "#{current_scope_name}##{method_name}"
|
179
|
+
|
180
|
+
if @generator.global_state.has_declaration?(qualified_name)
|
181
|
+
@generator.global_state.get_declaration(qualified_name)[:visibility] = visibility
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def handle_attribute_method(node)
|
188
|
+
return unless node.arguments
|
189
|
+
|
190
|
+
attr_type = node.name.to_s
|
191
|
+
node.arguments.arguments.each do |arg|
|
192
|
+
next unless arg.respond_to?(:value)
|
193
|
+
|
194
|
+
attr_name = arg.value.to_s
|
195
|
+
register_attribute(attr_name, attr_type)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def register_attribute(attr_name, attr_type)
|
200
|
+
base_name = "#{current_scope_name}##{attr_name}"
|
201
|
+
|
202
|
+
# Register reader method if applicable
|
203
|
+
if %w[attr_reader attr_accessor].include?(attr_type)
|
204
|
+
@generator.register_declaration({
|
205
|
+
type: :method,
|
206
|
+
name: base_name,
|
207
|
+
node: nil, # Synthetic node
|
208
|
+
scope: current_scope_name,
|
209
|
+
visibility: current_visibility,
|
210
|
+
synthetic: true,
|
211
|
+
kind: :reader
|
212
|
+
})
|
213
|
+
end
|
214
|
+
|
215
|
+
# Register writer method if applicable
|
216
|
+
if %w[attr_writer attr_accessor].include?(attr_type)
|
217
|
+
@generator.register_declaration({
|
218
|
+
type: :method,
|
219
|
+
name: "#{base_name}=",
|
220
|
+
node: nil, # Synthetic node
|
221
|
+
scope: current_scope_name,
|
222
|
+
visibility: current_visibility,
|
223
|
+
synthetic: true,
|
224
|
+
kind: :writer
|
225
|
+
})
|
226
|
+
end
|
227
|
+
|
228
|
+
# Register the instance variable
|
229
|
+
@generator.register_declaration({
|
230
|
+
type: :instance_variable,
|
231
|
+
name: "@#{attr_name}",
|
232
|
+
node: nil, # Synthetic node
|
233
|
+
scope: current_scope_name,
|
234
|
+
synthetic: true
|
235
|
+
})
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
@@ -0,0 +1,221 @@
|
|
1
|
+
# lib/hind/lsif/visitors/reference_visitor.rb
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Hind
|
5
|
+
module LSIF
|
6
|
+
class ReferenceVisitor < Prism::Visitor
|
7
|
+
attr_reader :current_scope
|
8
|
+
|
9
|
+
def initialize(generator, file_path)
|
10
|
+
@generator = generator
|
11
|
+
@file_path = file_path
|
12
|
+
@current_scope = []
|
13
|
+
end
|
14
|
+
|
15
|
+
# Method calls
|
16
|
+
def visit_call_node(node)
|
17
|
+
return unless node.name && node.location
|
18
|
+
|
19
|
+
method_name = node.name.to_s
|
20
|
+
qualified_names = generate_qualified_names_for_call(node)
|
21
|
+
|
22
|
+
qualified_names.each do |qualified_name|
|
23
|
+
@generator.register_reference({
|
24
|
+
type: :method,
|
25
|
+
name: qualified_name,
|
26
|
+
node: node,
|
27
|
+
scope: current_scope_name,
|
28
|
+
call_type: :instance_method
|
29
|
+
})
|
30
|
+
end
|
31
|
+
|
32
|
+
super
|
33
|
+
end
|
34
|
+
|
35
|
+
# Class/module references
|
36
|
+
def visit_constant_read_node(node)
|
37
|
+
return unless node.name
|
38
|
+
|
39
|
+
constant_name = node.name.to_s
|
40
|
+
qualified_name = @current_scope.empty? ? constant_name : "#{current_scope_name}::#{constant_name}"
|
41
|
+
|
42
|
+
@generator.register_reference({
|
43
|
+
type: :constant,
|
44
|
+
name: qualified_name,
|
45
|
+
node: node,
|
46
|
+
scope: current_scope_name
|
47
|
+
})
|
48
|
+
|
49
|
+
super
|
50
|
+
end
|
51
|
+
|
52
|
+
# Constant path references (e.g., A::B::C)
|
53
|
+
def visit_constant_path_node(node)
|
54
|
+
qualified_name = node.slice
|
55
|
+
|
56
|
+
@generator.register_reference({
|
57
|
+
type: :constant,
|
58
|
+
name: qualified_name,
|
59
|
+
node: node,
|
60
|
+
scope: current_scope_name
|
61
|
+
})
|
62
|
+
|
63
|
+
super
|
64
|
+
end
|
65
|
+
|
66
|
+
# Instance variable references
|
67
|
+
def visit_instance_variable_read_node(node)
|
68
|
+
return unless node.name && current_scope_name
|
69
|
+
|
70
|
+
var_name = node.name.to_s
|
71
|
+
qualified_name = "#{current_scope_name}##{var_name}"
|
72
|
+
|
73
|
+
@generator.register_reference({
|
74
|
+
type: :instance_variable,
|
75
|
+
name: qualified_name,
|
76
|
+
node: node,
|
77
|
+
scope: current_scope_name
|
78
|
+
})
|
79
|
+
|
80
|
+
super
|
81
|
+
end
|
82
|
+
|
83
|
+
# Class variable references
|
84
|
+
def visit_class_variable_read_node(node)
|
85
|
+
return unless node.name && current_scope_name
|
86
|
+
|
87
|
+
var_name = node.name.to_s
|
88
|
+
qualified_name = "#{current_scope_name}::#{var_name}"
|
89
|
+
|
90
|
+
@generator.register_reference({
|
91
|
+
type: :class_variable,
|
92
|
+
name: qualified_name,
|
93
|
+
node: node,
|
94
|
+
scope: current_scope_name
|
95
|
+
})
|
96
|
+
|
97
|
+
super
|
98
|
+
end
|
99
|
+
|
100
|
+
# Singleton method calls (class methods)
|
101
|
+
def visit_constant_path_call_node(node)
|
102
|
+
return unless node.name
|
103
|
+
|
104
|
+
method_name = node.name.to_s
|
105
|
+
receiver_name = node.receiver.slice
|
106
|
+
qualified_name = "#{receiver_name}.#{method_name}"
|
107
|
+
|
108
|
+
@generator.register_reference({
|
109
|
+
type: :method,
|
110
|
+
name: qualified_name,
|
111
|
+
node: node,
|
112
|
+
scope: current_scope_name,
|
113
|
+
call_type: :class_method
|
114
|
+
})
|
115
|
+
|
116
|
+
super
|
117
|
+
end
|
118
|
+
|
119
|
+
# Super method calls
|
120
|
+
def visit_super_node(node)
|
121
|
+
return unless current_scope_name
|
122
|
+
|
123
|
+
# Extract current method name from scope
|
124
|
+
current_method = current_method_name
|
125
|
+
return unless current_method
|
126
|
+
|
127
|
+
# Try to find the superclass method
|
128
|
+
if in_class_scope?
|
129
|
+
superclass = find_superclass
|
130
|
+
if superclass
|
131
|
+
qualified_name = "#{superclass}##{current_method}"
|
132
|
+
|
133
|
+
@generator.register_reference({
|
134
|
+
type: :method,
|
135
|
+
name: qualified_name,
|
136
|
+
node: node,
|
137
|
+
scope: current_scope_name,
|
138
|
+
call_type: :super
|
139
|
+
})
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
super
|
144
|
+
end
|
145
|
+
|
146
|
+
# Track class/module scope
|
147
|
+
def visit_class_node(node)
|
148
|
+
@current_scope.push(node.constant_path.slice)
|
149
|
+
super
|
150
|
+
@current_scope.pop
|
151
|
+
end
|
152
|
+
|
153
|
+
def visit_module_node(node)
|
154
|
+
@current_scope.push(node.constant_path.slice)
|
155
|
+
super
|
156
|
+
@current_scope.pop
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
def current_scope_name
|
162
|
+
@current_scope.join('::')
|
163
|
+
end
|
164
|
+
|
165
|
+
def generate_qualified_names_for_call(node)
|
166
|
+
qualified_names = []
|
167
|
+
method_name = node.name.to_s
|
168
|
+
|
169
|
+
# Try with current scope first
|
170
|
+
qualified_names << "#{current_scope_name}##{method_name}" unless current_scope_name.empty?
|
171
|
+
|
172
|
+
# Try with receiver's type if available
|
173
|
+
if node.receiver
|
174
|
+
case node.receiver
|
175
|
+
when Prism::ConstantReadNode
|
176
|
+
qualified_names << "#{node.receiver.name}##{method_name}"
|
177
|
+
when Prism::ConstantPathNode
|
178
|
+
qualified_names << "#{node.receiver.slice}##{method_name}"
|
179
|
+
when Prism::CallNode
|
180
|
+
# Method chaining - try both instance and class methods
|
181
|
+
if node.receiver.name
|
182
|
+
qualified_names << "#{node.receiver.name}##{method_name}"
|
183
|
+
qualified_names << "#{node.receiver.name}.#{method_name}"
|
184
|
+
end
|
185
|
+
when Prism::InstanceVariableReadNode
|
186
|
+
# Instance variable calls - try current class context
|
187
|
+
qualified_names << "#{current_scope_name}##{method_name}" if current_scope_name
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Try as a standalone method
|
192
|
+
qualified_names << method_name
|
193
|
+
|
194
|
+
# Add potential class method variant
|
195
|
+
qualified_names << "#{current_scope_name}.#{method_name}" unless current_scope_name.empty?
|
196
|
+
|
197
|
+
qualified_names.uniq
|
198
|
+
end
|
199
|
+
|
200
|
+
def current_method_name
|
201
|
+
# Try to find the nearest method node in the AST
|
202
|
+
# This is a simplified version - you might need to enhance this
|
203
|
+
# based on your specific needs
|
204
|
+
"current_method"
|
205
|
+
end
|
206
|
+
|
207
|
+
def in_class_scope?
|
208
|
+
# Check if we're currently in a class definition
|
209
|
+
!@current_scope.empty? && @generator.global_state.declarations[@current_scope.last]&.[](:type) == :class
|
210
|
+
end
|
211
|
+
|
212
|
+
def find_superclass
|
213
|
+
return unless in_class_scope?
|
214
|
+
|
215
|
+
current_class = @current_scope.last
|
216
|
+
class_declaration = @generator.global_state.declarations[current_class]
|
217
|
+
class_declaration&.[](:superclass)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
data/lib/hind/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hind
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aboobacker MK
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-02-
|
10
|
+
date: 2025-02-10 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: prism
|
@@ -112,6 +112,8 @@ files:
|
|
112
112
|
- lib/hind/lsif/global_state.rb
|
113
113
|
- lib/hind/lsif/vertex.rb
|
114
114
|
- lib/hind/lsif/visitor.rb
|
115
|
+
- lib/hind/lsif/visitors/declaration_visitor.rb
|
116
|
+
- lib/hind/lsif/visitors/reference_visitor.rb
|
115
117
|
- lib/hind/parser.rb
|
116
118
|
- lib/hind/scip.rb
|
117
119
|
- lib/hind/scip/generator.rb
|