Rudimentary logging and lints

This commit is contained in:
mars 2024-02-10 18:32:10 -07:00
parent 07e8fbad93
commit 94c079a7e9
4 changed files with 233 additions and 22 deletions

103
Cargo.lock generated
View File

@ -46,7 +46,7 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
dependencies = [
"windows-sys",
"windows-sys 0.52.0",
]
[[package]]
@ -56,7 +56,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
dependencies = [
"anstyle",
"windows-sys",
"windows-sys 0.52.0",
]
[[package]]
@ -115,6 +115,16 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "colored"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8"
dependencies = [
"lazy_static",
"windows-sys 0.48.0",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.5"
@ -175,6 +185,12 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "log"
version = "0.4.20"
@ -236,6 +252,7 @@ name = "saul"
version = "0.1.0"
dependencies = [
"clap",
"colored",
"ignore",
]
@ -329,13 +346,37 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
"windows-targets 0.52.0",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
@ -344,51 +385,93 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
"windows_aarch64_gnullvm 0.52.0",
"windows_aarch64_msvc 0.52.0",
"windows_i686_gnu 0.52.0",
"windows_i686_msvc 0.52.0",
"windows_x86_64_gnu 0.52.0",
"windows_x86_64_gnullvm 0.52.0",
"windows_x86_64_msvc 0.52.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.0"

View File

@ -8,4 +8,5 @@ license = "AGPL-3.0-or-later"
[dependencies]
clap = { version = "4.5.0", features = ["derive"] }
colored = "2.1.0"
ignore = "0.4.22"

119
src/log.rs Normal file
View File

@ -0,0 +1,119 @@
// Copyright (c) 2024 Marceline Cramer
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This file is part of Saul.
//
// Saul is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// Saul is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Saul. If not, see <https://www.gnu.org/licenses/>.
use std::{cell::RefCell, collections::HashMap};
use colored::*;
#[derive(Clone, Copy, Debug)]
pub enum LintLevel {
Deny,
Warning,
Ignore,
}
pub fn init_lints() {
unsafe {
LINTS = Some(HashMap::new());
}
}
pub fn lint(name: &str, body: &str) {
let lints = unsafe { LINTS.as_mut().expect("lints uninitialized") };
let level = lints.get(name).copied().unwrap_or(LintLevel::Warning);
let prefix = match level {
LintLevel::Deny => format!("deny({name})").red().bold(),
LintLevel::Warning => format!("warning({name})").yellow().bold(),
LintLevel::Ignore => return,
};
let msg = format!("{prefix}: {body}");
log(msg.as_str());
}
static mut LINTS: Option<HashMap<String, LintLevel>> = None;
pub fn log(body: &str) {
with_logger(|l| l.message(body));
}
pub fn with_context(ctx: &str, body: impl FnOnce()) {
with_logger(|l| l.push_context(ctx.to_string()));
body();
with_logger(|l| l.pop_context());
}
static mut LOGGER: RefCell<Logger> = RefCell::new(Logger::new());
fn with_logger(f: impl Fn(&mut Logger)) {
unsafe { f(&mut LOGGER.borrow_mut()) }
}
struct Context {
label: String,
rendered: bool,
}
struct Logger {
contexts: Vec<Context>,
}
impl Logger {
const fn new() -> Self {
Self { contexts: vec![] }
}
fn message(&mut self, body: &str) {
let indent = |lvl| std::iter::repeat(" ").take(lvl).collect::<String>();
let mut rendered_contexts = Vec::with_capacity(self.contexts.len());
for (lvl, ctx) in self.contexts.iter_mut().enumerate().rev() {
if ctx.rendered {
break;
}
let label = ctx.label.underline();
let out = format!("{}{}", indent(lvl), label);
rendered_contexts.push(out);
ctx.rendered = true;
}
while let Some(out) = rendered_contexts.pop() {
println!("{out}");
}
let lvl = self.contexts.len();
let indent = indent(lvl);
for line in body.lines() {
println!("{}{}", indent, line);
}
}
fn push_context(&mut self, label: String) {
self.contexts.push(Context {
label,
rendered: false,
});
}
fn pop_context(&mut self) {
self.contexts.pop();
}
}

View File

@ -21,6 +21,7 @@ use std::{fs::File, io::BufReader, path::PathBuf};
use clap::Parser;
use ignore::Walk;
mod log;
mod parse;
#[derive(Debug, Parser)]
@ -31,6 +32,7 @@ struct Args {
fn main() {
let mut args = Args::parse();
log::init_lints();
if args.input.is_empty() {
args.input = vec![".".into()];
@ -55,20 +57,26 @@ fn main() {
}
let path = entry.path();
let f = File::open(path).unwrap();
let mut read = BufReader::new(f);
let filename = path.to_string_lossy().to_owned();
let lines = match parse::Language::RUST.read_header(&mut read) {
Ok(lines) => lines,
Err(err) => {
eprintln!("error parsing {:?}: {:?}", path, err);
continue;
log::with_context(&filename, || {
let f = File::open(path).unwrap();
let mut read = BufReader::new(f);
let lines = match parse::Language::RUST.read_header(&mut read) {
Ok(lines) => lines,
Err(err) => {
log::log(&format!("error parsing {:?}: {:?}", path, err));
return;
}
};
let header = parse::Header::parse(lines).unwrap();
if header.spdx.is_none() {
log::lint("missing_spdx", "header is missing SPDX license identifier");
}
};
let header = parse::Header::parse(lines).unwrap();
println!("{:?}: {:#?}", path, header);
});
}
}
}