cli: Improve Anchor workspace name validation (#1949)

This commit is contained in:
Tom Linton 2022-06-07 12:21:10 +12:00 committed by GitHub
parent 37c5ff4c6d
commit c14668d6ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 73 additions and 17 deletions

View File

@ -508,24 +508,15 @@ fn init(cfg_override: &ConfigOverride, name: String, javascript: bool, no_git: b
return Err(anyhow!("Workspace already initialized"));
}
// The list is taken from https://doc.rust-lang.org/reference/keywords.html.
let key_words = [
"as", "break", "const", "continue", "crate", "else", "enum", "extern", "false", "fn",
"for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", "ref",
"return", "self", "Self", "static", "struct", "super", "trait", "true", "type", "unsafe",
"use", "where", "while", "async", "await", "dyn", "abstract", "become", "box", "do",
"final", "macro", "override", "priv", "typeof", "unsized", "virtual", "yield", "try",
"unique",
];
if key_words.contains(&name[..].into()) {
// Additional keywords that have not been added to the `syn` crate as reserved words
// https://github.com/dtolnay/syn/pull/1098
let extra_keywords = ["async", "await", "try"];
// Anchor converts to snake case before writing the program name
if syn::parse_str::<syn::Ident>(&name.to_snake_case()).is_err()
|| extra_keywords.contains(&name.to_snake_case().as_str())
{
return Err(anyhow!(
"{} is a reserved word in rust, name your project something else!",
name
));
} else if name.chars().next().unwrap().is_numeric() {
return Err(anyhow!(
"Cannot start project name with numbers, name your project something else!"
"Anchor workspace name must be a valid Rust identifier. It may not be a Rust reserved word, start with a digit, or include certain disallowed characters. See https://doc.rust-lang.org/reference/identifiers.html for more detail.",
));
}
@ -3175,3 +3166,68 @@ fn get_node_dns_option() -> Result<&'static str> {
};
Ok(option)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic(expected = "Anchor workspace name must be a valid Rust identifier.")]
fn test_init_reserved_word() {
init(
&ConfigOverride {
cluster: None,
wallet: None,
},
"await".to_string(),
true,
false,
)
.unwrap();
}
#[test]
#[should_panic(expected = "Anchor workspace name must be a valid Rust identifier.")]
fn test_init_reserved_word_from_syn() {
init(
&ConfigOverride {
cluster: None,
wallet: None,
},
"fn".to_string(),
true,
false,
)
.unwrap();
}
#[test]
#[should_panic(expected = "Anchor workspace name must be a valid Rust identifier.")]
fn test_init_invalid_ident_chars() {
init(
&ConfigOverride {
cluster: None,
wallet: None,
},
"project.name".to_string(),
true,
false,
)
.unwrap();
}
#[test]
#[should_panic(expected = "Anchor workspace name must be a valid Rust identifier.")]
fn test_init_starting_with_digit() {
init(
&ConfigOverride {
cluster: None,
wallet: None,
},
"1project".to_string(),
true,
false,
)
.unwrap();
}
}