Validate project name on aiken new

This commit is contained in:
vh-zuka 2022-11-13 22:46:01 +07:00 committed by Lucas
parent 2cac7963c3
commit 2736df5466
5 changed files with 86 additions and 9 deletions

20
Cargo.lock generated
View File

@ -64,6 +64,8 @@ dependencies = [
"pallas-crypto",
"pallas-primitives",
"pallas-traverse",
"regex",
"thiserror",
"uplc",
]
@ -233,9 +235,9 @@ dependencies = [
[[package]]
name = "clap"
version = "3.2.22"
version = "3.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750"
checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5"
dependencies = [
"atty",
"bitflags",
@ -245,7 +247,7 @@ dependencies = [
"once_cell",
"strsim",
"termcolor",
"textwrap",
"textwrap 0.16.0",
]
[[package]]
@ -591,7 +593,7 @@ dependencies = [
"supports-hyperlinks",
"supports-unicode",
"terminal_size",
"textwrap",
"textwrap 0.15.0",
"thiserror",
"unicode-width",
]
@ -1214,15 +1216,21 @@ dependencies = [
[[package]]
name = "textwrap"
version = "0.15.1"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16"
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
dependencies = [
"smawk",
"unicode-linebreak",
"unicode-width",
]
[[package]]
name = "textwrap"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
[[package]]
name = "thiserror"
version = "1.0.37"

View File

@ -20,6 +20,8 @@ pallas-codec = "0.14.0"
pallas-crypto = "0.14.0"
pallas-primitives = "0.14.0"
pallas-traverse = "0.14.0"
regex = "1.5.4"
thiserror = "1.0.31"
aiken-lang = { path = "../lang", version = "0.0.24" }
aiken-lsp = { path = "../lsp", version = "0.0.0" }

View File

@ -0,0 +1,36 @@
use std::fmt;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("{} is not a valid project name. {}", name, reason.to_string())]
InvalidProjectName {
name: String,
reason: InvalidProjectNameReason,
},
}
#[derive(Debug, Clone, Copy)]
pub enum InvalidProjectNameReason {
AikenPrefix,
AikenReservedModule,
Format,
}
impl fmt::Display for InvalidProjectNameReason {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
InvalidProjectNameReason::AikenPrefix => write!(f, "It is a reserved word in Aiken."),
InvalidProjectNameReason::AikenReservedModule => {
write!(f, "It is a reserved module name in Aiken.")
}
InvalidProjectNameReason::Format => write!(
f,
"It does not have the correct format. Project names \
must start with a lowercase letter and may only contain lowercase letters, \
numbers and underscores."
),
}
}
}

View File

@ -1,5 +1,6 @@
pub mod build;
pub mod check;
pub mod error;
pub mod fmt;
pub mod lsp;
pub mod new;

View File

@ -4,6 +4,8 @@ use std::fs;
use std::io::Write;
use std::path::PathBuf;
use super::error::{Error, InvalidProjectNameReason};
#[derive(clap::Args)]
/// Create a new Aiken project
pub struct Args {
@ -20,11 +22,11 @@ pub struct Creator {
}
impl Creator {
fn new(args: Args) -> Self {
fn new(args: Args, project_name: String) -> Self {
let root = args.name;
let src = root.join("src");
let scripts = src.join("scripts");
let project_name = root.clone().into_os_string().into_string().unwrap();
let project_name = project_name;
let project = src.join(&project_name);
Self {
root,
@ -111,9 +113,37 @@ fn write(path: PathBuf, contents: &str) -> miette::Result<()> {
Ok(())
}
fn validate_name(name: &str) -> Result<(), Error> {
if name.starts_with("aiken_") {
Err(Error::InvalidProjectName {
name: name.to_string(),
reason: InvalidProjectNameReason::AikenPrefix,
})
} else if name == "aiken" {
Err(Error::InvalidProjectName {
name: name.to_string(),
reason: InvalidProjectNameReason::AikenReservedModule,
})
} else if !regex::Regex::new("^[a-z][a-z0-9_]*$")
.expect("new name regex could not be compiled")
.is_match(name)
{
Err(Error::InvalidProjectName {
name: name.to_string(),
reason: InvalidProjectNameReason::Format,
})
} else {
Ok(())
}
}
pub fn exec(args: Args) -> miette::Result<()> {
if !args.name.exists() {
let creator = Creator::new(args);
let project_name = args.name.clone().into_os_string().into_string().unwrap();
validate_name(&project_name).into_diagnostic()?;
let creator = Creator::new(args, project_name);
creator.run()?;
}