Skip to content

Commit eb368fb

Browse files
committed
Merge branch 'master' into refactor/enforce-conventions
2 parents c91933b + 7c038a0 commit eb368fb

61 files changed

Lines changed: 1184 additions & 1217 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

crates/plotnik-core/src/interner.rs

Lines changed: 0 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -132,103 +132,3 @@ impl Interner {
132132
(blob, offsets)
133133
}
134134
}
135-
136-
#[cfg(test)]
137-
mod tests {
138-
use super::*;
139-
140-
#[test]
141-
fn intern_deduplicates() {
142-
let mut interner = Interner::new();
143-
144-
let a = interner.intern("foo");
145-
let b = interner.intern("foo");
146-
let c = interner.intern("bar");
147-
148-
assert_eq!(a, b);
149-
assert_ne!(a, c);
150-
assert_eq!(interner.len(), 2);
151-
}
152-
153-
#[test]
154-
fn resolve_roundtrip() {
155-
let mut interner = Interner::new();
156-
157-
let sym = interner.intern("hello");
158-
assert_eq!(interner.resolve(sym), "hello");
159-
}
160-
161-
#[test]
162-
fn intern_owned_avoids_clone_on_hit() {
163-
let mut interner = Interner::new();
164-
165-
let a = interner.intern("test");
166-
let b = interner.intern_owned("test".to_string());
167-
168-
assert_eq!(a, b);
169-
assert_eq!(interner.len(), 1);
170-
}
171-
172-
#[test]
173-
fn symbols_are_copy() {
174-
let mut interner = Interner::new();
175-
let sym = interner.intern("x");
176-
177-
let copy = sym;
178-
assert_eq!(sym, copy);
179-
}
180-
181-
#[test]
182-
fn symbol_ordering_is_insertion_order() {
183-
let mut interner = Interner::new();
184-
185-
let z = interner.intern("z");
186-
let a = interner.intern("a");
187-
188-
// z was inserted first, so z < a by insertion order
189-
assert!(z < a);
190-
}
191-
192-
#[test]
193-
fn to_blob_produces_correct_format() {
194-
let mut interner = Interner::new();
195-
interner.intern("id");
196-
interner.intern("foo");
197-
198-
let (blob, offsets) = interner.to_blob();
199-
200-
assert_eq!(blob, b"idfoo");
201-
assert_eq!(offsets, vec![0, 2, 5]);
202-
203-
// Verify we can reconstruct strings
204-
let s0 = &blob[offsets[0] as usize..offsets[1] as usize];
205-
let s1 = &blob[offsets[1] as usize..offsets[2] as usize];
206-
assert_eq!(s0, b"id");
207-
assert_eq!(s1, b"foo");
208-
}
209-
210-
#[test]
211-
fn to_blob_empty() {
212-
let interner = Interner::new();
213-
let (blob, offsets) = interner.to_blob();
214-
215-
assert!(blob.is_empty());
216-
assert_eq!(offsets, vec![0]); // just the sentinel
217-
}
218-
219-
#[test]
220-
fn iter_yields_all_strings() {
221-
let mut interner = Interner::new();
222-
let a = interner.intern("alpha");
223-
let b = interner.intern("beta");
224-
225-
let items: Vec<_> = interner.iter().collect();
226-
assert_eq!(items, vec![(a, "alpha"), (b, "beta")]);
227-
}
228-
229-
#[test]
230-
fn symbol_from_raw_roundtrip() {
231-
let sym = Symbol::from_raw(42);
232-
assert_eq!(sym.as_u32(), 42);
233-
}
234-
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
use crate::{Interner, Symbol};
2+
3+
#[test]
4+
fn intern_deduplicates() {
5+
let mut interner = Interner::new();
6+
7+
let a = interner.intern("foo");
8+
let b = interner.intern("foo");
9+
let c = interner.intern("bar");
10+
11+
assert_eq!(a, b);
12+
assert_ne!(a, c);
13+
assert_eq!(interner.len(), 2);
14+
}
15+
16+
#[test]
17+
fn resolve_roundtrip() {
18+
let mut interner = Interner::new();
19+
20+
let sym = interner.intern("hello");
21+
assert_eq!(interner.resolve(sym), "hello");
22+
}
23+
24+
#[test]
25+
fn intern_owned_avoids_clone_on_hit() {
26+
let mut interner = Interner::new();
27+
28+
let a = interner.intern("test");
29+
let b = interner.intern_owned("test".to_string());
30+
31+
assert_eq!(a, b);
32+
assert_eq!(interner.len(), 1);
33+
}
34+
35+
#[test]
36+
fn symbols_are_copy() {
37+
let mut interner = Interner::new();
38+
let sym = interner.intern("x");
39+
40+
let copy = sym;
41+
assert_eq!(sym, copy);
42+
}
43+
44+
#[test]
45+
fn symbol_ordering_is_insertion_order() {
46+
let mut interner = Interner::new();
47+
48+
let z = interner.intern("z");
49+
let a = interner.intern("a");
50+
51+
// z was inserted first, so z < a by insertion order
52+
assert!(z < a);
53+
}
54+
55+
#[test]
56+
fn to_blob_produces_correct_format() {
57+
let mut interner = Interner::new();
58+
interner.intern("id");
59+
interner.intern("foo");
60+
61+
let (blob, offsets) = interner.to_blob();
62+
63+
assert_eq!(blob, b"idfoo");
64+
assert_eq!(offsets, vec![0, 2, 5]);
65+
66+
// Verify we can reconstruct strings
67+
let s0 = &blob[offsets[0] as usize..offsets[1] as usize];
68+
let s1 = &blob[offsets[1] as usize..offsets[2] as usize];
69+
assert_eq!(s0, b"id");
70+
assert_eq!(s1, b"foo");
71+
}
72+
73+
#[test]
74+
fn to_blob_empty() {
75+
let interner = Interner::new();
76+
let (blob, offsets) = interner.to_blob();
77+
78+
assert!(blob.is_empty());
79+
assert_eq!(offsets, vec![0]); // just the sentinel
80+
}
81+
82+
#[test]
83+
fn iter_yields_all_strings() {
84+
let mut interner = Interner::new();
85+
let a = interner.intern("alpha");
86+
let b = interner.intern("beta");
87+
88+
let items: Vec<_> = interner.iter().collect();
89+
assert_eq!(items, vec![(a, "alpha"), (b, "beta")]);
90+
}
91+
92+
#[test]
93+
fn symbol_from_raw_roundtrip() {
94+
let sym = Symbol::from_raw(42);
95+
assert_eq!(sym.as_u32(), 42);
96+
}

crates/plotnik-core/src/lib.rs

Lines changed: 7 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ mod interner;
1717
mod invariants;
1818
pub mod utils;
1919

20+
#[cfg(test)]
21+
mod interner_tests;
22+
#[cfg(test)]
23+
mod lib_tests;
24+
#[cfg(test)]
25+
mod utils_tests;
26+
2027
pub use interner::{Interner, Symbol};
2128

2229
/// Raw node definition from `node-types.json`.
@@ -548,80 +555,3 @@ impl NodeTypes for DynamicNodeTypes {
548555
self.valid_child_types(node_type_id).contains(&child)
549556
}
550557
}
551-
552-
#[cfg(test)]
553-
mod tests {
554-
use super::*;
555-
556-
const SAMPLE_JSON: &str = r#"[
557-
{
558-
"type": "expression",
559-
"named": true,
560-
"subtypes": [
561-
{"type": "identifier", "named": true},
562-
{"type": "number", "named": true}
563-
]
564-
},
565-
{
566-
"type": "function_declaration",
567-
"named": true,
568-
"fields": {
569-
"name": {
570-
"multiple": false,
571-
"required": true,
572-
"types": [{"type": "identifier", "named": true}]
573-
},
574-
"body": {
575-
"multiple": false,
576-
"required": true,
577-
"types": [{"type": "block", "named": true}]
578-
}
579-
}
580-
},
581-
{
582-
"type": "program",
583-
"named": true,
584-
"root": true,
585-
"fields": {},
586-
"children": {
587-
"multiple": true,
588-
"required": false,
589-
"types": [{"type": "statement", "named": true}]
590-
}
591-
},
592-
{
593-
"type": "comment",
594-
"named": true,
595-
"extra": true
596-
},
597-
{
598-
"type": "identifier",
599-
"named": true
600-
},
601-
{
602-
"type": "+",
603-
"named": false
604-
}
605-
]"#;
606-
607-
#[test]
608-
fn parse_raw_nodes() {
609-
let nodes = parse_node_types(SAMPLE_JSON).unwrap();
610-
assert_eq!(nodes.len(), 6);
611-
612-
let expr = nodes.iter().find(|n| n.type_name == "expression").unwrap();
613-
assert!(expr.named);
614-
assert!(expr.subtypes.is_some());
615-
assert_eq!(expr.subtypes.as_ref().unwrap().len(), 2);
616-
617-
let func = nodes
618-
.iter()
619-
.find(|n| n.type_name == "function_declaration")
620-
.unwrap();
621-
assert!(func.fields.contains_key("name"));
622-
assert!(func.fields.contains_key("body"));
623-
624-
let plus = nodes.iter().find(|n| n.type_name == "+").unwrap();
625-
assert!(!plus.named);
626-
}
627-
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
use crate::parse_node_types;
2+
3+
const SAMPLE_JSON: &str = r#"[
4+
{
5+
"type": "expression",
6+
"named": true,
7+
"subtypes": [
8+
{"type": "identifier", "named": true},
9+
{"type": "number", "named": true}
10+
]
11+
},
12+
{
13+
"type": "function_declaration",
14+
"named": true,
15+
"fields": {
16+
"name": {
17+
"multiple": false,
18+
"required": true,
19+
"types": [{"type": "identifier", "named": true}]
20+
},
21+
"body": {
22+
"multiple": false,
23+
"required": true,
24+
"types": [{"type": "block", "named": true}]
25+
}
26+
}
27+
},
28+
{
29+
"type": "program",
30+
"named": true,
31+
"root": true,
32+
"fields": {},
33+
"children": {
34+
"multiple": true,
35+
"required": false,
36+
"types": [{"type": "statement", "named": true}]
37+
}
38+
},
39+
{
40+
"type": "comment",
41+
"named": true,
42+
"extra": true
43+
},
44+
{
45+
"type": "identifier",
46+
"named": true
47+
},
48+
{
49+
"type": "+",
50+
"named": false
51+
}
52+
]"#;
53+
54+
#[test]
55+
fn parse_raw_nodes() {
56+
let nodes = parse_node_types(SAMPLE_JSON).unwrap();
57+
assert_eq!(nodes.len(), 6);
58+
59+
let expr = nodes.iter().find(|n| n.type_name == "expression").unwrap();
60+
assert!(expr.named);
61+
assert!(expr.subtypes.is_some());
62+
assert_eq!(expr.subtypes.as_ref().unwrap().len(), 2);
63+
64+
let func = nodes
65+
.iter()
66+
.find(|n| n.type_name == "function_declaration")
67+
.unwrap();
68+
assert!(func.fields.contains_key("name"));
69+
assert!(func.fields.contains_key("body"));
70+
71+
let plus = nodes.iter().find(|n| n.type_name == "+").unwrap();
72+
assert!(!plus.named);
73+
}

0 commit comments

Comments
 (0)