1use crate::TextSpan;
2use colored::Colorize;
3use std::{fmt::Debug, path::PathBuf};
4
5#[derive(Clone)]
9pub struct Frame {
10 pub name: String,
12 pub span: TextSpan,
14 pub path: String,
16}
17
18impl Frame {
19 pub fn new(name: impl Into<String>, span: TextSpan, path: impl Into<String>) -> Self {
36 Self {
37 name: name.into(),
38 span,
39 path: path.into(),
40 }
41 }
42
43 pub fn path_or_unknown(path: Option<PathBuf>) -> String {
45 let path = path
46 .map(PathBuf::from)
47 .unwrap_or_else(|| PathBuf::from("unknown"));
48
49 path.to_string_lossy().to_string()
50 }
51}
52
53impl Debug for Frame {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 write!(
56 f,
57 " {} {} {}{}{}{}{}",
58 "at".dimmed(),
59 self.name.bold(),
60 self.path.cyan(),
61 ":".dimmed(),
62 self.span.start.line.to_string().yellow(),
63 ":".dimmed(),
64 self.span.start.column.to_string().dimmed().yellow()
65 )
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72 use crate::Position;
73
74 #[test]
75 fn test_frame_new() {
76 let frame = Frame::new(
77 "main",
78 TextSpan::new(
79 Position::new(1, 1, 1),
80 Position::new(1, 1, 1),
81 "main".into(),
82 ),
83 ".\\src\\main.roan",
84 );
85
86 assert_eq!(frame.name, "main");
87 assert_eq!(frame.span.start.line, 1);
88 assert_eq!(frame.span.start.column, 1);
89 assert_eq!(frame.path, ".\\src\\main.roan");
90 }
91
92 #[test]
93 fn test_frame_path_or_unknown() {
94 let path = Some(PathBuf::from("tests\\test.roan"));
95 assert_eq!(Frame::path_or_unknown(path), "tests\\test.roan");
96
97 let path = None;
98 assert_eq!(Frame::path_or_unknown(path), "unknown");
99 }
100}