hind 0.1.6 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -13,10 +13,6 @@ module Hind
13
13
  @result_sets = {} # {qualified_name => result_set_id}
14
14
  @ranges = {} # {file_path => [range_ids]}
15
15
  @project_id = nil
16
-
17
- # Method visibility tracking
18
- @visibility_stack = [] # Stack of method visibility states per scope
19
- @current_visibility = :public
20
16
  end
21
17
 
22
18
  def add_declaration(qualified_name, data)
@@ -24,12 +20,12 @@ module Hind
24
20
  @result_sets[qualified_name] = data[:result_set_id] if data[:result_set_id]
25
21
  end
26
22
 
27
- def add_reference(qualified_name, file_path, range_id, type = :reference)
23
+ def add_reference(qualified_name, file_path, range_id, document_id)
28
24
  @references[qualified_name] ||= []
29
25
  @references[qualified_name] << {
30
26
  file: file_path,
31
27
  range_id: range_id,
32
- type: type
28
+ document_id: document_id
33
29
  }
34
30
  end
35
31
 
@@ -58,98 +54,31 @@ module Hind
58
54
  @ranges[file_path] || []
59
55
  end
60
56
 
61
- def push_visibility_scope(visibility = :public)
62
- @visibility_stack.push(@current_visibility)
63
- @current_visibility = visibility
64
- end
65
-
66
- def pop_visibility_scope
67
- @current_visibility = @visibility_stack.pop || :public
68
- end
69
-
70
- def current_visibility
71
- @current_visibility
72
- end
73
-
74
- def get_declaration_in_scope(name, scope)
75
- # Try exact scope first
76
- qualified_name = scope.empty? ? name : "#{scope}::#{name}"
77
- return qualified_name if has_declaration?(qualified_name)
78
-
79
- # Try parent scopes
80
- scope_parts = scope.split('::')
81
- while scope_parts.any?
82
- scope_parts.pop
83
- qualified_name = scope_parts.empty? ? name : "#{scope_parts.join('::')}::#{name}"
84
- return qualified_name if has_declaration?(qualified_name)
85
- end
86
-
87
- # Try top level
88
- has_declaration?(name) ? name : nil
89
- end
90
-
91
- def get_method_declaration(method_name, scope, instance_method = true)
92
- separator = instance_method ? '#' : '.'
93
- qualified_name = scope.empty? ? method_name : "#{scope}#{separator}#{method_name}"
94
-
95
- return qualified_name if has_declaration?(qualified_name)
96
-
97
- # For instance methods, try to find in superclass chain
98
- if instance_method && !scope.empty?
99
- current_scope = scope
100
- while (class_data = @declarations[current_scope])
101
- break unless class_data[:type] == :class && class_data[:superclass]
102
-
103
- superclass = class_data[:superclass]
104
- superclass_method = "#{superclass}#{separator}#{method_name}"
105
- return superclass_method if has_declaration?(superclass_method)
106
-
107
- current_scope = superclass
108
- end
109
- end
110
-
111
- nil
112
- end
113
-
114
57
  def find_constant_declaration(name, current_scope)
115
58
  return name if has_declaration?(name)
116
59
 
117
- # Try with current scope
118
60
  if current_scope && !current_scope.empty?
119
61
  qualified_name = "#{current_scope}::#{name}"
120
62
  return qualified_name if has_declaration?(qualified_name)
121
63
 
122
- # Try parent scopes
123
64
  scope_parts = current_scope.split('::')
124
65
  while scope_parts.any?
125
66
  scope_parts.pop
126
- qualified_name = scope_parts.empty? ? name : "#{scope_parts.join('::')}::#{name}"
67
+ qualified_name = scope_parts.empty? ? name : "#{scope_parts.join("::")}::#{name}"
127
68
  return qualified_name if has_declaration?(qualified_name)
128
69
  end
129
70
  end
130
71
 
131
- # Try top level
132
72
  has_declaration?(name) ? name : nil
133
73
  end
134
74
 
135
- def get_instance_variable_scope(var_name, current_scope)
136
- return nil unless current_scope
137
- "#{current_scope}##{var_name}"
138
- end
139
-
140
- def get_class_variable_scope(var_name, current_scope)
141
- return nil unless current_scope
142
- "#{current_scope}::#{var_name}"
143
- end
144
-
145
75
  def debug_info
146
76
  {
147
77
  declarations_count: @declarations.size,
148
78
  references_count: @references.values.sum(&:size),
149
79
  result_sets_count: @result_sets.size,
150
80
  ranges_count: @ranges.values.sum(&:size),
151
- declaration_types: declaration_types_count,
152
- reference_types: reference_types_count
81
+ declaration_types: declaration_types_count
153
82
  }
154
83
  end
155
84
 
@@ -160,12 +89,6 @@ module Hind
160
89
  counts[decl[:type]] += 1
161
90
  end
162
91
  end
163
-
164
- def reference_types_count
165
- @references.values.flatten.each_with_object(Hash.new(0)) do |ref, counts|
166
- counts[ref[:type]] += 1
167
- end
168
- end
169
92
  end
170
93
  end
171
94
  end
@@ -10,16 +10,12 @@ module Hind
10
10
  @generator = generator
11
11
  @file_path = file_path
12
12
  @current_scope = []
13
- @current_visibility = :public
14
- @visibility_stack = []
15
- @in_singleton_class = false
16
13
  end
17
14
 
18
15
  def visit_class_node(node)
19
16
  @current_scope.push(node.constant_path.slice)
20
17
  class_name = current_scope_name
21
18
 
22
- # Register class declaration
23
19
  @generator.register_declaration({
24
20
  type: :class,
25
21
  name: class_name,
@@ -28,10 +24,7 @@ module Hind
28
24
  superclass: node.superclass&.slice
29
25
  })
30
26
 
31
- # Process the class body with proper scope and visibility
32
- push_visibility(:public)
33
27
  super
34
- pop_visibility
35
28
  @current_scope.pop
36
29
  end
37
30
 
@@ -46,32 +39,10 @@ module Hind
46
39
  scope: @current_scope[0..-2].join('::')
47
40
  })
48
41
 
49
- push_visibility(:public)
50
42
  super
51
- pop_visibility
52
43
  @current_scope.pop
53
44
  end
54
45
 
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
46
  def visit_constant_write_node(node)
76
47
  return unless node.name
77
48
 
@@ -88,152 +59,11 @@ module Hind
88
59
  super
89
60
  end
90
61
 
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
62
  private
148
63
 
149
64
  def current_scope_name
150
65
  @current_scope.join('::')
151
66
  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
67
  end
238
68
  end
239
69
  end
@@ -1,4 +1,3 @@
1
- # lib/hind/lsif/visitors/reference_visitor.rb
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module Hind
@@ -12,27 +11,6 @@ module Hind
12
11
  @current_scope = []
13
12
  end
14
13
 
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
14
  def visit_constant_read_node(node)
37
15
  return unless node.name
38
16
 
@@ -49,7 +27,6 @@ module Hind
49
27
  super
50
28
  end
51
29
 
52
- # Constant path references (e.g., A::B::C)
53
30
  def visit_constant_path_node(node)
54
31
  qualified_name = node.slice
55
32
 
@@ -63,87 +40,6 @@ module Hind
63
40
  super
64
41
  end
65
42
 
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
43
  def visit_class_node(node)
148
44
  @current_scope.push(node.constant_path.slice)
149
45
  super
@@ -161,61 +57,6 @@ module Hind
161
57
  def current_scope_name
162
58
  @current_scope.join('::')
163
59
  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
60
  end
220
61
  end
221
62
  end
data/lib/hind/lsif.rb CHANGED
@@ -4,7 +4,6 @@ require_relative 'lsif/global_state'
4
4
  require_relative 'lsif/edge'
5
5
  require_relative 'lsif/generator'
6
6
  require_relative 'lsif/vertex'
7
- require_relative 'lsif/visitor'
8
7
 
9
8
  module Hind
10
9
  module LSIF
data/lib/hind/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hind
4
- VERSION = '0.1.6'
4
+ VERSION = '0.1.8'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hind
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aboobacker MK
@@ -111,7 +111,6 @@ files:
111
111
  - lib/hind/lsif/generator.rb
112
112
  - lib/hind/lsif/global_state.rb
113
113
  - lib/hind/lsif/vertex.rb
114
- - lib/hind/lsif/visitor.rb
115
114
  - lib/hind/lsif/visitors/declaration_visitor.rb
116
115
  - lib/hind/lsif/visitors/reference_visitor.rb
117
116
  - lib/hind/parser.rb