crates/gunnar-ui-web/src/code.rs
//! **The code of a page, for the tests that can only read it** (stinky #22).
//!
//! The pages are `#[cfg(target_arch = "wasm32")]` and the host has no DOM, so
//! a few promises about them — this card swaps through that rule, that page
//! reads this route — are held to the page's source. A test that searched the
//! raw file went green when the words stood in a COMMENT, which is exactly
//! where a removed call leaves them. [`of`] is the source with every comment
//! taken out (string and char literals kept whole, a `//` inside a URL is not
//! a comment), so what such a test finds is code that compiles.
//!
//! Where a promise CAN be run — a rule in a host module, a route on the
//! server's router — it is a behaviour test instead, and not here.
/// `src` with its line, doc and (nested) block comments removed. A comment
/// becomes one space; a line comment keeps its newline.
pub fn of(src: &str) -> String {
let b = src.as_bytes();
let mut out = String::with_capacity(src.len());
let mut i = 0;
let mut kept = 0;
let keep = |out: &mut String, from: usize, to: usize| out.push_str(&src[from..to]);
while i < b.len() {
if b[i..].starts_with(b"//") {
keep(&mut out, kept, i);
out.push(' ');
i = b[i..].iter().position(|&x| x == b'\n').map_or(b.len(), |j| i + j);
kept = i;
continue;
}
if b[i..].starts_with(b"/*") {
keep(&mut out, kept, i);
out.push(' ');
let mut depth = 0usize;
while i < b.len() {
if b[i..].starts_with(b"/*") {
depth += 1;
i += 2;
} else if b[i..].starts_with(b"*/") {
depth -= 1;
i += 2;
if depth == 0 {
break;
}
} else {
i += 1;
}
}
kept = i;
continue;
}
let c = b[i];
if c == b'r' && (i == 0 || !(b[i - 1].is_ascii_alphanumeric() || b[i - 1] == b'_')) {
let hashes = src[i + 1..].bytes().take_while(|&x| x == b'#').count();
if b.get(i + 1 + hashes) == Some(&b'"') {
let start = i + 2 + hashes;
let close = format!("\"{}", "#".repeat(hashes));
i = src[start..].find(&close).map_or(src.len(), |j| start + j + close.len());
continue;
}
}
if c == b'\'' {
// A char literal ('"' included) or a lifetime.
let rest = &src[i + 1..];
match rest.chars().next() {
Some('\\') => i += 1 + 2 + rest.get(2..).and_then(|r| r.find('\'')).map_or(0, |j| j + 1),
Some(ch) if rest[ch.len_utf8()..].starts_with('\'') => i += 1 + ch.len_utf8() + 1,
_ => i += 1,
}
continue;
}
if c == b'"' {
i += 1;
while i < b.len() && b[i] != b'"' {
i += if b[i] == b'\\' { 2 } else { 1 };
}
i += 1;
continue;
}
i += 1;
}
keep(&mut out, kept, src.len().min(i.max(kept)));
out
}
#[cfg(test)]
mod tests {
use super::of;
/// ★ **Words in a comment are not code** — the way a scanner went green
/// on a call that had been removed and left behind in a sentence.
#[test]
fn a_comment_is_not_code() {
let src = "/// calls `machine::swap(` on every answer — ändå\n\
fn card() {\n // machine::swap(&a, &b) was here\n /* and /* nested */ machine::swap( */ draw();\n}\n";
let code = of(src);
assert!(!code.contains("machine::swap("), "{code}");
assert!(code.contains("fn card()") && code.contains("draw();"), "{code}");
}
/// …while a string that holds `//` or `/*`, a raw string and a char
/// literal are code, whole.
#[test]
fn literals_are_code_whole() {
let src = r##"fn f() { let u = "https://x/api/server-key"; let r = r#"/* not "a" comment */"#; let q = '"'; let s = '/'; let å = '—'; g::<'a>(); } // gone"##;
let code = of(src);
assert!(code.contains(r#""https://x/api/server-key""#), "{code}");
assert!(code.contains(r##"r#"/* not "a" comment */"#"##), "{code}");
assert!(code.contains(r#"'"'"#) && code.contains("'/'") && code.contains("g::<'a>()") && code.contains("let å = '—';"), "{code}");
assert!(!code.contains("gone"), "{code}");
}
}