//! **源码结构断言**的小工具:把某个函数的实现文本切出来(只给测试用)。 //! //! ## 为什么要读源码(而不是量 Element) //! //! iced 的 `Element` 没有几何内省接口(`size()` 只是 `Size`,取不到布局结果), //! 所以「页面把块摆在哪 / 有没有在行之间叠间距」在单测里**量不到**。M102 r1 的教训正是这个: //! 护栏只喂 `frame_metrics()` 与常量重算,把 `frame::body` 换回「居中 424」的实现, //! 测试照样全绿——钉住的是公式,不是摆法。 //! //! 本仓已有同一条纪律的先例:`tests/no_hardcoded_tokens.rs` 直接扫 `src/**`, //! `pages/download/tests.rs::every_download_key_is_referenced_by_the_page` 用 `include_str!` //! 扫页面源码找 key 引用。这里只是把「切出某个函数」这件小事做成一个共用工具, //! 让护栏能断言「盒子是不是照那个数建的」。 //! //! ## 边界(它抓不住什么) //! //! 它读的是**文本**:换个写法(先赋值给局部变量再 `.width(...)`)就可能绕过。 //! 所以它只配一条**明确的契约**用:`frame::body` / `frame::prose` / `list_column` 这几处的 //! 写法本身就是契约的一部分(它们各自只有 5~10 行),不是为了抠实现细节。 //! 真要守像素,还是得靠软件渲染金图(`shot::diff`,绑 Windows + 字体栈,属另一个决定)。 /// 把 `source` 里第一个 `signature` 起始、到该函数**顶层**右花括号为止的文本切出来。 /// /// 「顶层」= 行首的 `}`(本仓函数都是顶格收尾,内层块都是缩进收尾),所以不会在内层 `}` 提前断。 /// /// # Panics /// 签名不存在时 panic(护栏自己的前置条件坏了要立刻红,不能静默放行)。 pub(crate) fn function_body<'a>(source: &'a str, signature: &str) -> &'a str { let start = source .find(signature) .unwrap_or_else(|| panic!("源码里找不到签名 {signature:?}")); let rest = &source[start..]; let end = rest.find("\n}").map_or(rest.len(), |index| index + 2); &rest[..end] } #[cfg(test)] mod tests;