rubydex 0.1.0.beta11 → 0.1.0.beta13
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/LICENSE.txt +23 -23
- data/README.md +125 -125
- data/THIRD_PARTY_LICENSES.html +2018 -945
- data/exe/rdx +47 -47
- data/ext/rubydex/declaration.c +453 -388
- data/ext/rubydex/declaration.h +23 -23
- data/ext/rubydex/definition.c +284 -197
- data/ext/rubydex/definition.h +28 -28
- data/ext/rubydex/diagnostic.c +6 -6
- data/ext/rubydex/diagnostic.h +11 -11
- data/ext/rubydex/document.c +97 -98
- data/ext/rubydex/document.h +10 -10
- data/ext/rubydex/extconf.rb +146 -127
- data/ext/rubydex/graph.c +701 -512
- data/ext/rubydex/graph.h +10 -10
- data/ext/rubydex/handle.h +44 -44
- data/ext/rubydex/location.c +22 -22
- data/ext/rubydex/location.h +15 -15
- data/ext/rubydex/reference.c +123 -104
- data/ext/rubydex/reference.h +15 -16
- data/ext/rubydex/rubydex.c +22 -22
- data/ext/rubydex/utils.c +108 -86
- data/ext/rubydex/utils.h +34 -28
- data/lib/rubydex/comment.rb +17 -17
- data/lib/rubydex/declaration.rb +11 -0
- data/lib/rubydex/diagnostic.rb +21 -21
- data/lib/rubydex/failures.rb +15 -15
- data/lib/rubydex/graph.rb +98 -92
- data/lib/rubydex/keyword.rb +17 -0
- data/lib/rubydex/keyword_parameter.rb +13 -0
- data/lib/rubydex/location.rb +90 -90
- data/lib/rubydex/mixin.rb +22 -0
- data/lib/rubydex/version.rb +5 -5
- data/lib/rubydex.rb +24 -20
- data/rbi/rubydex.rbi +425 -310
- data/rust/Cargo.lock +1851 -1851
- data/rust/Cargo.toml +29 -29
- data/rust/about.toml +10 -10
- data/rust/{about.hbs → about_templates/about.hbs} +81 -78
- data/rust/about_templates/mingw_licenses.hbs +1071 -0
- data/rust/rubydex/Cargo.toml +42 -42
- data/rust/rubydex/src/compile_assertions.rs +13 -13
- data/rust/rubydex/src/diagnostic.rs +110 -109
- data/rust/rubydex/src/errors.rs +28 -28
- data/rust/rubydex/src/indexing/local_graph.rs +224 -224
- data/rust/rubydex/src/indexing/rbs_indexer.rs +1551 -1554
- data/rust/rubydex/src/indexing/ruby_indexer.rs +2329 -6753
- data/rust/rubydex/src/indexing/ruby_indexer_tests.rs +4962 -0
- data/rust/rubydex/src/indexing.rs +210 -210
- data/rust/rubydex/src/integrity.rs +279 -278
- data/rust/rubydex/src/job_queue.rs +199 -205
- data/rust/rubydex/src/lib.rs +17 -17
- data/rust/rubydex/src/listing.rs +371 -272
- data/rust/rubydex/src/main.rs +160 -160
- data/rust/rubydex/src/model/built_in.rs +83 -0
- data/rust/rubydex/src/model/comment.rs +24 -24
- data/rust/rubydex/src/model/declaration.rs +679 -588
- data/rust/rubydex/src/model/definitions.rs +1682 -1602
- data/rust/rubydex/src/model/document.rs +222 -252
- data/rust/rubydex/src/model/encoding.rs +22 -22
- data/rust/rubydex/src/model/graph.rs +3782 -3556
- data/rust/rubydex/src/model/id.rs +110 -110
- data/rust/rubydex/src/model/identity_maps.rs +58 -58
- data/rust/rubydex/src/model/ids.rs +60 -38
- data/rust/rubydex/src/model/keywords.rs +256 -256
- data/rust/rubydex/src/model/name.rs +298 -298
- data/rust/rubydex/src/model/references.rs +111 -111
- data/rust/rubydex/src/model/string_ref.rs +50 -50
- data/rust/rubydex/src/model/visibility.rs +41 -41
- data/rust/rubydex/src/model.rs +15 -14
- data/rust/rubydex/src/offset.rs +147 -147
- data/rust/rubydex/src/position.rs +6 -6
- data/rust/rubydex/src/query.rs +1841 -1700
- data/rust/rubydex/src/resolution.rs +1852 -5895
- data/rust/rubydex/src/resolution_tests.rs +4701 -0
- data/rust/rubydex/src/stats/memory.rs +71 -71
- data/rust/rubydex/src/stats/orphan_report.rs +264 -263
- data/rust/rubydex/src/stats/timer.rs +127 -127
- data/rust/rubydex/src/stats.rs +11 -11
- data/rust/rubydex/src/test_utils/context.rs +226 -226
- data/rust/rubydex/src/test_utils/graph_test.rs +730 -679
- data/rust/rubydex/src/test_utils/local_graph_test.rs +602 -602
- data/rust/rubydex/src/test_utils.rs +52 -52
- data/rust/rubydex/src/visualization/dot.rs +192 -176
- data/rust/rubydex/src/visualization.rs +6 -6
- data/rust/rubydex/tests/cli.rs +185 -167
- data/rust/rubydex-mcp/Cargo.toml +28 -28
- data/rust/rubydex-mcp/src/main.rs +48 -48
- data/rust/rubydex-mcp/src/server.rs +1145 -1145
- data/rust/rubydex-mcp/src/tools.rs +49 -49
- data/rust/rubydex-mcp/tests/mcp.rs +302 -302
- data/rust/rubydex-sys/Cargo.toml +20 -20
- data/rust/rubydex-sys/build.rs +14 -14
- data/rust/rubydex-sys/cbindgen.toml +12 -12
- data/rust/rubydex-sys/src/declaration_api.rs +485 -469
- data/rust/rubydex-sys/src/definition_api.rs +443 -352
- data/rust/rubydex-sys/src/diagnostic_api.rs +99 -99
- data/rust/rubydex-sys/src/document_api.rs +85 -54
- data/rust/rubydex-sys/src/graph_api.rs +1017 -700
- data/rust/rubydex-sys/src/lib.rs +79 -9
- data/rust/rubydex-sys/src/location_api.rs +79 -79
- data/rust/rubydex-sys/src/name_api.rs +187 -135
- data/rust/rubydex-sys/src/reference_api.rs +267 -195
- data/rust/rubydex-sys/src/utils.rs +70 -70
- data/rust/rustfmt.toml +2 -2
- metadata +16 -9
- data/lib/rubydex/librubydex_sys.so +0 -0
|
@@ -1,298 +1,298 @@
|
|
|
1
|
-
use std::fmt::Display;
|
|
2
|
-
|
|
3
|
-
use crate::{
|
|
4
|
-
assert_mem_size,
|
|
5
|
-
model::ids::{DeclarationId, NameId, StringId},
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
9
|
-
pub enum ParentScope {
|
|
10
|
-
/// There's no parent scope in this reference (e.g.: `Foo`)
|
|
11
|
-
None,
|
|
12
|
-
/// There's an empty parent scope in this reference (e.g.: `::Foo`)
|
|
13
|
-
TopLevel,
|
|
14
|
-
/// There's a parent scope in this reference (e.g.: `Foo::Bar`)
|
|
15
|
-
Some(NameId),
|
|
16
|
-
/// Parent scope representing the class attached to a singleton class context
|
|
17
|
-
///
|
|
18
|
-
/// `Foo::<Foo>::<<Foo>>`
|
|
19
|
-
/// ^ Attached for <Foo>
|
|
20
|
-
/// ^ Attached for <<Foo>>
|
|
21
|
-
Attached(NameId),
|
|
22
|
-
}
|
|
23
|
-
assert_mem_size!(ParentScope, 16);
|
|
24
|
-
|
|
25
|
-
impl ParentScope {
|
|
26
|
-
pub fn map_or<F, T>(&self, default: T, f: F) -> T
|
|
27
|
-
where
|
|
28
|
-
F: FnOnce(&NameId) -> T,
|
|
29
|
-
{
|
|
30
|
-
match self {
|
|
31
|
-
ParentScope::Some(id) | ParentScope::Attached(id) => f(id),
|
|
32
|
-
_ => default,
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
#[must_use]
|
|
37
|
-
pub fn as_ref(&self) -> Option<&NameId> {
|
|
38
|
-
match self {
|
|
39
|
-
ParentScope::Some(id) | ParentScope::Attached(id) => Some(id),
|
|
40
|
-
_ => None,
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
#[must_use]
|
|
45
|
-
pub fn is_none(&self) -> bool {
|
|
46
|
-
matches!(self, ParentScope::None)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
#[must_use]
|
|
50
|
-
pub fn is_top_level(&self) -> bool {
|
|
51
|
-
matches!(self, ParentScope::TopLevel)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/// # Panics
|
|
55
|
-
///
|
|
56
|
-
/// Panics if the `ParentScope` is None or `TopLevel`
|
|
57
|
-
#[must_use]
|
|
58
|
-
pub fn expect(&self, message: &str) -> NameId {
|
|
59
|
-
match self {
|
|
60
|
-
ParentScope::Some(id) | ParentScope::Attached(id) => *id,
|
|
61
|
-
_ => panic!("{}", message),
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
impl Display for ParentScope {
|
|
67
|
-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
68
|
-
match self {
|
|
69
|
-
ParentScope::None => write!(f, "None"),
|
|
70
|
-
ParentScope::TopLevel => write!(f, "TopLevel"),
|
|
71
|
-
ParentScope::Some(id) => write!(f, "Some({id})"),
|
|
72
|
-
ParentScope::Attached(id) => write!(f, "Attached({id})"),
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
#[derive(Debug, Clone, Eq)]
|
|
78
|
-
pub struct Name {
|
|
79
|
-
/// The unqualified name of the constant
|
|
80
|
-
str: StringId,
|
|
81
|
-
/// The ID of parent scope for this constant. For example:
|
|
82
|
-
///
|
|
83
|
-
/// ```ruby
|
|
84
|
-
/// Foo::Bar::Baz
|
|
85
|
-
/// # ^ parent scope of Bar::Baz
|
|
86
|
-
/// # ^ parent scope of Baz
|
|
87
|
-
/// ```
|
|
88
|
-
parent_scope: ParentScope,
|
|
89
|
-
/// The ID of the name for the nesting where we found this name. This effectively turns the structure into a linked
|
|
90
|
-
/// list of names to represent the nesting
|
|
91
|
-
nesting: Option<NameId>,
|
|
92
|
-
ref_count: u32,
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
impl PartialEq for Name {
|
|
96
|
-
fn eq(&self, other: &Self) -> bool {
|
|
97
|
-
self.str == other.str && self.parent_scope == other.parent_scope && self.nesting == other.nesting
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
assert_mem_size!(Name, 40);
|
|
101
|
-
|
|
102
|
-
impl Name {
|
|
103
|
-
#[must_use]
|
|
104
|
-
pub fn new(str: StringId, parent_scope: ParentScope, nesting: Option<NameId>) -> Self {
|
|
105
|
-
Self {
|
|
106
|
-
str,
|
|
107
|
-
parent_scope,
|
|
108
|
-
nesting,
|
|
109
|
-
ref_count: 1,
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
#[must_use]
|
|
114
|
-
pub fn str(&self) -> &StringId {
|
|
115
|
-
&self.str
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
#[must_use]
|
|
119
|
-
pub fn parent_scope(&self) -> &ParentScope {
|
|
120
|
-
&self.parent_scope
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
#[must_use]
|
|
124
|
-
pub fn nesting(&self) -> &Option<NameId> {
|
|
125
|
-
&self.nesting
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
#[must_use]
|
|
129
|
-
pub fn id(&self) -> NameId {
|
|
130
|
-
NameId::from(&format!(
|
|
131
|
-
"{}{}{}",
|
|
132
|
-
self.str,
|
|
133
|
-
self.parent_scope,
|
|
134
|
-
self.nesting.map_or(String::from("None"), |id| id.to_string())
|
|
135
|
-
))
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
#[derive(Debug, Clone)]
|
|
140
|
-
pub struct ResolvedName {
|
|
141
|
-
name: Name,
|
|
142
|
-
declaration_id: DeclarationId,
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
impl ResolvedName {
|
|
146
|
-
#[must_use]
|
|
147
|
-
pub fn new(name: Name, declaration_id: DeclarationId) -> Self {
|
|
148
|
-
Self { name, declaration_id }
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
#[must_use]
|
|
152
|
-
pub fn name(&self) -> &Name {
|
|
153
|
-
&self.name
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
#[must_use]
|
|
157
|
-
pub fn declaration_id(&self) -> &DeclarationId {
|
|
158
|
-
&self.declaration_id
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
#[must_use]
|
|
162
|
-
pub fn nesting(&self) -> &Option<NameId> {
|
|
163
|
-
self.name.nesting()
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/// A usage of a constant name. This could be a constant reference or a definition like a class or module
|
|
168
|
-
#[derive(Debug, Clone)]
|
|
169
|
-
pub enum NameRef {
|
|
170
|
-
/// This name has not yet been resolved. We don't yet know what this name refers to or if it refers to an existing
|
|
171
|
-
/// declaration
|
|
172
|
-
Unresolved(Box<Name>),
|
|
173
|
-
/// This name has been resolved to an existing declaration
|
|
174
|
-
Resolved(Box<ResolvedName>),
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
impl NameRef {
|
|
178
|
-
#[must_use]
|
|
179
|
-
pub fn str(&self) -> &StringId {
|
|
180
|
-
match self {
|
|
181
|
-
NameRef::Unresolved(name) => name.str(),
|
|
182
|
-
NameRef::Resolved(resolved_name) => resolved_name.name.str(),
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
#[must_use]
|
|
187
|
-
pub fn parent_scope(&self) -> &ParentScope {
|
|
188
|
-
match self {
|
|
189
|
-
NameRef::Unresolved(name) => name.parent_scope(),
|
|
190
|
-
NameRef::Resolved(resolved_name) => resolved_name.name.parent_scope(),
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
#[must_use]
|
|
195
|
-
pub fn into_unresolved(self) -> Option<Name> {
|
|
196
|
-
match self {
|
|
197
|
-
NameRef::Unresolved(name) => Some(*name),
|
|
198
|
-
NameRef::Resolved(_) => None,
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
#[must_use]
|
|
203
|
-
pub fn nesting(&self) -> &Option<NameId> {
|
|
204
|
-
match self {
|
|
205
|
-
NameRef::Unresolved(name) => name.nesting(),
|
|
206
|
-
NameRef::Resolved(resolved_name) => resolved_name.name.nesting(),
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
#[must_use]
|
|
211
|
-
pub fn ref_count(&self) -> u32 {
|
|
212
|
-
match self {
|
|
213
|
-
NameRef::Unresolved(name) => name.ref_count,
|
|
214
|
-
NameRef::Resolved(resolved_name) => resolved_name.name.ref_count,
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/// # Panics
|
|
219
|
-
///
|
|
220
|
-
/// Panics if we exceed the maximum size of the reference count
|
|
221
|
-
pub fn increment_ref_count(&mut self, count: u32) {
|
|
222
|
-
let ref_count = match self {
|
|
223
|
-
NameRef::Unresolved(name) => &mut name.ref_count,
|
|
224
|
-
NameRef::Resolved(resolved_name) => &mut resolved_name.name.ref_count,
|
|
225
|
-
};
|
|
226
|
-
*ref_count = ref_count
|
|
227
|
-
.checked_add(count)
|
|
228
|
-
.expect("Should not exceed maximum name ref count");
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
#[must_use]
|
|
232
|
-
pub fn decrement_ref_count(&mut self) -> bool {
|
|
233
|
-
match self {
|
|
234
|
-
NameRef::Unresolved(name) => {
|
|
235
|
-
name.ref_count -= 1;
|
|
236
|
-
name.ref_count > 0
|
|
237
|
-
}
|
|
238
|
-
NameRef::Resolved(resolved_name) => {
|
|
239
|
-
resolved_name.name.ref_count -= 1;
|
|
240
|
-
resolved_name.name.ref_count > 0
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
impl PartialEq for NameRef {
|
|
247
|
-
fn eq(&self, other: &Self) -> bool {
|
|
248
|
-
match (self, other) {
|
|
249
|
-
(NameRef::Unresolved(a), NameRef::Unresolved(b)) => a == b,
|
|
250
|
-
(NameRef::Resolved(a), NameRef::Resolved(b)) => a.name == b.name,
|
|
251
|
-
(NameRef::Unresolved(name), NameRef::Resolved(resolved))
|
|
252
|
-
| (NameRef::Resolved(resolved), NameRef::Unresolved(name)) => **name == resolved.name,
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
impl PartialEq<Name> for NameRef {
|
|
258
|
-
fn eq(&self, other: &Name) -> bool {
|
|
259
|
-
match self {
|
|
260
|
-
NameRef::Unresolved(name) => **name == *other,
|
|
261
|
-
NameRef::Resolved(resolved_name) => &resolved_name.name == other,
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
#[cfg(test)]
|
|
267
|
-
mod tests {
|
|
268
|
-
use super::*;
|
|
269
|
-
|
|
270
|
-
#[test]
|
|
271
|
-
fn same_parent_scope_and_nesting() {
|
|
272
|
-
let name_1 = Name::new(StringId::from("Foo"), ParentScope::None, None);
|
|
273
|
-
let name_2 = Name::new(StringId::from("Foo"), ParentScope::None, None);
|
|
274
|
-
assert_eq!(name_1.id(), name_2.id());
|
|
275
|
-
|
|
276
|
-
let name_3 = Name::new(StringId::from("Foo"), ParentScope::Some(name_1.id()), None);
|
|
277
|
-
let name_4 = Name::new(StringId::from("Foo"), ParentScope::Some(name_2.id()), None);
|
|
278
|
-
assert_eq!(name_3.id(), name_4.id());
|
|
279
|
-
|
|
280
|
-
let name_5 = Name::new(StringId::from("Foo"), ParentScope::None, Some(name_1.id()));
|
|
281
|
-
let name_6 = Name::new(StringId::from("Foo"), ParentScope::None, Some(name_2.id()));
|
|
282
|
-
assert_eq!(name_5.id(), name_6.id());
|
|
283
|
-
assert_ne!(name_3.id(), name_5.id());
|
|
284
|
-
assert_ne!(name_4.id(), name_6.id());
|
|
285
|
-
|
|
286
|
-
let name_7 = Name::new(
|
|
287
|
-
StringId::from("Foo"),
|
|
288
|
-
ParentScope::Some(Name::new(StringId::from("Foo"), ParentScope::None, None).id()),
|
|
289
|
-
Some(Name::new(StringId::from("Foo"), ParentScope::None, None).id()),
|
|
290
|
-
);
|
|
291
|
-
let name_8 = Name::new(
|
|
292
|
-
StringId::from("Foo"),
|
|
293
|
-
ParentScope::Some(Name::new(StringId::from("Foo"), ParentScope::None, None).id()),
|
|
294
|
-
Some(Name::new(StringId::from("Foo"), ParentScope::None, None).id()),
|
|
295
|
-
);
|
|
296
|
-
assert_eq!(name_7.id(), name_8.id());
|
|
297
|
-
}
|
|
298
|
-
}
|
|
1
|
+
use std::fmt::Display;
|
|
2
|
+
|
|
3
|
+
use crate::{
|
|
4
|
+
assert_mem_size,
|
|
5
|
+
model::ids::{DeclarationId, NameId, StringId},
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
9
|
+
pub enum ParentScope {
|
|
10
|
+
/// There's no parent scope in this reference (e.g.: `Foo`)
|
|
11
|
+
None,
|
|
12
|
+
/// There's an empty parent scope in this reference (e.g.: `::Foo`)
|
|
13
|
+
TopLevel,
|
|
14
|
+
/// There's a parent scope in this reference (e.g.: `Foo::Bar`)
|
|
15
|
+
Some(NameId),
|
|
16
|
+
/// Parent scope representing the class attached to a singleton class context
|
|
17
|
+
///
|
|
18
|
+
/// `Foo::<Foo>::<<Foo>>`
|
|
19
|
+
/// ^ Attached for <Foo>
|
|
20
|
+
/// ^ Attached for <<Foo>>
|
|
21
|
+
Attached(NameId),
|
|
22
|
+
}
|
|
23
|
+
assert_mem_size!(ParentScope, 16);
|
|
24
|
+
|
|
25
|
+
impl ParentScope {
|
|
26
|
+
pub fn map_or<F, T>(&self, default: T, f: F) -> T
|
|
27
|
+
where
|
|
28
|
+
F: FnOnce(&NameId) -> T,
|
|
29
|
+
{
|
|
30
|
+
match self {
|
|
31
|
+
ParentScope::Some(id) | ParentScope::Attached(id) => f(id),
|
|
32
|
+
_ => default,
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
#[must_use]
|
|
37
|
+
pub fn as_ref(&self) -> Option<&NameId> {
|
|
38
|
+
match self {
|
|
39
|
+
ParentScope::Some(id) | ParentScope::Attached(id) => Some(id),
|
|
40
|
+
_ => None,
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#[must_use]
|
|
45
|
+
pub fn is_none(&self) -> bool {
|
|
46
|
+
matches!(self, ParentScope::None)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
#[must_use]
|
|
50
|
+
pub fn is_top_level(&self) -> bool {
|
|
51
|
+
matches!(self, ParentScope::TopLevel)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/// # Panics
|
|
55
|
+
///
|
|
56
|
+
/// Panics if the `ParentScope` is None or `TopLevel`
|
|
57
|
+
#[must_use]
|
|
58
|
+
pub fn expect(&self, message: &str) -> NameId {
|
|
59
|
+
match self {
|
|
60
|
+
ParentScope::Some(id) | ParentScope::Attached(id) => *id,
|
|
61
|
+
_ => panic!("{}", message),
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
impl Display for ParentScope {
|
|
67
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
68
|
+
match self {
|
|
69
|
+
ParentScope::None => write!(f, "None"),
|
|
70
|
+
ParentScope::TopLevel => write!(f, "TopLevel"),
|
|
71
|
+
ParentScope::Some(id) => write!(f, "Some({id})"),
|
|
72
|
+
ParentScope::Attached(id) => write!(f, "Attached({id})"),
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
#[derive(Debug, Clone, Eq)]
|
|
78
|
+
pub struct Name {
|
|
79
|
+
/// The unqualified name of the constant
|
|
80
|
+
str: StringId,
|
|
81
|
+
/// The ID of parent scope for this constant. For example:
|
|
82
|
+
///
|
|
83
|
+
/// ```ruby
|
|
84
|
+
/// Foo::Bar::Baz
|
|
85
|
+
/// # ^ parent scope of Bar::Baz
|
|
86
|
+
/// # ^ parent scope of Baz
|
|
87
|
+
/// ```
|
|
88
|
+
parent_scope: ParentScope,
|
|
89
|
+
/// The ID of the name for the nesting where we found this name. This effectively turns the structure into a linked
|
|
90
|
+
/// list of names to represent the nesting
|
|
91
|
+
nesting: Option<NameId>,
|
|
92
|
+
ref_count: u32,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
impl PartialEq for Name {
|
|
96
|
+
fn eq(&self, other: &Self) -> bool {
|
|
97
|
+
self.str == other.str && self.parent_scope == other.parent_scope && self.nesting == other.nesting
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
assert_mem_size!(Name, 40);
|
|
101
|
+
|
|
102
|
+
impl Name {
|
|
103
|
+
#[must_use]
|
|
104
|
+
pub fn new(str: StringId, parent_scope: ParentScope, nesting: Option<NameId>) -> Self {
|
|
105
|
+
Self {
|
|
106
|
+
str,
|
|
107
|
+
parent_scope,
|
|
108
|
+
nesting,
|
|
109
|
+
ref_count: 1,
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
#[must_use]
|
|
114
|
+
pub fn str(&self) -> &StringId {
|
|
115
|
+
&self.str
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
#[must_use]
|
|
119
|
+
pub fn parent_scope(&self) -> &ParentScope {
|
|
120
|
+
&self.parent_scope
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
#[must_use]
|
|
124
|
+
pub fn nesting(&self) -> &Option<NameId> {
|
|
125
|
+
&self.nesting
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
#[must_use]
|
|
129
|
+
pub fn id(&self) -> NameId {
|
|
130
|
+
NameId::from(&format!(
|
|
131
|
+
"{}{}{}",
|
|
132
|
+
self.str,
|
|
133
|
+
self.parent_scope,
|
|
134
|
+
self.nesting.map_or(String::from("None"), |id| id.to_string())
|
|
135
|
+
))
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
#[derive(Debug, Clone)]
|
|
140
|
+
pub struct ResolvedName {
|
|
141
|
+
name: Name,
|
|
142
|
+
declaration_id: DeclarationId,
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
impl ResolvedName {
|
|
146
|
+
#[must_use]
|
|
147
|
+
pub fn new(name: Name, declaration_id: DeclarationId) -> Self {
|
|
148
|
+
Self { name, declaration_id }
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
#[must_use]
|
|
152
|
+
pub fn name(&self) -> &Name {
|
|
153
|
+
&self.name
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
#[must_use]
|
|
157
|
+
pub fn declaration_id(&self) -> &DeclarationId {
|
|
158
|
+
&self.declaration_id
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
#[must_use]
|
|
162
|
+
pub fn nesting(&self) -> &Option<NameId> {
|
|
163
|
+
self.name.nesting()
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/// A usage of a constant name. This could be a constant reference or a definition like a class or module
|
|
168
|
+
#[derive(Debug, Clone)]
|
|
169
|
+
pub enum NameRef {
|
|
170
|
+
/// This name has not yet been resolved. We don't yet know what this name refers to or if it refers to an existing
|
|
171
|
+
/// declaration
|
|
172
|
+
Unresolved(Box<Name>),
|
|
173
|
+
/// This name has been resolved to an existing declaration
|
|
174
|
+
Resolved(Box<ResolvedName>),
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
impl NameRef {
|
|
178
|
+
#[must_use]
|
|
179
|
+
pub fn str(&self) -> &StringId {
|
|
180
|
+
match self {
|
|
181
|
+
NameRef::Unresolved(name) => name.str(),
|
|
182
|
+
NameRef::Resolved(resolved_name) => resolved_name.name.str(),
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
#[must_use]
|
|
187
|
+
pub fn parent_scope(&self) -> &ParentScope {
|
|
188
|
+
match self {
|
|
189
|
+
NameRef::Unresolved(name) => name.parent_scope(),
|
|
190
|
+
NameRef::Resolved(resolved_name) => resolved_name.name.parent_scope(),
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
#[must_use]
|
|
195
|
+
pub fn into_unresolved(self) -> Option<Name> {
|
|
196
|
+
match self {
|
|
197
|
+
NameRef::Unresolved(name) => Some(*name),
|
|
198
|
+
NameRef::Resolved(_) => None,
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
#[must_use]
|
|
203
|
+
pub fn nesting(&self) -> &Option<NameId> {
|
|
204
|
+
match self {
|
|
205
|
+
NameRef::Unresolved(name) => name.nesting(),
|
|
206
|
+
NameRef::Resolved(resolved_name) => resolved_name.name.nesting(),
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
#[must_use]
|
|
211
|
+
pub fn ref_count(&self) -> u32 {
|
|
212
|
+
match self {
|
|
213
|
+
NameRef::Unresolved(name) => name.ref_count,
|
|
214
|
+
NameRef::Resolved(resolved_name) => resolved_name.name.ref_count,
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/// # Panics
|
|
219
|
+
///
|
|
220
|
+
/// Panics if we exceed the maximum size of the reference count
|
|
221
|
+
pub fn increment_ref_count(&mut self, count: u32) {
|
|
222
|
+
let ref_count = match self {
|
|
223
|
+
NameRef::Unresolved(name) => &mut name.ref_count,
|
|
224
|
+
NameRef::Resolved(resolved_name) => &mut resolved_name.name.ref_count,
|
|
225
|
+
};
|
|
226
|
+
*ref_count = ref_count
|
|
227
|
+
.checked_add(count)
|
|
228
|
+
.expect("Should not exceed maximum name ref count");
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
#[must_use]
|
|
232
|
+
pub fn decrement_ref_count(&mut self) -> bool {
|
|
233
|
+
match self {
|
|
234
|
+
NameRef::Unresolved(name) => {
|
|
235
|
+
name.ref_count -= 1;
|
|
236
|
+
name.ref_count > 0
|
|
237
|
+
}
|
|
238
|
+
NameRef::Resolved(resolved_name) => {
|
|
239
|
+
resolved_name.name.ref_count -= 1;
|
|
240
|
+
resolved_name.name.ref_count > 0
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
impl PartialEq for NameRef {
|
|
247
|
+
fn eq(&self, other: &Self) -> bool {
|
|
248
|
+
match (self, other) {
|
|
249
|
+
(NameRef::Unresolved(a), NameRef::Unresolved(b)) => a == b,
|
|
250
|
+
(NameRef::Resolved(a), NameRef::Resolved(b)) => a.name == b.name,
|
|
251
|
+
(NameRef::Unresolved(name), NameRef::Resolved(resolved))
|
|
252
|
+
| (NameRef::Resolved(resolved), NameRef::Unresolved(name)) => **name == resolved.name,
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
impl PartialEq<Name> for NameRef {
|
|
258
|
+
fn eq(&self, other: &Name) -> bool {
|
|
259
|
+
match self {
|
|
260
|
+
NameRef::Unresolved(name) => **name == *other,
|
|
261
|
+
NameRef::Resolved(resolved_name) => &resolved_name.name == other,
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
#[cfg(test)]
|
|
267
|
+
mod tests {
|
|
268
|
+
use super::*;
|
|
269
|
+
|
|
270
|
+
#[test]
|
|
271
|
+
fn same_parent_scope_and_nesting() {
|
|
272
|
+
let name_1 = Name::new(StringId::from("Foo"), ParentScope::None, None);
|
|
273
|
+
let name_2 = Name::new(StringId::from("Foo"), ParentScope::None, None);
|
|
274
|
+
assert_eq!(name_1.id(), name_2.id());
|
|
275
|
+
|
|
276
|
+
let name_3 = Name::new(StringId::from("Foo"), ParentScope::Some(name_1.id()), None);
|
|
277
|
+
let name_4 = Name::new(StringId::from("Foo"), ParentScope::Some(name_2.id()), None);
|
|
278
|
+
assert_eq!(name_3.id(), name_4.id());
|
|
279
|
+
|
|
280
|
+
let name_5 = Name::new(StringId::from("Foo"), ParentScope::None, Some(name_1.id()));
|
|
281
|
+
let name_6 = Name::new(StringId::from("Foo"), ParentScope::None, Some(name_2.id()));
|
|
282
|
+
assert_eq!(name_5.id(), name_6.id());
|
|
283
|
+
assert_ne!(name_3.id(), name_5.id());
|
|
284
|
+
assert_ne!(name_4.id(), name_6.id());
|
|
285
|
+
|
|
286
|
+
let name_7 = Name::new(
|
|
287
|
+
StringId::from("Foo"),
|
|
288
|
+
ParentScope::Some(Name::new(StringId::from("Foo"), ParentScope::None, None).id()),
|
|
289
|
+
Some(Name::new(StringId::from("Foo"), ParentScope::None, None).id()),
|
|
290
|
+
);
|
|
291
|
+
let name_8 = Name::new(
|
|
292
|
+
StringId::from("Foo"),
|
|
293
|
+
ParentScope::Some(Name::new(StringId::from("Foo"), ParentScope::None, None).id()),
|
|
294
|
+
Some(Name::new(StringId::from("Foo"), ParentScope::None, None).id()),
|
|
295
|
+
);
|
|
296
|
+
assert_eq!(name_7.id(), name_8.id());
|
|
297
|
+
}
|
|
298
|
+
}
|