From 9aa8594f65cf7c31333d5851cec219e7f0930d1a Mon Sep 17 00:00:00 2001 From: xnacly <47723417+xNaCly@users.noreply.github.com> Date: Thu, 5 Dec 2024 14:33:26 +0100 Subject: [PATCH] rules+main: migrate from toml to lua for configuration this change is necessary because i want to allow the user to hook into the analysis of sql statements via a lua api, this would have been disgusting in toml --- Cargo.lock | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + README.md | 49 +++++---- leibniz.lua | 20 ++++ leibniz.toml | 20 ---- src/main.rs | 49 ++++++--- src/rules.rs | 18 ++-- 7 files changed, 368 insertions(+), 73 deletions(-) create mode 100644 leibniz.lua delete mode 100644 leibniz.toml diff --git a/Cargo.lock b/Cargo.lock index d1836d5..46f8cc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,7 +38,7 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -48,9 +48,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.59.0", ] +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bstr" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "cc" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "clap" version = "4.5.21" @@ -97,12 +134,38 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "erased-serde" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d" +dependencies = [ + "serde", + "typeid", +] + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "hashbrown" version = "0.15.0" @@ -115,6 +178,15 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "indexmap" version = "2.6.0" @@ -131,12 +203,130 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "libc" +version = "0.2.167" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "lua-src" +version = "547.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edaf29e3517b49b8b746701e5648ccb5785cde1c119062cbabbc5d5cd115e42" +dependencies = [ + "cc", +] + +[[package]] +name = "luajit-src" +version = "210.5.11+97813fb" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3015551c284515db7c30c559fc1080f9cb9ee990d1f6fca315451a107c7540bb" +dependencies = [ + "cc", + "which", +] + [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "mlua" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea43c3ffac2d0798bd7128815212dd78c98316b299b7a902dabef13dc7b6b8d" +dependencies = [ + "bstr", + "either", + "erased-serde", + "mlua-sys", + "num-traits", + "parking_lot", + "rustc-hash", + "serde", + "serde-value", +] + +[[package]] +name = "mlua-sys" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63a11d485edf0f3f04a508615d36c7d50d299cf61a7ee6d3e2530651e0a31771" +dependencies = [ + "cc", + "cfg-if", + "lua-src", + "luajit-src", + "pkg-config", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + [[package]] name = "proc-macro2" version = "1.0.87" @@ -155,6 +345,40 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rustc-hash" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" + +[[package]] +name = "rustix" +version = "0.38.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "serde" version = "1.0.210" @@ -164,6 +388,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.210" @@ -184,11 +418,24 @@ dependencies = [ "serde", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "sqleibniz" version = "0.1.0" dependencies = [ "clap", + "mlua", "serde", "toml", ] @@ -244,6 +491,12 @@ dependencies = [ "winnow", ] +[[package]] +name = "typeid" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e" + [[package]] name = "unicode-ident" version = "1.0.13" @@ -256,6 +509,27 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "which" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" +dependencies = [ + "either", + "home", + "rustix", + "winsafe", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.59.0" @@ -337,3 +611,9 @@ checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] + +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" diff --git a/Cargo.toml b/Cargo.toml index cdb99b5..2b8117b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,5 +10,6 @@ trace_parser = [] [dependencies] clap = { version = "4.5", features = ["derive"] } +mlua = {version = "0.10.2", features = ["lua54", "vendored", "serialize"]} serde = { version = "1.0", features = ["derive"] } toml = "0.8.19" diff --git a/README.md b/README.md index aa1f8a2..1effa3c 100644 --- a/README.md +++ b/README.md @@ -157,33 +157,32 @@ Options: ### Configuration -Sqleibniz can be configured via a `leibniz.toml` file, this file has to be +Sqleibniz can be configured via a `leibniz.lua` file, this file has to be accessible to sqleibniz by existing at the path sqleibniz is invoked at. Consult [src/rules.rs](./src/rules.rs) for configuration documentation and -[leibniz.toml](./leibniz.toml) for said example: - -```toml -# this is an example file, consult: https://toml.io/en/ for syntax help and -# src/rules.rs::Config for all available options -[disabled] - # see sqleibniz --help for all available rules - rules = [ - # by default, sqleibniz specific errors are disabled: - "NoContent", # source file is empty - "NoStatements", # source file contains no statements - "Unimplemented", # construct is not implemented yet - "BadSqleibnizInstruction", # source file contains a bad sqleibniz instruction - - # ignoring sqlite specific diagnostics: - # "UnknownKeyword", # an unknown keyword was encountered - # "UnterminatedString", # a not closed string was found - # "UnknownCharacter", # an unknown character was found - # "InvalidNumericLiteral", # an invalid numeric literal was found - # "InvalidBlob", # an invalid blob literal was found (either bad hex data or incorrect syntax) - # "Syntax", # a structure with incorrect syntax was found - # "Semicolon", # a semicolon is missing - ] - +[leibniz.lua](./leibniz.lua) for said example: + +```lua +-- this is an example configuration, consult: https://www.lua.org/manual/5.4/ +-- or https://learnxinyminutes.com/docs/lua/ for syntax help and +-- src/rules.rs::Config for all available options +leibniz.disabled_rules = { + -- by default, sqleibniz specific errors are disabled: + "NoContent", -- source file is empty + "NoStatements", -- source file contains no statements + "Unimplemented", -- construct is not implemented yet + "BadSqleibnizInstruction", -- source file contains a bad sqleibniz instruction + + -- ignoring sqlite specific diagnostics: + + -- "UnknownKeyword", -- an unknown keyword was encountered + -- "UnterminatedString", -- a not closed string was found + -- "UnknownCharacter", -- an unknown character was found + -- "InvalidNumericLiteral", -- an invalid numeric literal was found + -- "InvalidBlob", -- an invalid blob literal was found (either bad hex data or incorrect syntax) + -- "Syntax", -- a structure with incorrect syntax was found + -- "Semicolon", -- a semicolon is missing +} ``` ### sqleibniz instructions diff --git a/leibniz.lua b/leibniz.lua new file mode 100644 index 0000000..ab64f07 --- /dev/null +++ b/leibniz.lua @@ -0,0 +1,20 @@ +-- this is an example configuration, consult: https://www.lua.org/manual/5.4/ +-- or https://learnxinyminutes.com/docs/lua/ for syntax help and +-- src/rules.rs::Config for all available options +leibniz.disabled_rules = { + -- by default, sqleibniz specific errors are disabled: + "NoContent", -- source file is empty + "NoStatements", -- source file contains no statements + "Unimplemented", -- construct is not implemented yet + "BadSqleibnizInstruction", -- source file contains a bad sqleibniz instruction + + -- ignoring sqlite specific diagnostics: + + -- "UnknownKeyword", -- an unknown keyword was encountered + -- "UnterminatedString", -- a not closed string was found + -- "UnknownCharacter", -- an unknown character was found + -- "InvalidNumericLiteral", -- an invalid numeric literal was found + -- "InvalidBlob", -- an invalid blob literal was found (either bad hex data or incorrect syntax) + -- "Syntax", -- a structure with incorrect syntax was found + -- "Semicolon", -- a semicolon is missing +} diff --git a/leibniz.toml b/leibniz.toml deleted file mode 100644 index dcf382c..0000000 --- a/leibniz.toml +++ /dev/null @@ -1,20 +0,0 @@ -# this is an example file, consult: https://toml.io/en/ for syntax help and -# src/rules.rs::Config for all available options -[disabled] - # see sqleibniz --help for all available rules - rules = [ - # by default, sqleibniz specific errors are disabled: - "NoContent", # source file is empty - "NoStatements", # source file contains no statements - "Unimplemented", # construct is not implemented yet - "BadSqleibnizInstruction", # source file contains a bad sqleibniz instruction - - # ignoring sqlite specific diagnostics: - # "UnknownKeyword", # an unknown keyword was encountered - # "UnterminatedString", # a not closed string was found - # "UnknownCharacter", # an unknown character was found - # "InvalidNumericLiteral", # an invalid numeric literal was found - # "InvalidBlob", # an invalid blob literal was found (either bad hex data or incorrect syntax) - # "Syntax", # a structure with incorrect syntax was found - # "Semicolon", # a semicolon is missing - ] diff --git a/src/main.rs b/src/main.rs index b5965d3..9c07df1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,8 @@ use std::{fs, process::exit, vec}; use clap::Parser; use error::{print_str_colored, warn}; use lexer::Lexer; -use rules::{Config, Disabled, Rule}; +use mlua::{Lua, LuaSerdeExt}; +use rules::{Config, Rule}; /// error does formatting and highlighting for errors mod error; @@ -26,7 +27,7 @@ mod types; #[derive(clap::Parser)] #[command(about, long_about=None)] struct Cli { - /// instruct sqleibniz to ignore the configuration, if found + /// instruct sqleibniz to ignore the configuration, if specified #[arg(short, long)] ignore_config: bool, @@ -34,7 +35,7 @@ struct Cli { paths: Vec, /// path to the configuration - #[arg(short = 'c', long, default_value = "leibniz.toml")] + #[arg(short = 'c', long, default_value = "leibniz.lua")] config: String, /// disable stdout/stderr output @@ -64,20 +65,36 @@ fn main() { } let mut config = Config { - disabled: Disabled { rules: vec![] }, + disabled_rules: vec![], }; if !args.ignore_config { match fs::read_to_string(&args.config) { - Ok(config_str) => match toml::from_str(&config_str) { - Ok(conf) => config = conf, - Err(err) => warn(&format!( - "Failed to parse configuration file '{}': {}", - args.config, err - )), - }, + Ok(config_str) => { + let lua = Lua::new(); + let globals = lua.globals(); + let leibniz = lua + .to_value(&Config { + disabled_rules: vec![], + }) + .expect("failed to serialize default configuration"); + globals + .set("leibniz", leibniz) + .expect("failed to serialize default configuration"); + match lua.load(config_str).set_name(&args.config).exec() { + Ok(()) => { + if let Ok(raw_conf) = globals.get::("leibniz") { + match lua.from_value::(raw_conf) { + Ok(conf) => config.disabled_rules = conf.disabled_rules, + Err(err) => println!("{err}"), + } + } + } + Err(err) => println!("{err}"), + } + } Err(err) => warn(&format!( - "Failed to read configuration file '{}': {}", + "Failed to execute configuration file '{}': {}", args.config, err )), } @@ -85,12 +102,12 @@ fn main() { if let Some(rules) = args.disable { let mut p = rules.clone(); - config.disabled.rules.append(&mut p); + config.disabled_rules.append(&mut p); } - if !config.disabled.rules.is_empty() && !args.silent { + if !config.disabled_rules.is_empty() && !args.silent { warn("Ignoring the following diagnostics, as specified:"); - for rule in &config.disabled.rules { + for rule in &config.disabled_rules { print_str_colored(" -> ", error::Color::Blue); println!("{}", rule.name()) } @@ -132,7 +149,7 @@ fn main() { .iter() .flatten() .filter(|e| { - if config.disabled.rules.contains(&e.rule) { + if config.disabled_rules.contains(&e.rule) { ignored_errors += 1; false } else { diff --git a/src/rules.rs b/src/rules.rs index 6443641..342cb1d 100644 --- a/src/rules.rs +++ b/src/rules.rs @@ -1,6 +1,7 @@ -use serde::Deserialize; +use mlua::UserData; +use serde::{Deserialize, Serialize}; -#[derive(Deserialize, Debug, PartialEq, Clone)] +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] /// Rule is attached to each error and can be supplied to sqleibniz via the Config structure serialized in ./leibniz.toml #[derive(clap::ValueEnum)] pub enum Rule { @@ -30,19 +31,16 @@ pub enum Rule { Semicolon, } -#[derive(Deserialize, Debug)] -/// Allows for disabling diagnostics and turning off behaviours -pub struct Disabled { - pub rules: Vec, -} - -#[derive(Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug)] /// Configuration is expected to be at ./leibniz.toml - its existence is not necessary for the program invocation pub struct Config { /// holds the rules that the user wants to not see errors for. - pub disabled: Disabled, + pub disabled_rules: Vec, } +impl UserData for Config {} +impl UserData for Rule {} + impl Rule { pub fn name(&self) -> &str { match self {