hind 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|