use std::path::PathBuf;
use crate::PackagingError;
#[derive(thiserror::Error, Debug)]
pub enum CodegenError {
#[error(transparent)]
Config(#[from] PackagingError),
#[error("gleam.toml package name `{name}` cannot name the generated module: {reason}")]
ProjectName {
name: String,
reason: String,
},
#[error(
"invalid workflow.toml: {field}: schema {path} is outside the schemas/ directory; \
`aion codegen` only generates from schemas/*.json"
)]
SchemaOutsideSchemasDir {
field: String,
path: PathBuf,
},
#[error("schemas directory {path} does not exist")]
SchemasDirMissing {
path: PathBuf,
},
#[error("no *.json schema files found in {path}")]
SchemasDirEmpty {
path: PathBuf,
},
#[error("failed to list schemas directory {path}: {source}")]
SchemasDirRead {
path: PathBuf,
source: std::io::Error,
},
#[error("failed to read schema {path}: {source}")]
SchemaRead {
path: PathBuf,
source: std::io::Error,
},
#[error("schema {path} is not valid JSON: {source}")]
SchemaParse {
path: PathBuf,
source: serde_json::Error,
},
#[error("schema file name {path} cannot name a Gleam type: {reason}")]
SchemaFileName {
path: PathBuf,
reason: String,
},
#[error("unsupported JSON Schema construct in {file} at `{pointer}`: {construct}")]
UnsupportedConstruct {
file: PathBuf,
pointer: String,
construct: String,
},
#[error(
"generated Gleam name `{name}` collides: derived from {first_file} at \
`{first_pointer}` and from {second_file} at `{second_pointer}`; \
rename one of the schema properties or files"
)]
NameCollision {
name: String,
first_file: PathBuf,
first_pointer: String,
second_file: PathBuf,
second_pointer: String,
},
#[error("failed to write generated module {path}: {source}")]
Write {
path: PathBuf,
source: std::io::Error,
},
#[error("--check failed: generated module {path} does not exist; run `aion codegen`")]
CheckMissing {
path: PathBuf,
},
#[error(
"--check failed: {path} differs from the schema-generated output; \
run `aion codegen` to regenerate it"
)]
CheckDrift {
path: PathBuf,
},
#[error("failed to read {path} for --check: {source}")]
CheckRead {
path: PathBuf,
source: std::io::Error,
},
}
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use super::CodegenError;
fn assert_send_sync<T: Send + Sync + 'static>() {}
#[test]
fn codegen_error_is_send_sync_and_static() {
assert_send_sync::<CodegenError>();
}
#[test]
fn display_messages_name_file_and_pointer() {
assert_eq!(
CodegenError::UnsupportedConstruct {
file: PathBuf::from("schemas/input.json"),
pointer: "/properties/tag/oneOf".to_owned(),
construct: "unrecognised keyword `oneOf`".to_owned(),
}
.to_string(),
"unsupported JSON Schema construct in schemas/input.json at \
`/properties/tag/oneOf`: unrecognised keyword `oneOf`"
);
assert_eq!(
CodegenError::CheckDrift {
path: PathBuf::from("src/demo_io.gleam"),
}
.to_string(),
"--check failed: src/demo_io.gleam differs from the schema-generated \
output; run `aion codegen` to regenerate it"
);
assert_eq!(
CodegenError::CheckMissing {
path: PathBuf::from("src/demo_io.gleam"),
}
.to_string(),
"--check failed: generated module src/demo_io.gleam does not exist; \
run `aion codegen`"
);
assert_eq!(
CodegenError::SchemaOutsideSchemasDir {
field: "workflow[0].input_schema".to_owned(),
path: PathBuf::from("/project/io/input.json"),
}
.to_string(),
"invalid workflow.toml: workflow[0].input_schema: schema \
/project/io/input.json is outside the schemas/ directory; \
`aion codegen` only generates from schemas/*.json"
);
}
#[test]
fn packaging_errors_convert_transparently() {
let error = CodegenError::from(crate::PackagingError::ConfigMissing {
root: PathBuf::from("/project"),
});
assert_eq!(error.to_string(), "no workflow.toml found in /project");
assert!(matches!(error, CodegenError::Config(_)));
}
}