⭐️ A friendly language for building type-safe, scalable systems!
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 117 lines 4.3 kB view raw
1use camino::{Utf8Path, Utf8PathBuf}; 2use gleam_core::{ 3 io::{Content, FileSystemWriter, memory::InMemoryFileSystem}, 4 version::COMPILER_VERSION, 5}; 6use itertools::Itertools; 7use regex::Regex; 8use std::{collections::HashMap, fmt::Write, sync::LazyLock}; 9 10#[derive(Debug)] 11pub struct TestCompileOutput { 12 pub files: HashMap<Utf8PathBuf, Content>, 13 pub warnings: Vec<gleam_core::Warning>, 14} 15 16impl TestCompileOutput { 17 pub fn as_overview_text(&self) -> String { 18 let mut buffer = String::new(); 19 for (path, content) in self.files.iter().sorted_by(|a, b| a.0.cmp(b.0)) { 20 let normalised_path = if path.as_str().contains("cases") { 21 path.as_str() 22 .split("cases") 23 .skip(1) 24 .collect::<String>() 25 .as_str() 26 .replace('\\', "/") 27 .split('/') 28 .skip(1) 29 .join("/") 30 } else { 31 path.as_str().replace('\\', "/") 32 }; 33 buffer.push_str("//// "); 34 buffer.push_str(&normalised_path); 35 buffer.push('\n'); 36 37 let extension = path.extension(); 38 match content { 39 _ if extension == Some("cache") => buffer.push_str("<.cache binary>"), 40 Content::Binary(data) => write!(buffer, "<{} byte binary>", data.len()).unwrap(), 41 42 Content::Text(_) if normalised_path.ends_with("@@main.erl") => { 43 write!(buffer, "<erlang entrypoint>").unwrap() 44 } 45 46 Content::Text(text) => { 47 let format_path = |caps: &regex::Captures| { 48 caps.get(1) 49 .expect("file path") 50 .as_str() 51 .replace("\\\\", "/") 52 }; 53 let text = FILE_LINE_REGEX.replace_all(text, |caps: &regex::Captures| { 54 let path = format_path(caps); 55 let line_number = caps.get(2).expect("line number").as_str(); 56 format!("-file(\"{path}\", {line_number}).") 57 }); 58 let text = FILEPATH_MACRO_REGEX 59 .replace_all(text.to_string().as_str(), |caps: &regex::Captures| { 60 let path = format_path(caps); 61 format!("-define(FILEPATH, \"{path}\").") 62 }) 63 .replace(COMPILER_VERSION, "<gleam compiler version string>"); 64 buffer.push_str(&text) 65 } 66 }; 67 buffer.push('\n'); 68 buffer.push('\n'); 69 } 70 71 for warning in self.warnings.iter().map(|w| w.to_pretty_string()).sorted() { 72 write!(buffer, "//// Warning\n{}", normalise_diagnostic(&warning)).unwrap(); 73 buffer.push('\n'); 74 buffer.push('\n'); 75 } 76 77 buffer 78 } 79} 80 81pub fn to_in_memory_filesystem(path: &Utf8Path) -> InMemoryFileSystem { 82 let fs = InMemoryFileSystem::new(); 83 84 let files = walkdir::WalkDir::new(path) 85 .follow_links(true) 86 .into_iter() 87 .filter_map(Result::ok) 88 .filter(|entry| entry.file_type().is_file()) 89 .map(|entry| entry.into_path()); 90 91 for fullpath in files { 92 let content = std::fs::read(&fullpath).unwrap(); 93 let path = fullpath.strip_prefix(path).unwrap(); 94 fs.write_bytes(Utf8Path::from_path(path).unwrap(), &content) 95 .unwrap(); 96 } 97 98 fs 99} 100 101static FILE_LINE_REGEX: LazyLock<Regex> = 102 LazyLock::new(|| Regex::new(r#"-file\("([^"]+)", (\d+)\)\."#).expect("Invalid regex")); 103 104static FILEPATH_MACRO_REGEX: LazyLock<Regex> = 105 LazyLock::new(|| Regex::new(r#"-define\(FILEPATH, "([^"]+)"\)\."#).expect("Invalid regex")); 106 107pub fn normalise_diagnostic(text: &str) -> String { 108 // There is an extra ^ on Windows in some error messages' code 109 // snippets. 110 // I've not managed to determine why this is yet (it is especially 111 // tricky without a Windows computer) so for now we just squash them 112 // in these cross-platform tests. 113 Regex::new(r"\^+") 114 .expect("^ sequence regex") 115 .replace_all(text, "^") 116 .replace('\\', "/") 117}