diff --git a/src/cli/commands/publish.rs b/src/cli/commands/publish.rs index eaaeed7..cdb2c4c 100644 --- a/src/cli/commands/publish.rs +++ b/src/cli/commands/publish.rs @@ -48,9 +48,34 @@ pub struct PublishCommand { /// The index to publish to #[arg(short, long, default_value_t = DEFAULT_INDEX_NAME.to_string())] index: String, + + /// Whether to skip syntax validation + #[arg(long)] + no_verify: bool, } impl PublishCommand { + fn validate_luau_file(&self, name: &str, contents: &str) -> anyhow::Result<()> { + if self.no_verify { + return Ok(()); + } + + if let Err(err) = full_moon::parse(contents) { + eprintln!( + "{}: {name} is not a valid Luau file:\n{}", + "error".red().bold(), + err.into_iter() + .map(|err| format!("\t- {err}")) + .collect::>() + .join("\n") + ); + + anyhow::bail!("failed to validate Luau file"); + } + + Ok(()) + } + async fn run_impl( self, project: &Project, @@ -226,14 +251,7 @@ info: otherwise, the file was deemed unnecessary, if you don't understand why, p .canonicalize() .with_context(|| format!("failed to canonicalize {name}"))?; - if let Err(err) = full_moon::parse(&contents).map_err(|errs| { - errs.into_iter() - .map(|err| err.to_string()) - .collect::>() - .join(", ") - }) { - anyhow::bail!("{name} is not a valid Luau file: {err}"); - } + self.validate_luau_file(&format!("file at {name}"), &contents)?; let first_part = relative_export_path .components() @@ -318,14 +336,7 @@ info: otherwise, the file was deemed unnecessary, if you don't understand why, p .canonicalize() .with_context(|| format!("failed to canonicalize script {name}"))?; - if let Err(err) = full_moon::parse(&contents).map_err(|errs| { - errs.into_iter() - .map(|err| err.to_string()) - .collect::>() - .join(", ") - }) { - anyhow::bail!("script {name} is not a valid Luau file: {err}"); - } + self.validate_luau_file(&format!("the `{name}` script"), &contents)?; if paths.insert( script_path diff --git a/src/linking/generator.rs b/src/linking/generator.rs index d8746db..ab54162 100644 --- a/src/linking/generator.rs +++ b/src/linking/generator.rs @@ -41,13 +41,25 @@ impl Visitor for TypeVisitor { } } -/// Get the types exported by a file -pub fn get_file_types(file: &str) -> Result, Vec> { - let ast = full_moon::parse(file)?; +pub(crate) fn get_file_types(file: &str) -> Vec { + let ast = match full_moon::parse(file) { + Ok(ast) => ast, + Err(err) => { + tracing::error!( + "failed to parse file to extract types:\n{}", + err.into_iter() + .map(|err| format!("\t- {err}")) + .collect::>() + .join("\n") + ); + + return vec![]; + } + }; let mut visitor = TypeVisitor { types: vec![] }; visitor.visit_ast(&ast); - Ok(visitor.types) + visitor.types } /// Generate a linking module for a library diff --git a/src/linking/mod.rs b/src/linking/mod.rs index 2f3bc00..7cc47cb 100644 --- a/src/linking/mod.rs +++ b/src/linking/mod.rs @@ -99,18 +99,9 @@ impl Project { Err(e) => return Err(e.into()), }; - let types = match spawn_blocking(move || get_file_types(&contents)) + let types = spawn_blocking(move || get_file_types(&contents)) .await - .unwrap() - { - Ok(types) => types, - Err(e) => { - return Err(errors::LinkingError::FullMoon( - lib_file.display().to_string(), - e, - )) - } - }; + .unwrap(); tracing::debug!("contains {} exported types", types.len()); @@ -145,7 +136,7 @@ impl Project { } Ok((version_id, types)) - }.instrument(tracing::debug_span!("extract types", name = name.to_string(), version_id = version_id.to_string())))) + }.instrument(tracing::info_span!("extract types", name = name.to_string(), version_id = version_id.to_string())))) .await? .into_iter() .collect::>(), @@ -384,10 +375,6 @@ pub mod errors { #[error("library file at {0} not found")] LibFileNotFound(String), - /// An error occurred while parsing a Luau script - #[error("error parsing Luau script at {0}")] - FullMoon(String, Vec), - /// An error occurred while generating a Roblox sync config #[error("error generating roblox sync config for {0}")] GenerateRobloxSyncConfig(String, #[source] std::io::Error),