diff options
-rw-r--r-- | Cargo.lock | 112 | ||||
-rw-r--r-- | Cargo.toml | 4 | ||||
-rw-r--r-- | src/errors/merge_error.rs | 31 | ||||
-rw-r--r-- | src/lib.rs | 3 | ||||
-rw-r--r-- | src/reports/mod.rs | 73 | ||||
-rw-r--r-- | src/reports/source_hierarchy.rs | 22 | ||||
-rw-r--r-- | src/reports/source_symbols.rs | 6 | ||||
-rw-r--r-- | src/reports/unused_symbols.rs | 4 |
8 files changed, 176 insertions, 79 deletions
@@ -3,28 +3,122 @@ version = 4 [[package]] -name = "ansi" -version = "1.0.0" -source = "git+git://benbridle.com/ansi?tag=v1.0.0#81d47867c2c97a9ae1d1c8fdfcd42c582410ad2a" - -[[package]] name = "assembler" version = "2.2.2" dependencies = [ - "ansi", + "inked", "log", "vagabond", ] [[package]] +name = "inked" +version = "1.0.0" +source = "git+git://benbridle.com/inked?tag=v1.0.0#2954d37b638fa2c1dd3d51ff53f08f475aea6ea3" +dependencies = [ + "termcolor", +] + +[[package]] name = "log" -version = "1.1.2" -source = "git+git://benbridle.com/log?tag=v1.1.2#3d5d1f7a19436151ba1dd52a2b50664969d90db6" +version = "2.0.0" +source = "git+git://benbridle.com/log?tag=v2.0.0#a38d3dd487594f41151db57625410d1b786bebe4" +dependencies = [ + "inked", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ - "ansi", + "winapi-util", ] [[package]] name = "vagabond" version = "1.1.1" source = "git+git://benbridle.com/vagabond?tag=v1.1.1#b190582517e6008ad1deff1859f15988e4efaa26" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" @@ -4,6 +4,6 @@ version = "2.2.2" edition = "2021" [dependencies] -ansi = { git = "git://benbridle.com/ansi", tag = "v1.0.0" } -log = { git = "git://benbridle.com/log", tag = "v1.1.2" } +inked = { git = "git://benbridle.com/inked", tag = "v1.0.0" } +log = { git = "git://benbridle.com/log", tag = "v2.0.0" } vagabond = { git = "git://benbridle.com/vagabond", tag = "v1.1.1" } diff --git a/src/errors/merge_error.rs b/src/errors/merge_error.rs index 89f55a2..01cbcba 100644 --- a/src/errors/merge_error.rs +++ b/src/errors/merge_error.rs @@ -1,8 +1,5 @@ use crate::*; -use ansi::*; -use log::error; - use std::collections::HashSet; @@ -14,15 +11,19 @@ pub struct MergeError<'a> { impl MergeError<'_> { pub fn report(&self) { - error!("A cyclic dependency was found between the following files:"); + let message = "A cyclic dependency was found between the following files:"; + let mut details = InkedString::new(); for id in &self.cyclic_unit_ids { let unit = &self.resolver.source_units[*id]; let path = &unit.source_unit.path(); match unit.source_unit.name() { - Some(name) => - eprintln!("{name}{NORMAL}{DIM} ({path}){NORMAL}"), - None => - eprintln!("{path}"), + Some(name) => { + details.push(ink!("{name}")); + details.push(ink!(" ({path})\n").dim()); + } + None => { + details.push(ink!("{path}\n")); + } }; // Print each parent involved in the dependency cycle. for parent_id in &unit.parent_ids { @@ -30,10 +31,13 @@ impl MergeError<'_> { let parent_unit = &self.resolver.source_units[*parent_id]; let parent_path = &parent_unit.source_unit.path(); match parent_unit.source_unit.name() { - Some(parent_name) => - eprintln!(" => {parent_name} {DIM}({parent_path}){NORMAL}"), - None => - eprintln!(" => {parent_path}"), + Some(parent_name) => { + details.push(ink!(" => {parent_name}")); + details.push(ink!(" ({parent_path})\n").dim()); + } + None => { + details.push(ink!(" => {parent_path}\n")); + } }; // Report all referenced symbols that are defined by this parent. let mut reported_definition_ids = HashSet::new(); @@ -42,12 +46,13 @@ impl MergeError<'_> { if reported_definition_ids.insert(reference.definition) { let definition = &self.resolver.definitions[reference.definition]; if definition.tracked.source_id == *parent_id { - eprintln!(" {:?}", definition.tracked.symbol); + details.push(ink!(" {:?}\n", definition.tracked.symbol)); } } } } } } + log_error(message, Some(details)); } } @@ -12,3 +12,6 @@ pub use types::*; pub type ParseFn = fn(&str, Option<&Path>) -> Option<Vec<Symbol>>; pub type PushFn = fn(&mut String, &SourceFile); + +use log::*; +use inked::*; diff --git a/src/reports/mod.rs b/src/reports/mod.rs index bbddba9..9fc5e27 100644 --- a/src/reports/mod.rs +++ b/src/reports/mod.rs @@ -10,53 +10,52 @@ pub use unused_symbols::*; use crate::*; -pub use log::LogLevel; -pub use ansi::*; - pub fn report_source_issue(level: LogLevel, context: &Context, message: &str) { - let mut reporter = SourceIssueReporter::new(context, message, level); + let mut reporter = SourceIssueReporter::new(context, level); reporter.format_source_span(context.source); - let string = reporter.output; + let details = reporter.details; // Print the completed message. match level { - LogLevel::Info => log::info!( "{string}"), - LogLevel::Warn => log::warn!( "{string}"), - LogLevel::Error => log::error!("{string}"), - LogLevel::Fatal => log::fatal!("{string}"), + LogLevel::Info => log_info(message, Some(details)), + LogLevel::Warn => log_warn(message, Some(details)), + LogLevel::Error => log_error(message, Some(details)), + LogLevel::Fatal => log_fatal(message, Some(details)), } } struct SourceIssueReporter<'a> { context: &'a Context<'a>, - output: String, + details: InkedString, level: LogLevel, digits: usize, } impl<'a> SourceIssueReporter<'a> { - pub fn new(context: &'a Context<'a>, message: &str, level: LogLevel) -> Self { - let output = format!("{message}\n"); + pub fn new(context: &'a Context<'a>, level: LogLevel) -> Self { + let details = InkedString::new(); let digits = get_end_line_number(context.source).to_string().len(); - Self { context, level, output, digits } + Self { context, level, details, digits } } pub fn format_source_span(&mut self, source: &SourceSpan) { let colour = match self.level { - LogLevel::Info => BLUE, - LogLevel::Warn => YELLOW, - LogLevel::Error => RED, - LogLevel::Fatal => RED, + LogLevel::Info => Colour::Blue, + LogLevel::Warn => Colour::Yellow, + LogLevel::Error => Colour::Red, + LogLevel::Fatal => Colour::Red, }; // Print location line. - self.output.push_str(NORMAL); let arrow = "-->"; + let w = self.digits + 3; + self.details.push(ink!("{arrow:>w$} ").blue()); let location = source.location(); - self.push(&format!("{BLUE}{arrow:>w$}{NORMAL} {location}\n", w=self.digits+3)); + self.details.push(ink!("{location}\n")); + // Print each source line. let line_count = location.end.line - location.start.line + 1; for line_i in 0..line_count { let merged_i = source.in_merged.start.line + line_i; @@ -74,25 +73,30 @@ impl<'a> SourceIssueReporter<'a> { }; // Print source code line. - self.push(&format!("{BLUE} {line_num:>w$} | {NORMAL}", line_num=location_i+1, w=self.digits)); + let line_num = location_i + 1; + let w = self.digits; + self.details.push(ink!(" {line_num:>w$} | ").blue()); + let mut line_colour = None; for (i, c) in source_line.chars().enumerate() { - if i == left { self.output.push_str(colour) } - if i == right { self.output.push_str(NORMAL) } - self.output.push(c); + if i == left { line_colour = Some(colour) } + if i == right { line_colour = None } + self.details.push(ink!("{c}").set_colour(line_colour)); } - self.output.push_str(NORMAL); - self.output.push('\n'); + self.details.push(ink!("\n")); // Print an underline on the final line. if line_i + 1 == line_count { // Print source code underline. let space = " "; - self.push(&format!("{BLUE} {space:>w$} | {NORMAL}", w=self.digits)); - for _ in 0..left { self.output.push_str(" "); } - self.output.push_str(colour); - for _ in left..right { self.output.push_str("^"); } - self.output.push_str(NORMAL); - self.output.push('\n'); + let w = self.digits; + self.details.push(ink!(" {space:>w$} | ").blue()); + for _ in 0..left { + self.details.push(ink!(" ")); + } + for _ in left..right { + self.details.push(ink!("^").set_colour(Some(colour))); + } + self.details.push(ink!("\n")); } } @@ -100,13 +104,6 @@ impl<'a> SourceIssueReporter<'a> { if let Some(child) = &source.child { self.format_source_span(&child); } - - // Remove the trailing new-line. - self.output.pop(); - } - - fn push(&mut self, string: &str) { - self.output.push_str(&string); } } diff --git a/src/reports/source_hierarchy.rs b/src/reports/source_hierarchy.rs index 2e88a77..f391785 100644 --- a/src/reports/source_hierarchy.rs +++ b/src/reports/source_hierarchy.rs @@ -7,7 +7,7 @@ pub struct SourceHierarchy<'a> { impl<'a> SourceHierarchy<'a> { pub fn report(&self) { - eprintln!("."); + ink!(".").eprintln(); let len = self.resolver.root_unit_ids.len(); for (i, id) in self.resolver.root_unit_ids.iter().enumerate() { let end = i + 1 == len; @@ -19,29 +19,29 @@ impl<'a> SourceHierarchy<'a> { // A level entry is true if all entries in that level have been printed. for level in &levels { match level { - false => eprint!("│ "), - true => eprint!(" "), + false => ink!("│ ").eprint(), + true => ink!(" ").eprint(), } } // The end value is true if all siblings of this entry have been printed. match end { - false => eprint!("├── "), - true => eprint!("└── "), + false => ink!("├── ").eprint(), + true => ink!("└── ").eprint(), } let unit = &self.resolver.source_units[id]; let path_str = &unit.source_unit.main.path.as_os_str().to_string_lossy(); if let Some(name_str) = unit.source_unit.name() { - eprint!("{name_str}{BLUE}"); - if unit.source_unit.head.is_some() { eprint!(" +head") } - if unit.source_unit.tail.is_some() { eprint!(" +tail") } + ink!("{name_str}").eprint(); + if unit.source_unit.head.is_some() { ink!(" +head").blue().eprint() } + if unit.source_unit.tail.is_some() { ink!(" +tail").blue().eprint() } let mut unresolved = 0; for symbol in &self.resolver.unresolved { if symbol.source_id == id { unresolved += 1; } } - if unresolved > 0 { eprint!("{RED} ({unresolved})"); } - eprintln!("{NORMAL} {DIM}({path_str}){NORMAL}"); + if unresolved > 0 { ink!(" ({unresolved})").red().eprint(); } + ink!(" ({path_str})").dim().eprintln(); } else { - eprintln!("{path_str}"); + ink!("{path_str}").eprintln(); } levels.push(end); let len = unit.child_ids.len(); diff --git a/src/reports/source_symbols.rs b/src/reports/source_symbols.rs index 976660f..a042f1c 100644 --- a/src/reports/source_symbols.rs +++ b/src/reports/source_symbols.rs @@ -9,7 +9,7 @@ impl<'a> SourceSymbols<'a> { pub fn report(&self) { for definition in &self.resolver.definitions { let message = format!( - "Definition '{BOLD}{:?}{NORMAL}' (resolves {})", + "Definition '{:?}' (resolves {})", definition.tracked.symbol, definition.references.len()); let context = definition.tracked.context(self.resolver); report_source_issue(LogLevel::Info, &context, &message); @@ -18,7 +18,7 @@ impl<'a> SourceSymbols<'a> { for reference in &self.resolver.resolved { let definition = &self.resolver.definitions[reference.definition]; let message = format!( - "Resolved reference '{BOLD}{:?}{NORMAL}' (defined by {:?})", + "Resolved reference '{:?}' (defined by {:?})", reference.tracked.symbol, definition.tracked.symbol); let context = reference.tracked.context(self.resolver); report_source_issue(LogLevel::Info, &context, &message); @@ -26,7 +26,7 @@ impl<'a> SourceSymbols<'a> { for reference in &self.resolver.unresolved { let message = format!( - "Unresolved reference '{BOLD}{:?}{NORMAL}'", reference.symbol); + "Unresolved reference '{:?}'", reference.symbol); let context = reference.context(self.resolver); report_source_issue(LogLevel::Warn, &context, &message); } diff --git a/src/reports/unused_symbols.rs b/src/reports/unused_symbols.rs index 7cd3596..90cb7d1 100644 --- a/src/reports/unused_symbols.rs +++ b/src/reports/unused_symbols.rs @@ -9,9 +9,7 @@ impl<'a> UnusedSymbols<'a> { pub fn report(&self) { for definition in &self.resolver.definitions { if definition.references.is_empty() { - let message = format!( - "Unused definition '{BOLD}{:?}{NORMAL}'", - definition.tracked.symbol); + let message = format!("Unused definition '{:?}'", definition.tracked.symbol); let context = definition.tracked.context(self.resolver); report_source_issue(LogLevel::Warn, &context, &message); } |