rubydex 0.2.4-aarch64-linux → 0.2.5-aarch64-linux
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/rubydex_mcp +17 -0
- data/ext/rubydex/definition.c +56 -0
- data/ext/rubydex/extconf.rb +8 -0
- data/lib/rubydex/3.2/rubydex.so +0 -0
- data/lib/rubydex/3.3/rubydex.so +0 -0
- data/lib/rubydex/3.4/rubydex.so +0 -0
- data/lib/rubydex/4.0/rubydex.so +0 -0
- data/lib/rubydex/bin/rubydex_mcp +0 -0
- data/lib/rubydex/declaration.rb +3 -3
- data/lib/rubydex/graph.rb +3 -1
- data/lib/rubydex/librubydex_sys.so +0 -0
- data/lib/rubydex/version.rb +1 -1
- data/rbi/rubydex.rbi +8 -2
- data/rust/rubydex/src/indexing/local_graph.rs +38 -0
- data/rust/rubydex/src/indexing/ruby_indexer.rs +6 -0
- data/rust/rubydex/src/indexing/ruby_indexer_tests.rs +5 -1
- data/rust/rubydex/src/indexing.rs +38 -12
- data/rust/rubydex/src/lib.rs +1 -0
- data/rust/rubydex/src/listing.rs +14 -3
- data/rust/rubydex/src/main.rs +27 -2
- data/rust/rubydex/src/model/definitions.rs +7 -18
- data/rust/rubydex/src/model/ids.rs +27 -1
- data/rust/rubydex/src/operation/applier.rs +519 -0
- data/rust/rubydex/src/operation/mod.rs +284 -0
- data/rust/rubydex/src/operation/printer.rs +260 -0
- data/rust/rubydex/src/operation/ruby_builder.rs +2915 -0
- data/rust/rubydex/src/resolution.rs +6 -1
- data/rust/rubydex/src/resolution_tests.rs +217 -209
- data/rust/rubydex/src/test_utils/graph_test.rs +19 -4
- data/rust/rubydex/src/test_utils/local_graph_test.rs +7 -6
- data/rust/rubydex-mcp/src/server.rs +5 -1
- data/rust/rubydex-sys/src/definition_api.rs +24 -0
- data/rust/rubydex-sys/src/graph_api.rs +1 -1
- metadata +9 -2
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
//! Converts an `OperationBuilderResult` into a `LocalGraph` by walking operations and creating definitions.
|
|
2
|
+
//!
|
|
3
|
+
//! This is the second phase of the two-phase operation pipeline:
|
|
4
|
+
//! 1. `RubyOperationBuilder` parses source → produces ordered operations
|
|
5
|
+
//! 2. `apply_operations` walks operations → creates definitions in a `LocalGraph`
|
|
6
|
+
//!
|
|
7
|
+
//! The applier maintains its own scope stack to derive `lexical_nesting_id` for definitions.
|
|
8
|
+
//! Operations carry only their own data; scope context comes from Enter/Exit scope operations.
|
|
9
|
+
|
|
10
|
+
use std::collections::HashMap;
|
|
11
|
+
|
|
12
|
+
use crate::indexing::local_graph::LocalGraph;
|
|
13
|
+
use crate::model::definitions::{
|
|
14
|
+
AttrAccessorDefinition, AttrReaderDefinition, AttrWriterDefinition, ClassDefinition, ClassVariableDefinition,
|
|
15
|
+
ConstantAliasDefinition, ConstantDefinition, ConstantVisibilityDefinition, Definition, ExtendDefinition,
|
|
16
|
+
GlobalVariableAliasDefinition, GlobalVariableDefinition, IncludeDefinition, InstanceVariableDefinition,
|
|
17
|
+
MethodAliasDefinition, MethodDefinition, MethodVisibilityDefinition, Mixin, ModuleDefinition, PrependDefinition,
|
|
18
|
+
Receiver, SingletonClassDefinition,
|
|
19
|
+
};
|
|
20
|
+
use crate::model::ids::{ConstantReferenceId, DefinitionId, NameId};
|
|
21
|
+
use crate::model::references::{ConstantReference, MethodRef};
|
|
22
|
+
use crate::model::visibility::Visibility;
|
|
23
|
+
use crate::operation::ruby_builder::OperationBuilderResult;
|
|
24
|
+
use crate::operation::{
|
|
25
|
+
AliasConstant, AliasGlobalVariable, AliasMethod, AttrKind, DefineAttribute, DefineClassVariable, DefineConstant,
|
|
26
|
+
DefineGlobalVariable, DefineInstanceVariable, EnterClass, EnterMethod, EnterModule, EnterSingletonClass, MixinKind,
|
|
27
|
+
Operation, ReferenceConstant, ReferenceMethod, SetConstantVisibility, SetMethodVisibility, Target,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
enum ApplierScope {
|
|
31
|
+
Namespace {
|
|
32
|
+
definition_id: DefinitionId,
|
|
33
|
+
is_lexical_scope: bool,
|
|
34
|
+
},
|
|
35
|
+
Method {
|
|
36
|
+
definition_id: DefinitionId,
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
struct OperationApplier {
|
|
41
|
+
local_graph: LocalGraph,
|
|
42
|
+
scope_stack: Vec<ApplierScope>,
|
|
43
|
+
scope_visibility: HashMap<Option<DefinitionId>, Visibility>,
|
|
44
|
+
// Maps the most recently emitted ReferenceConstant per name. The builder emits
|
|
45
|
+
// ReferenceConstant immediately before the operation that consumes it (Mixin,
|
|
46
|
+
// EnterClass superclass, SetConstantVisibility), so the last entry always wins.
|
|
47
|
+
constant_ref_ids: HashMap<NameId, ConstantReferenceId>,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
impl OperationApplier {
|
|
51
|
+
fn current_owner_id(&self) -> Option<DefinitionId> {
|
|
52
|
+
self.scope_stack.iter().rev().find_map(|scope| match scope {
|
|
53
|
+
ApplierScope::Namespace { definition_id, .. } => Some(*definition_id),
|
|
54
|
+
ApplierScope::Method { .. } => None,
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
fn current_lexical_scope_id(&self) -> Option<DefinitionId> {
|
|
59
|
+
self.scope_stack.iter().rev().find_map(|scope| match scope {
|
|
60
|
+
ApplierScope::Namespace {
|
|
61
|
+
definition_id,
|
|
62
|
+
is_lexical_scope: true,
|
|
63
|
+
} => Some(*definition_id),
|
|
64
|
+
_ => None,
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
fn current_scope_id(&self) -> Option<DefinitionId> {
|
|
69
|
+
self.scope_stack.last().map(|scope| match scope {
|
|
70
|
+
ApplierScope::Namespace { definition_id, .. } | ApplierScope::Method { definition_id } => *definition_id,
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
fn resolve_receiver(&self, receiver: Option<&Target>) -> Option<Receiver> {
|
|
75
|
+
let current_owner_id = self.current_owner_id();
|
|
76
|
+
match receiver {
|
|
77
|
+
Some(Target::ExplicitSelf) => current_owner_id.map(Receiver::SelfReceiver),
|
|
78
|
+
Some(Target::Constant(name_id)) => Some(Receiver::ConstantReceiver(*name_id)),
|
|
79
|
+
Some(Target::Other) | None => None,
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
fn resolve_visibility(&self, has_receiver: bool) -> Visibility {
|
|
84
|
+
if has_receiver {
|
|
85
|
+
return Visibility::Public;
|
|
86
|
+
}
|
|
87
|
+
let scope = self.current_owner_id();
|
|
88
|
+
let default = self
|
|
89
|
+
.scope_visibility
|
|
90
|
+
.get(&scope)
|
|
91
|
+
.copied()
|
|
92
|
+
.unwrap_or(if scope.is_none() {
|
|
93
|
+
Visibility::Private
|
|
94
|
+
} else {
|
|
95
|
+
Visibility::Public
|
|
96
|
+
});
|
|
97
|
+
match default {
|
|
98
|
+
Visibility::ModuleFunction => Visibility::Private,
|
|
99
|
+
v => v,
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
fn add_member(&mut self, owner_id: Option<DefinitionId>, member_id: DefinitionId) {
|
|
104
|
+
let Some(owner_id) = owner_id else {
|
|
105
|
+
return;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
let Some(owner) = self.local_graph.get_definition_mut(owner_id) else {
|
|
109
|
+
return;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
match owner {
|
|
113
|
+
Definition::Class(class) => class.add_member(member_id),
|
|
114
|
+
Definition::Module(module) => module.add_member(member_id),
|
|
115
|
+
Definition::SingletonClass(singleton) => singleton.add_member(member_id),
|
|
116
|
+
_ => {}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
impl OperationApplier {
|
|
122
|
+
fn apply_operation(&mut self, op: Operation) {
|
|
123
|
+
match op {
|
|
124
|
+
Operation::EnterClass(op) => self.apply_enter_class(op),
|
|
125
|
+
Operation::EnterModule(op) => self.apply_enter_module(op),
|
|
126
|
+
Operation::EnterSingletonClass(op) => self.apply_enter_singleton_class(op),
|
|
127
|
+
Operation::EnterMethod(op) => self.apply_enter_method(op),
|
|
128
|
+
Operation::ExitScope => {
|
|
129
|
+
debug_assert!(!self.scope_stack.is_empty(), "ExitScope with empty scope stack");
|
|
130
|
+
self.scope_stack.pop();
|
|
131
|
+
}
|
|
132
|
+
Operation::AliasMethod(op) => self.apply_alias_method(op),
|
|
133
|
+
Operation::SetMethodVisibility(op) => self.apply_set_method_visibility(op),
|
|
134
|
+
Operation::SetDefaultVisibility(op) => {
|
|
135
|
+
let scope = self.current_owner_id();
|
|
136
|
+
self.scope_visibility.insert(scope, op.visibility);
|
|
137
|
+
}
|
|
138
|
+
Operation::DefineConstant(op) => self.apply_define_constant(op),
|
|
139
|
+
Operation::AliasConstant(op) => self.apply_alias_constant(op),
|
|
140
|
+
Operation::SetConstantVisibility(op) => self.apply_set_constant_visibility(op),
|
|
141
|
+
Operation::Mixin(ref op) => self.apply_mixin(op),
|
|
142
|
+
Operation::DefineAttribute(op) => self.apply_define_attribute(op),
|
|
143
|
+
Operation::DefineGlobalVariable(op) => self.apply_define_global_variable(op),
|
|
144
|
+
Operation::DefineInstanceVariable(op) => self.apply_define_instance_variable(op),
|
|
145
|
+
Operation::DefineClassVariable(op) => self.apply_define_class_variable(op),
|
|
146
|
+
Operation::AliasGlobalVariable(op) => self.apply_alias_global_variable(op),
|
|
147
|
+
Operation::ReferenceConstant(op) => self.apply_reference_constant(op),
|
|
148
|
+
Operation::ReferenceMethod(op) => self.apply_reference_method(op),
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
fn apply_enter_class(&mut self, op: EnterClass) {
|
|
153
|
+
let lexical_nesting_id = self.current_lexical_scope_id();
|
|
154
|
+
let superclass_ref = op.superclass_name.and_then(|n| self.constant_ref_ids.get(&n).copied());
|
|
155
|
+
let def = ClassDefinition::new(
|
|
156
|
+
op.name_id,
|
|
157
|
+
op.uri_id,
|
|
158
|
+
op.offset,
|
|
159
|
+
op.name_offset,
|
|
160
|
+
op.comments,
|
|
161
|
+
op.flags,
|
|
162
|
+
lexical_nesting_id,
|
|
163
|
+
superclass_ref,
|
|
164
|
+
);
|
|
165
|
+
let def_id = self.local_graph.add_definition(Definition::Class(Box::new(def)));
|
|
166
|
+
self.add_member(lexical_nesting_id, def_id);
|
|
167
|
+
self.scope_stack.push(ApplierScope::Namespace {
|
|
168
|
+
definition_id: def_id,
|
|
169
|
+
is_lexical_scope: op.is_lexical_scope,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
fn apply_enter_module(&mut self, op: EnterModule) {
|
|
174
|
+
let lexical_nesting_id = self.current_lexical_scope_id();
|
|
175
|
+
let def = ModuleDefinition::new(
|
|
176
|
+
op.name_id,
|
|
177
|
+
op.uri_id,
|
|
178
|
+
op.offset,
|
|
179
|
+
op.name_offset,
|
|
180
|
+
op.comments,
|
|
181
|
+
op.flags,
|
|
182
|
+
lexical_nesting_id,
|
|
183
|
+
);
|
|
184
|
+
let def_id = self.local_graph.add_definition(Definition::Module(Box::new(def)));
|
|
185
|
+
self.add_member(lexical_nesting_id, def_id);
|
|
186
|
+
self.scope_stack.push(ApplierScope::Namespace {
|
|
187
|
+
definition_id: def_id,
|
|
188
|
+
is_lexical_scope: op.is_lexical_scope,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
fn apply_enter_singleton_class(&mut self, op: EnterSingletonClass) {
|
|
193
|
+
let lexical_nesting_id = self.current_lexical_scope_id();
|
|
194
|
+
let def = SingletonClassDefinition::new(
|
|
195
|
+
op.name_id,
|
|
196
|
+
op.uri_id,
|
|
197
|
+
op.offset,
|
|
198
|
+
op.name_offset,
|
|
199
|
+
op.comments,
|
|
200
|
+
op.flags,
|
|
201
|
+
lexical_nesting_id,
|
|
202
|
+
);
|
|
203
|
+
let def_id = self
|
|
204
|
+
.local_graph
|
|
205
|
+
.add_definition(Definition::SingletonClass(Box::new(def)));
|
|
206
|
+
self.add_member(lexical_nesting_id, def_id);
|
|
207
|
+
self.scope_stack.push(ApplierScope::Namespace {
|
|
208
|
+
definition_id: def_id,
|
|
209
|
+
is_lexical_scope: true,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
fn apply_enter_method(&mut self, op: EnterMethod) {
|
|
214
|
+
let lexical_nesting_id = self.current_owner_id();
|
|
215
|
+
let has_receiver = op.receiver.is_some();
|
|
216
|
+
let receiver = self.resolve_receiver(op.receiver.as_ref());
|
|
217
|
+
let visibility = self.resolve_visibility(has_receiver);
|
|
218
|
+
let def = MethodDefinition::new(
|
|
219
|
+
op.str_id,
|
|
220
|
+
op.uri_id,
|
|
221
|
+
op.offset,
|
|
222
|
+
op.comments,
|
|
223
|
+
op.flags,
|
|
224
|
+
lexical_nesting_id,
|
|
225
|
+
op.signatures,
|
|
226
|
+
visibility,
|
|
227
|
+
receiver,
|
|
228
|
+
);
|
|
229
|
+
let def_id = self.local_graph.add_definition(Definition::Method(Box::new(def)));
|
|
230
|
+
self.add_member(lexical_nesting_id, def_id);
|
|
231
|
+
self.scope_stack.push(ApplierScope::Method { definition_id: def_id });
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
fn apply_alias_method(&mut self, op: AliasMethod) {
|
|
235
|
+
let lexical_nesting_id = self.current_owner_id();
|
|
236
|
+
let receiver = self.resolve_receiver(op.receiver.as_ref());
|
|
237
|
+
let def = MethodAliasDefinition::new(
|
|
238
|
+
op.new_name_str_id,
|
|
239
|
+
op.old_name_str_id,
|
|
240
|
+
op.uri_id,
|
|
241
|
+
op.offset,
|
|
242
|
+
op.comments,
|
|
243
|
+
op.flags,
|
|
244
|
+
lexical_nesting_id,
|
|
245
|
+
receiver,
|
|
246
|
+
);
|
|
247
|
+
let def_id = self.local_graph.add_definition(Definition::MethodAlias(Box::new(def)));
|
|
248
|
+
self.add_member(lexical_nesting_id, def_id);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
fn apply_set_method_visibility(&mut self, op: SetMethodVisibility) {
|
|
252
|
+
let lexical_nesting_id = self.current_owner_id();
|
|
253
|
+
let def = MethodVisibilityDefinition::new(
|
|
254
|
+
op.str_id,
|
|
255
|
+
op.visibility,
|
|
256
|
+
op.uri_id,
|
|
257
|
+
op.offset,
|
|
258
|
+
Box::default(),
|
|
259
|
+
op.flags,
|
|
260
|
+
lexical_nesting_id,
|
|
261
|
+
);
|
|
262
|
+
let def_id = self
|
|
263
|
+
.local_graph
|
|
264
|
+
.add_definition(Definition::MethodVisibility(Box::new(def)));
|
|
265
|
+
self.add_member(lexical_nesting_id, def_id);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
fn apply_define_constant(&mut self, op: DefineConstant) {
|
|
269
|
+
let lexical_nesting_id = self.current_lexical_scope_id();
|
|
270
|
+
let def = ConstantDefinition::new(
|
|
271
|
+
op.name_id,
|
|
272
|
+
op.uri_id,
|
|
273
|
+
op.offset,
|
|
274
|
+
op.comments,
|
|
275
|
+
op.flags,
|
|
276
|
+
lexical_nesting_id,
|
|
277
|
+
);
|
|
278
|
+
let def_id = self.local_graph.add_definition(Definition::Constant(Box::new(def)));
|
|
279
|
+
self.add_member(lexical_nesting_id, def_id);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
fn apply_alias_constant(&mut self, op: AliasConstant) {
|
|
283
|
+
let lexical_nesting_id = self.current_lexical_scope_id();
|
|
284
|
+
let constant = ConstantDefinition::new(
|
|
285
|
+
op.name_id,
|
|
286
|
+
op.uri_id,
|
|
287
|
+
op.offset,
|
|
288
|
+
op.comments,
|
|
289
|
+
op.flags,
|
|
290
|
+
lexical_nesting_id,
|
|
291
|
+
);
|
|
292
|
+
let def = ConstantAliasDefinition::new(op.target_name_id, constant);
|
|
293
|
+
let def_id = self
|
|
294
|
+
.local_graph
|
|
295
|
+
.add_definition(Definition::ConstantAlias(Box::new(def)));
|
|
296
|
+
self.add_member(lexical_nesting_id, def_id);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
fn apply_set_constant_visibility(&mut self, op: SetConstantVisibility) {
|
|
300
|
+
let lexical_nesting_id = self.current_owner_id();
|
|
301
|
+
let receiver = match op.receiver {
|
|
302
|
+
Some(Target::Constant(name_id)) => Some(name_id),
|
|
303
|
+
Some(Target::ExplicitSelf | Target::Other) | None => None,
|
|
304
|
+
};
|
|
305
|
+
let def = ConstantVisibilityDefinition::new(
|
|
306
|
+
receiver,
|
|
307
|
+
op.target,
|
|
308
|
+
op.visibility,
|
|
309
|
+
op.uri_id,
|
|
310
|
+
op.offset,
|
|
311
|
+
op.comments,
|
|
312
|
+
op.flags,
|
|
313
|
+
lexical_nesting_id,
|
|
314
|
+
);
|
|
315
|
+
let def_id = self
|
|
316
|
+
.local_graph
|
|
317
|
+
.add_definition(Definition::ConstantVisibility(Box::new(def)));
|
|
318
|
+
self.add_member(lexical_nesting_id, def_id);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
fn apply_mixin(&mut self, op: &crate::operation::Mixin) {
|
|
322
|
+
let Some(owner_id) = self.current_owner_id() else {
|
|
323
|
+
return;
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
let constant_reference_id = match op.target {
|
|
327
|
+
Target::Constant(name_id) => self.constant_ref_ids.get(&name_id).copied(),
|
|
328
|
+
Target::ExplicitSelf | Target::Other => None,
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
let Some(constant_reference_id) = constant_reference_id else {
|
|
332
|
+
return;
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
let mixin = match op.kind {
|
|
336
|
+
MixinKind::Include => Mixin::Include(IncludeDefinition::new(constant_reference_id)),
|
|
337
|
+
MixinKind::Prepend => Mixin::Prepend(PrependDefinition::new(constant_reference_id)),
|
|
338
|
+
MixinKind::Extend => Mixin::Extend(ExtendDefinition::new(constant_reference_id)),
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
if let Some(owner) = self.local_graph.get_definition_mut(owner_id) {
|
|
342
|
+
match owner {
|
|
343
|
+
Definition::Class(class) => class.add_mixin(mixin),
|
|
344
|
+
Definition::Module(module) => module.add_mixin(mixin),
|
|
345
|
+
Definition::SingletonClass(singleton) => singleton.add_mixin(mixin),
|
|
346
|
+
_ => {}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
fn apply_define_attribute(&mut self, op: DefineAttribute) {
|
|
352
|
+
let lexical_nesting_id = self.current_scope_id();
|
|
353
|
+
let visibility = self.resolve_visibility(false);
|
|
354
|
+
let def_id = match op.kind {
|
|
355
|
+
AttrKind::Accessor => {
|
|
356
|
+
let def = AttrAccessorDefinition::new(
|
|
357
|
+
op.str_id,
|
|
358
|
+
op.uri_id,
|
|
359
|
+
op.offset,
|
|
360
|
+
op.comments,
|
|
361
|
+
op.flags,
|
|
362
|
+
lexical_nesting_id,
|
|
363
|
+
visibility,
|
|
364
|
+
);
|
|
365
|
+
self.local_graph.add_definition(Definition::AttrAccessor(Box::new(def)))
|
|
366
|
+
}
|
|
367
|
+
AttrKind::Reader => {
|
|
368
|
+
let def = AttrReaderDefinition::new(
|
|
369
|
+
op.str_id,
|
|
370
|
+
op.uri_id,
|
|
371
|
+
op.offset,
|
|
372
|
+
op.comments,
|
|
373
|
+
op.flags,
|
|
374
|
+
lexical_nesting_id,
|
|
375
|
+
visibility,
|
|
376
|
+
);
|
|
377
|
+
self.local_graph.add_definition(Definition::AttrReader(Box::new(def)))
|
|
378
|
+
}
|
|
379
|
+
AttrKind::Writer => {
|
|
380
|
+
let def = AttrWriterDefinition::new(
|
|
381
|
+
op.str_id,
|
|
382
|
+
op.uri_id,
|
|
383
|
+
op.offset,
|
|
384
|
+
op.comments,
|
|
385
|
+
op.flags,
|
|
386
|
+
lexical_nesting_id,
|
|
387
|
+
visibility,
|
|
388
|
+
);
|
|
389
|
+
self.local_graph.add_definition(Definition::AttrWriter(Box::new(def)))
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
self.add_member(lexical_nesting_id, def_id);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
fn apply_define_global_variable(&mut self, op: DefineGlobalVariable) {
|
|
396
|
+
let lexical_nesting_id = self.current_scope_id();
|
|
397
|
+
let member_owner_id = self.current_owner_id();
|
|
398
|
+
let def = GlobalVariableDefinition::new(
|
|
399
|
+
op.str_id,
|
|
400
|
+
op.uri_id,
|
|
401
|
+
op.offset,
|
|
402
|
+
op.comments,
|
|
403
|
+
op.flags,
|
|
404
|
+
lexical_nesting_id,
|
|
405
|
+
);
|
|
406
|
+
let def_id = self
|
|
407
|
+
.local_graph
|
|
408
|
+
.add_definition(Definition::GlobalVariable(Box::new(def)));
|
|
409
|
+
self.add_member(member_owner_id, def_id);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
fn apply_define_instance_variable(&mut self, op: DefineInstanceVariable) {
|
|
413
|
+
let lexical_nesting_id = self.current_scope_id();
|
|
414
|
+
let member_owner_id = self.current_owner_id();
|
|
415
|
+
let def = InstanceVariableDefinition::new(
|
|
416
|
+
op.str_id,
|
|
417
|
+
op.uri_id,
|
|
418
|
+
op.offset,
|
|
419
|
+
op.comments,
|
|
420
|
+
op.flags,
|
|
421
|
+
lexical_nesting_id,
|
|
422
|
+
);
|
|
423
|
+
let def_id = self
|
|
424
|
+
.local_graph
|
|
425
|
+
.add_definition(Definition::InstanceVariable(Box::new(def)));
|
|
426
|
+
self.add_member(member_owner_id, def_id);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
fn apply_define_class_variable(&mut self, op: DefineClassVariable) {
|
|
430
|
+
let lexical_nesting_id = self.current_lexical_scope_id();
|
|
431
|
+
let member_owner_id = self.current_owner_id();
|
|
432
|
+
let def = ClassVariableDefinition::new(
|
|
433
|
+
op.str_id,
|
|
434
|
+
op.uri_id,
|
|
435
|
+
op.offset,
|
|
436
|
+
op.comments,
|
|
437
|
+
op.flags,
|
|
438
|
+
lexical_nesting_id,
|
|
439
|
+
);
|
|
440
|
+
let def_id = self
|
|
441
|
+
.local_graph
|
|
442
|
+
.add_definition(Definition::ClassVariable(Box::new(def)));
|
|
443
|
+
self.add_member(member_owner_id, def_id);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
fn apply_alias_global_variable(&mut self, op: AliasGlobalVariable) {
|
|
447
|
+
let lexical_nesting_id = self.current_scope_id();
|
|
448
|
+
let def = GlobalVariableAliasDefinition::new(
|
|
449
|
+
op.new_name_str_id,
|
|
450
|
+
op.old_name_str_id,
|
|
451
|
+
op.uri_id,
|
|
452
|
+
op.offset,
|
|
453
|
+
op.comments,
|
|
454
|
+
op.flags,
|
|
455
|
+
lexical_nesting_id,
|
|
456
|
+
);
|
|
457
|
+
self.local_graph
|
|
458
|
+
.add_definition(Definition::GlobalVariableAlias(Box::new(def)));
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
fn apply_reference_constant(&mut self, op: ReferenceConstant) {
|
|
462
|
+
let ref_id = self
|
|
463
|
+
.local_graph
|
|
464
|
+
.add_constant_reference(ConstantReference::new(op.name_id, op.uri_id, op.offset));
|
|
465
|
+
self.constant_ref_ids.insert(op.name_id, ref_id);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
fn apply_reference_method(&mut self, op: ReferenceMethod) {
|
|
469
|
+
let receiver = match op.receiver {
|
|
470
|
+
Some(Target::Constant(name_id)) => Some(name_id),
|
|
471
|
+
Some(Target::ExplicitSelf | Target::Other) | None => None,
|
|
472
|
+
};
|
|
473
|
+
self.local_graph
|
|
474
|
+
.add_method_reference(MethodRef::new(op.str_id, op.uri_id, op.offset, receiver));
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/// Converts an `OperationBuilderResult` into a `LocalGraph`.
|
|
479
|
+
///
|
|
480
|
+
/// Walks the operations in order, creating `Definition` objects and registering members/mixins.
|
|
481
|
+
/// Scope context is derived from the scope stack maintained by Enter/Exit operations.
|
|
482
|
+
#[must_use]
|
|
483
|
+
pub fn apply_operations(result: OperationBuilderResult) -> LocalGraph {
|
|
484
|
+
let OperationBuilderResult {
|
|
485
|
+
uri_id,
|
|
486
|
+
document,
|
|
487
|
+
operations,
|
|
488
|
+
strings,
|
|
489
|
+
names,
|
|
490
|
+
} = result;
|
|
491
|
+
|
|
492
|
+
let mut applier = OperationApplier {
|
|
493
|
+
local_graph: LocalGraph::from_parts(uri_id, document, strings, names),
|
|
494
|
+
scope_stack: Vec::new(),
|
|
495
|
+
scope_visibility: HashMap::new(),
|
|
496
|
+
constant_ref_ids: HashMap::new(),
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
for op in operations {
|
|
500
|
+
applier.apply_operation(op);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
applier.local_graph
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
#[cfg(test)]
|
|
507
|
+
fn backend() -> crate::indexing::IndexerBackend {
|
|
508
|
+
crate::indexing::IndexerBackend::OperationBuilder
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
#[cfg(test)]
|
|
512
|
+
#[allow(clippy::duplicate_mod)]
|
|
513
|
+
#[path = "../indexing/ruby_indexer_tests.rs"]
|
|
514
|
+
mod applier_tests;
|
|
515
|
+
|
|
516
|
+
#[cfg(test)]
|
|
517
|
+
#[allow(clippy::duplicate_mod)]
|
|
518
|
+
#[path = "../resolution_tests.rs"]
|
|
519
|
+
mod resolution_tests;
|