Skip to content

Commit

Permalink
replace panics with JS exceptions in npm package (#489)
Browse files Browse the repository at this point in the history
Closes #464
  • Loading branch information
OmarTawfik authored Jun 1, 2023
1 parent ba5ea9a commit 15c34a7
Show file tree
Hide file tree
Showing 28 changed files with 223 additions and 153 deletions.
5 changes: 5 additions & 0 deletions .changeset/fifty-students-applaud.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"changelog": minor
---

replace panics with JS exceptions in npm package
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 8 additions & 11 deletions crates/codegen/syntax/src/rust_lib_code_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,18 @@ impl CodeGenerator {
"
{language_boilerplate_common}
#[derive(Debug)]
pub struct Language {{
pub(crate) version: Version,
{version_flag_declarations}
}}
#[derive(thiserror::Error, Debug)]
pub enum Error {{
#[error(\"Invalid {language_title} language version '{{0}}'.\")]
InvalidLanguageVersion(Version),
#[error(\"Unsupported {language_title} language version '{{0}}'.\")]
UnsupportedLanguageVersion(Version),
#[error(\"Production '{{0:?}}' is not valid in this version of {language_title}.\")]
InvalidProductionVersion(ProductionKind),
}}
impl Language {{
Expand All @@ -75,27 +78,21 @@ impl CodeGenerator {
version,
}})
}} else {{
Err(Error::InvalidLanguageVersion(version))
Err(Error::UnsupportedLanguageVersion(version))
}}
}}
pub fn version(&self) -> &Version {{
&self.version
}}
pub fn parse(&self, production_kind: ProductionKind, input: &str) -> ParseOutput {{
pub fn parse(&self, production_kind: ProductionKind, input: &str) -> Result<ParseOutput, Error> {{
let output = match production_kind {{
{scanner_invocations},
{parser_invocations},
}};
output.unwrap_or_else(|| {{
let message = format!(\"ProductionKind {{production_kind}} is not valid in this version of {language_title}\");
ParseOutput {{
parse_tree: None,
errors: vec![ParseError::new(Default::default(), message)]
}}
}})
output.ok_or_else(|| Error::InvalidProductionVersion(production_kind))
}}
}}
",
Expand Down
33 changes: 26 additions & 7 deletions crates/codegen/syntax/src/typescript_lib_code_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,38 @@ impl CodeGenerator {
{version_flag_declarations}
}}
#[derive(thiserror::Error, Debug)]
pub enum Error {{
// Shared with Rust
#[error(\"Unsupported {language_title} language version '{{0}}'.\")]
UnsupportedLanguageVersion(Version),
#[error(\"Production '{{0:?}}' is not valid in this version of {language_title}.\")]
InvalidProductionVersion(ProductionKind),
// TypeScript-specific
#[error(\"Invalid semantic version '{{0}}'.\")]
InvalidSemanticVersion(String),
}}
impl From<Error> for napi::Error {{
fn from(value: Error) -> Self {{
napi::Error::from_reason(value.to_string())
}}
}}
#[napi]
impl Language {{
#[napi(constructor)]
pub fn new(version: String) -> Self {{
pub fn new(version: String) -> Result<Self, napi::Error> {{
{versions_array}
let version = Version::parse(&version).unwrap();
let version = Version::parse(&version).map_err(|_| Error::InvalidSemanticVersion(version))?;
if VERSIONS.contains(&version.to_string().as_str()) {{
Self {{
Ok(Self {{
{version_flag_initializers},
version,
}}
}})
}} else {{
panic!(\"Invalid {language_title} language version: {{version}}\");
Err(Error::UnsupportedLanguageVersion(version).into())
}}
}}
Expand All @@ -83,12 +102,12 @@ impl CodeGenerator {
}}
#[napi]
pub fn parse(&self, production_kind: ProductionKind, input: String) -> ParseOutput {{
pub fn parse(&self, production_kind: ProductionKind, input: String) -> Result<ParseOutput, napi::Error> {{
let input = input.as_str();
match production_kind {{
{scanner_invocations},
{parser_invocations},
}}.expect(&format!(\"Production {{production_kind:?}} is not valid in this version of {language_title}\"))
}}.ok_or_else(|| Error::InvalidProductionVersion(production_kind).into())
}}
}}
",
Expand Down
4 changes: 2 additions & 2 deletions crates/codegen/syntax_templates/src/rust/parser_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use super::{
language::{render_error_report, TextPosition},
};

#[derive(PartialEq)]
#[derive(Debug, PartialEq)]
pub struct ParseOutput {
pub(crate) parse_tree: Option<Rc<cst::Node>>,
pub(crate) errors: Vec<ParseError>,
Expand All @@ -25,7 +25,7 @@ impl ParseOutput {
}
}

#[derive(PartialEq)]
#[derive(Debug, PartialEq)]
pub struct ParseError {
pub(crate) position: TextPosition,
pub(crate) expected: BTreeSet<String>,
Expand Down
25 changes: 12 additions & 13 deletions crates/solidity/outputs/cargo/crate/src/generated/language.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion crates/solidity/outputs/cargo/crate/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ mod public_api {
* __SLANG_PUBLIC_API_SYNC__ (please keep in sync across all other instances)
*/

pub use crate::generated::language::Language;
pub mod language {
pub use crate::generated::language::{Error, Language};
}

pub mod syntax {
pub mod nodes {
Expand Down
24 changes: 10 additions & 14 deletions crates/solidity/outputs/cargo/crate/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use std::{fs, path::PathBuf};

use anyhow::Result;
use anyhow::{Context, Result};
use clap::{Parser as ClapParser, Subcommand};
use semver::Version;
use slang_solidity::{syntax::parser::ProductionKind, Language};
use slang_solidity::{language::Language, syntax::parser::ProductionKind};

mod _supress_library_dependencies_ {
// Below are dependencies used by the library `lib.rs`, but not here.
Expand Down Expand Up @@ -54,23 +54,19 @@ fn main() -> Result<()> {
};
}

fn execute_parse_command(file_path: String, version: Version, json: bool) -> Result<()> {
let input_file = &PathBuf::from(file_path).canonicalize()?;
let input = fs::read_to_string(input_file)?;
fn execute_parse_command(file_path_string: String, version: Version, json: bool) -> Result<()> {
let file_path = PathBuf::from(&file_path_string)
.canonicalize()
.with_context(|| format!("Failed to find file path: {file_path_string:?}"))?;

let input = fs::read_to_string(file_path)?;
let language = Language::new(version)?;
let output = language.parse(ProductionKind::SourceUnit, &input);
let output = language.parse(ProductionKind::SourceUnit, &input)?;

let errors = output.errors();
for error in errors {
eprintln!(
"{report}",
report = error.to_error_report(
input_file.to_str().unwrap(),
&input,
/* with_colour */ true,
)
);
let report = error.to_error_report(&file_path_string, &input, /* with_colour */ true);
eprintln!("{report}");
}

if json {
Expand Down
13 changes: 11 additions & 2 deletions crates/solidity/outputs/cargo/tests/src/cst_output/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use anyhow::Result;
use codegen_utils::context::CodegenContext;
use semver::Version;
use slang_solidity::{
language::{Error, Language},
syntax::parser::{ParseOutput, ProductionKind},
Language,
};
use solidity_testing_utils::cst_snapshots::ParseOutputTestSnapshotExtensions;

Expand Down Expand Up @@ -35,7 +35,16 @@ pub fn run(parser_name: &str, test_name: &str) -> Result<()> {

let production_kind = ProductionKind::from_str(parser_name)
.expect(format!("No such parser: {parser_name}").as_str());
let output = Language::new(version)?.parse(production_kind, &source);

let output = match Language::new(version)?.parse(production_kind, &source) {
Ok(output) => output,
Err(error) => match error {
Error::InvalidProductionVersion(_) => {
continue; // Skip versions that this production is not defined in.
}
_ => panic!("Unexpected error: {:?}", error),
},
};

if let Some(last_output) = &last_output {
if &output == last_output {
Expand Down
27 changes: 27 additions & 0 deletions crates/solidity/outputs/cargo/tests/src/errors/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use semver::Version;
use slang_solidity::{language::Language, syntax::parser::ProductionKind};

#[test]
fn unsupported_language_version() {
let version = Version::parse("0.0.0").unwrap();
let error = Language::new(version).unwrap_err();

assert_eq!(
error.to_string(),
"Unsupported Solidity language version '0.0.0'."
);
}

#[test]
fn invalid_production_version() {
let version = Version::parse("0.4.11").unwrap();
let language = Language::new(version).unwrap();
let error = language
.parse(ProductionKind::ConstructorDefinition, "")
.unwrap_err();

assert_eq!(
error.to_string(),
"Production 'ConstructorDefinition' is not valid in this version of Solidity."
);
}
2 changes: 2 additions & 0 deletions crates/solidity/outputs/cargo/tests/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
#[cfg(test)]
mod cst_output;
#[cfg(test)]
mod errors;
1 change: 1 addition & 0 deletions crates/solidity/outputs/npm/crate/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ napi = { workspace = true }
napi-derive = { workspace = true }
semver = { workspace = true }
serde = { workspace = true }
thiserror = { workspace = true }
Loading

0 comments on commit 15c34a7

Please sign in to comment.