devscout-rs 0.9.0

Fast code index for C# and TypeScript codebases -- map, find, refs, impact from the CLI.
use super::*;

fn purpose(src: &str) -> Option<String> {
    extract_rs_file(src).purpose
}

#[test]
fn an_inner_line_doc_gives_its_first_non_empty_line_as_the_prefix() {
    let src = "//!\n//! Shelves and the widgets on them.\n//! More detail.\nstruct Widget;\nfn polish() {}\n";
    assert_eq!(
        purpose(src).as_deref(),
        Some("Shelves and the widgets on them. — struct Widget | fn polish")
    );
}

#[test]
fn an_inner_block_doc_gives_its_first_non_empty_line() {
    let src = "/*!\n * Cabinet layout.\n * Second line.\n */\nenum Door { Left }\n";
    assert_eq!(purpose(src).as_deref(), Some("Cabinet layout. — enum Door"));
}

#[test]
fn a_plain_leading_comment_gives_its_first_line() {
    assert_eq!(
        purpose("// Tone tables.\n// more\nconst A: u8 = 1;\n").as_deref(),
        Some("Tone tables. — const A")
    );
    assert_eq!(
        purpose("/* Block note. */\nstatic B: u8 = 1;\n").as_deref(),
        Some("Block note. — static B")
    );
    assert_eq!(
        purpose("/*\n  body only\n*/\nstatic B: u8 = 1;\n").as_deref(),
        Some("static B"),
        "an empty first line gives no prefix"
    );
}

#[test]
fn an_outer_doc_first_gives_no_prefix() {
    assert_eq!(
        purpose("/// Widget doc.\nstruct Widget;\n").as_deref(),
        Some("struct Widget")
    );
}

#[test]
fn a_shebang_and_inner_attributes_are_skipped_before_the_prefix() {
    let src = "#!/usr/bin/env run\n#![allow(dead_code)]\n#![deny(missing_docs)]\n//! Tool entry.\nfn main() {}\n";
    assert_eq!(purpose(src).as_deref(), Some("Tool entry. — fn main"));
}

#[test]
fn a_use_first_gives_the_segments_alone() {
    let src = "use std::fmt;\n// not leading\nfn tone() {}\n";
    assert_eq!(purpose(src).as_deref(), Some("fn tone"));
}

#[test]
fn segments_group_by_kind_then_source_order_and_skip_nested_items() {
    let src = "\
mod inner { struct Hidden; }
fn b() {}
macro_rules! m { () => {}; }
static S: u8 = 0;
const C: u8 = 0;
fn a() {}
type T = u8;
trait Tr { fn nested(&self); }
union U { x: u8 }
enum E { V }
struct St;
impl St { fn method() {} }
";
    assert_eq!(
        purpose(src).as_deref(),
        Some("struct St | enum E | union U | trait Tr | type T | fn b | fn a | const C | static S | macro_rules m | mod inner")
    );
}

#[test]
fn a_file_with_neither_gives_none() {
    assert_eq!(purpose("use std::fmt;\nuse std::io;\n"), None);
    assert_eq!(purpose(""), None);
}

#[test]
fn a_long_purpose_is_cut_at_the_shared_cap() {
    let mut src = String::from("//! Many functions.\n");
    for i in 0..40 {
        src.push_str(&format!("fn function_number_{i}() {{}}\n"));
    }
    let p = purpose(&src).expect("a purpose");
    assert_eq!(p.encode_utf16().count(), 200);
    assert!(p.starts_with("Many functions. — fn function_number_0 | "));
    assert!(p.ends_with("..."));
}

#[test]
fn items_of_an_extern_block_are_not_segments() {
    let src = "extern \"C\" {\n    fn host_count() -> i32;\n}\nfn local() {}\n";
    assert_eq!(purpose(src).as_deref(), Some("fn local"));
}