Skip to content

Commit

Permalink
Binary to generate qlty.toml validation schema using Taplo (#1454)
Browse files Browse the repository at this point in the history
This sounds counter-intuitive, but extensions and tools like
[Taplo](https://taplo.tamasfe.dev/) ([Even Better
TOML](https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml))
support validating TOML files with JSON schemas. This PR aims to provide
the infrastructure to generate a JSON schema for use in these tools.

A schema file can be generated with

```sh
cargo run --bin qlty-config-generate-schema > schema.json
```

This PR does not generate the schema or use it anywhere yet.
  • Loading branch information
lsegal authored Jan 23, 2025
1 parent 21cb760 commit 1046f5e
Show file tree
Hide file tree
Showing 15 changed files with 958 additions and 55 deletions.
894 changes: 886 additions & 8 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ rand = "0.8.5"
rayon = "1.10.0"
regex = "1.11.0"
rust-embed = { version = "8.5.0", features = ["include-exclude"] }
schemars = "0.8.21"
semver = "1.0.25"
sentry = { version = "0.34.0", default-features = false, features = [
"backtrace",
Expand Down
6 changes: 6 additions & 0 deletions qlty-config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ categories.workspace = true
license-file.workspace = true
edition.workspace = true

[[bin]]
name = "qlty-config-generate-schema"
path = "src/bin/generate_schema.rs"

[lib]
doctest = false

Expand All @@ -30,8 +34,10 @@ lazy_static.workspace = true
md5.workspace = true
qlty-plugins.workspace = true
qlty-types.workspace = true
schemars.workspace = true
semver.workspace = true
serde_with.workspace = true
serde_json.workspace = true
serde_yaml.workspace = true
serde.workspace = true
tempfile.workspace = true
Expand Down
7 changes: 7 additions & 0 deletions qlty-config/src/bin/generate_schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use qlty_config::QltyConfig;
use schemars::schema_for;

fn main() {
let schema = schema_for!(QltyConfig);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}
3 changes: 2 additions & 1 deletion qlty-config/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,13 @@ use crate::sources::SourcesList;
use crate::version::QLTY_VERSION;
use crate::Library;
use anyhow::{bail, Result};
use schemars::JsonSchema;
use semver::Version;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use tracing::{debug, warn};

#[derive(Debug, Serialize, Deserialize, Clone, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, Default, JsonSchema)]
pub struct QltyConfig {
pub config_version: Option<String>,
pub cli_version: Option<String>,
Expand Down
3 changes: 2 additions & 1 deletion qlty-config/src/config/coverage.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, Default, JsonSchema)]
pub struct Coverage {
pub paths: Option<Vec<String>>,
pub ignores: Option<Vec<String>>,
Expand Down
11 changes: 6 additions & 5 deletions qlty-config/src/config/download.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::str::FromStr;

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum DownloadFileType {
#[default]
Expand Down Expand Up @@ -33,7 +34,7 @@ impl std::fmt::Display for DownloadFileType {
}
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default, JsonSchema)]
pub enum OperatingSystem {
#[default]
#[serde(rename = "linux")]
Expand All @@ -54,7 +55,7 @@ impl OperatingSystem {
}
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default, JsonSchema)]
pub enum Cpu {
#[default]
#[serde(rename = "x86_64")]
Expand All @@ -72,14 +73,14 @@ impl Cpu {
}
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default, JsonSchema)]
pub struct System {
pub url: String,
pub cpu: Cpu,
pub os: OperatingSystem,
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, JsonSchema)]
pub struct DownloadDef {
pub binary_name: Option<String>,

Expand Down
3 changes: 2 additions & 1 deletion qlty-config/src/config/file_type.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, Default, JsonSchema)]
pub struct FileType {
#[serde(default)]
pub globs: Vec<String>,
Expand Down
3 changes: 2 additions & 1 deletion qlty-config/src/config/ignore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ use std::sync::RwLock;
use crate::config::issue_transformer::IssueTransformer;
use globset::{Glob, GlobSet, GlobSetBuilder};
use qlty_types::analysis::v1::Issue;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

pub const ALL_WILDCARD: &'static str = "ALL";

#[derive(Debug, Serialize, Deserialize, Default)]
#[derive(Debug, Serialize, Deserialize, Default, JsonSchema)]
pub struct Ignore {
#[serde(default = "default_ignore_file_patterns")]
pub file_patterns: Vec<String>,
Expand Down
3 changes: 2 additions & 1 deletion qlty-config/src/config/language.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use super::smells::Smells;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, Default, JsonSchema)]
#[allow(unused)]
pub struct Language {
#[serde(default = "_default_true")]
Expand Down
3 changes: 2 additions & 1 deletion qlty-config/src/config/overrides.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ use crate::config::issue_transformer::IssueTransformer;
use globset::{Glob, GlobSet, GlobSetBuilder};
use qlty_types::category_from_str;
use qlty_types::{analysis::v1::Issue, level_from_str};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::sync::RwLock;

#[derive(Debug, Serialize, Deserialize, Default)]
#[derive(Debug, Serialize, Deserialize, Default, JsonSchema)]
pub struct Override {
#[serde(default)]
pub level: Option<String>,
Expand Down
49 changes: 25 additions & 24 deletions qlty-config/src/config/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::config::DownloadDef;
use crate::QltyConfig;
use anyhow::{Context, Result};
use qlty_types::analysis::v1::{Category, Level};
use schemars::JsonSchema;
use serde::{Deserialize, Deserializer, Serialize};
use std::collections::HashMap;
use std::fmt;
Expand All @@ -13,7 +14,7 @@ use std::path::PathBuf;
const SEMVER_REGEX: &str = r"(\d+\.\d+\.\d+)";
const ALL: &str = "ALL";

#[derive(Debug, Serialize, Deserialize, Clone, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, Default, JsonSchema)]
pub struct PluginsConfig {
#[serde(default)]
pub downloads: HashMap<String, DownloadDef>,
Expand All @@ -29,7 +30,7 @@ fn semver_regex() -> String {
SEMVER_REGEX.to_string()
}

#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
pub struct DriverDef {
#[serde(default)]
pub script: String,
Expand Down Expand Up @@ -123,7 +124,7 @@ fn default_max_batch() -> usize {
64
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default, JsonSchema)]
pub enum DriverBatchBy {
#[default]
#[serde(rename = "none")]
Expand All @@ -136,7 +137,7 @@ pub enum DriverBatchBy {
ConfigFile,
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default, JsonSchema)]
pub enum InvocationDirectoryType {
#[default]
#[serde(rename = "root")]
Expand All @@ -155,7 +156,7 @@ pub enum InvocationDirectoryType {
ToolDir,
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default, JsonSchema)]
pub struct InvocationDirectoryDef {
#[serde(default)]
#[serde(rename = "type")]
Expand All @@ -165,7 +166,7 @@ pub struct InvocationDirectoryDef {
pub path: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default, JsonSchema)]
pub struct TargetDef {
#[serde(default)]
#[serde(rename = "type")]
Expand All @@ -174,7 +175,7 @@ pub struct TargetDef {
pub path: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Default, JsonSchema)]
pub enum TargetType {
#[default]
#[serde(rename = "file")]
Expand All @@ -190,7 +191,7 @@ pub enum TargetType {
Parent,
}

#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, Default)]
#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, Default, JsonSchema)]
pub enum OutputLevel {
#[serde(rename = "high")]
High,
Expand All @@ -217,7 +218,7 @@ impl Into<Level> for OutputLevel {
}
}

#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, Default)]
#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, Default, JsonSchema)]
pub enum OutputCategory {
#[default]
#[serde(rename = "bug")]
Expand Down Expand Up @@ -288,7 +289,7 @@ impl Into<Category> for OutputCategory {
}
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Default)]
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Default, JsonSchema)]
pub struct PluginDef {
pub runtime: Option<Runtime>,

Expand Down Expand Up @@ -385,7 +386,7 @@ fn default_idempotent() -> bool {
true
}

#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Default)]
#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Default, JsonSchema)]
pub enum PackageFileCandidate {
#[default]
#[serde(rename = "package.json")]
Expand All @@ -403,7 +404,7 @@ impl std::fmt::Display for PackageFileCandidate {
}
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Default, Eq)]
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Default, Eq, JsonSchema)]
pub struct PluginEnvironment {
#[serde(default)]
pub name: String,
Expand All @@ -427,7 +428,7 @@ impl PartialOrd for PluginEnvironment {
}
}

#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, Default)]
#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, Default, JsonSchema)]
pub enum SuggestionMode {
#[default]
#[serde(rename = "never")]
Expand All @@ -438,7 +439,7 @@ pub enum SuggestionMode {
Targets,
}

#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, Default)]
#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, Default, JsonSchema)]
pub enum OutputDestination {
#[default]
#[serde(rename = "stdout")]
Expand All @@ -465,7 +466,7 @@ impl std::fmt::Display for OutputDestination {
}
}

#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, Default)]
#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, Default, JsonSchema)]
pub enum OutputFormat {
#[default]
#[serde(rename = "sarif")]
Expand Down Expand Up @@ -561,7 +562,7 @@ impl std::fmt::Display for OutputFormat {
}
}

#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, Default)]
#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, Default, JsonSchema)]
pub enum DriverType {
#[default]
#[serde(rename = "linter")]
Expand All @@ -572,7 +573,7 @@ pub enum DriverType {
Validator,
}

#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, Default)]
#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash, Default, JsonSchema)]
pub enum Runtime {
#[default]
#[serde(rename = "go")]
Expand Down Expand Up @@ -605,14 +606,14 @@ impl std::fmt::Display for Runtime {
}
}

#[derive(Debug, Serialize, Deserialize, Clone, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, Default, JsonSchema)]
#[allow(unused)]
pub struct EnabledRuntimes {
#[serde(default)]
pub enabled: HashMap<Runtime, String>,
}

#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq)]
#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq, JsonSchema)]
pub struct EnabledPlugin {
pub name: String,

Expand Down Expand Up @@ -653,7 +654,7 @@ pub struct EnabledPlugin {
pub prefix: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, JsonSchema)]
pub struct PluginFetch {
pub url: String,
pub path: String,
Expand Down Expand Up @@ -705,7 +706,7 @@ impl PluginFetch {
}
}

#[derive(Debug, Serialize, Deserialize, Clone, Copy, Default, PartialEq)]
#[derive(Debug, Serialize, Deserialize, Clone, Copy, Default, PartialEq, JsonSchema)]
pub enum IssueMode {
#[default]
#[serde(rename = "block")]
Expand Down Expand Up @@ -748,7 +749,7 @@ impl IssueMode {
}
}

#[derive(Debug, Serialize, Clone, Default, PartialEq)]
#[derive(Debug, Serialize, Clone, Default, PartialEq, JsonSchema)]
pub struct ExtraPackage {
pub name: String,
pub version: String,
Expand Down Expand Up @@ -777,7 +778,7 @@ fn default_plugin_drivers() -> Vec<String> {
vec![ALL.to_string()]
}

#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize)]
#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize, JsonSchema)]
pub enum CheckTrigger {
#[serde(rename = "manual")]
Manual,
Expand All @@ -789,7 +790,7 @@ pub enum CheckTrigger {
Build,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize, JsonSchema)]
pub enum Platform {
#[serde(rename = "linux")]
Linux,
Expand Down
3 changes: 2 additions & 1 deletion qlty-config/src/config/release.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use super::DownloadFileType;

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, JsonSchema)]
pub struct ReleaseDef {
pub github: String,

Expand Down
Loading

0 comments on commit 1046f5e

Please sign in to comment.