-
Notifications
You must be signed in to change notification settings - Fork 109
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce the
build
command in the CLI (#721)
* Introduce the `build` command in the CLI This commit introduces a `build` command in the CLI, which behaves exactly as the compile command and introduces a deprecation warning to the existing `compile` command. Additionally, as a preparation for the CLI redesign discussed in #702, this commit introduces a small refactoring of the code generation process, by: * Introducing a code generator builder, to abstract and validate all the code generation option combinations. * Introducing proper static and dynamic code generator modules, making it easier to divide the responsilibities of each. The main motivation for the refactoring is to: * Make it easier to finalize the CLI redesign. * Share code between the `compile` and `build` command while they must be equivalent. * Make it easier to keep the `compile` command frozen while it becomes deprecated and at the same time evolve the `build` command independently. NB: Given that the `compile` and `build` command are exactly the same, and that this change is purely mechanical; this change doesn't introduce integration tests for the `build` command. The plan is to introduce tests once other options are added to the `build` command as part of the CLI redesign. Alternatively, tests can be added, however, it would require either duplicating the entire test suite or adding testing infrastructure to minimize duplication, which will increase the size of the change. * Collapse `provider_version` call in `builder` * Improve some documentation * Clarify `source_compression` docs * Stylistic changes * Add NOTICE to help text of `compile` * Use `eprintln!` instead of `println!` * Use `build` in the README.md
- Loading branch information
1 parent
c2135a0
commit ff4be7e
Showing
12 changed files
with
749 additions
and
371 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
use crate::codegen::{CodeGen, CodeGenType, DynamicGenerator, StaticGenerator}; | ||
use anyhow::{bail, Result}; | ||
use std::path::PathBuf; | ||
|
||
/// Options for using WIT in the code generation process. | ||
#[derive(Default)] | ||
pub(crate) struct WitOptions { | ||
/// The path of the .wit file to use. | ||
pub path: Option<PathBuf>, | ||
/// The name of the wit world to use. | ||
pub world: Option<String>, | ||
} | ||
|
||
impl WitOptions { | ||
pub fn from_tuple(opts: (Option<PathBuf>, Option<String>)) -> Result<Self> { | ||
match opts { | ||
(None, None) => Ok(Self { | ||
path: None, | ||
world: None, | ||
}), | ||
(None, Some(_)) => Ok(Self { | ||
path: None, | ||
world: None, | ||
}), | ||
(Some(_), None) => bail!("Must provide WIT world when providing WIT file"), | ||
(path, world) => Ok(Self { path, world }), | ||
} | ||
} | ||
|
||
/// Whether WIT options were defined. | ||
pub fn defined(&self) -> bool { | ||
self.path.is_some() && self.world.is_some() | ||
} | ||
|
||
/// Unwraps a refernce to the .wit file path. | ||
pub fn unwrap_path(&self) -> &PathBuf { | ||
self.path.as_ref().unwrap() | ||
} | ||
|
||
/// Unwraps a reference to the WIT world name. | ||
pub fn unwrap_world(&self) -> &String { | ||
self.world.as_ref().unwrap() | ||
} | ||
} | ||
|
||
/// A code generation builder. | ||
#[derive(Default)] | ||
pub(crate) struct CodeGenBuilder { | ||
/// The QuickJS provider module version. | ||
provider_version: Option<&'static str>, | ||
/// WIT options for code generation. | ||
wit_opts: WitOptions, | ||
/// Whether to compress the original JS source. | ||
source_compression: bool, | ||
} | ||
|
||
impl CodeGenBuilder { | ||
/// Create a new [`CodeGenBuilder`]. | ||
pub fn new() -> Self { | ||
Self::default() | ||
} | ||
|
||
/// Set the provider version. | ||
pub fn provider_version(&mut self, v: &'static str) -> &mut Self { | ||
self.provider_version = Some(v); | ||
self | ||
} | ||
|
||
/// Set the wit options. | ||
pub fn wit_opts(&mut self, opts: WitOptions) -> &mut Self { | ||
self.wit_opts = opts; | ||
self | ||
} | ||
|
||
/// Whether to compress the JS source. | ||
pub fn source_compression(&mut self, compress: bool) -> &mut Self { | ||
self.source_compression = compress; | ||
self | ||
} | ||
|
||
/// Build a [`CodeGenerator`]. | ||
pub fn build<T>(self) -> Result<Box<dyn CodeGen>> | ||
where | ||
T: CodeGen, | ||
{ | ||
match T::classify() { | ||
CodeGenType::Static => self.build_static(), | ||
CodeGenType::Dynamic => self.build_dynamic(), | ||
} | ||
} | ||
|
||
fn build_static(self) -> Result<Box<dyn CodeGen>> { | ||
let mut static_gen = Box::new(StaticGenerator::new()); | ||
|
||
static_gen.source_compression = self.source_compression; | ||
static_gen.wit_opts = self.wit_opts; | ||
|
||
Ok(static_gen) | ||
} | ||
|
||
fn build_dynamic(self) -> Result<Box<dyn CodeGen>> { | ||
let mut dynamic_gen = Box::new(DynamicGenerator::new()); | ||
|
||
if let Some(v) = self.provider_version { | ||
dynamic_gen.import_namespace = String::from("javy_quickjs_provider_v"); | ||
dynamic_gen.import_namespace.push_str(v); | ||
} else { | ||
bail!("Provider version not specified") | ||
} | ||
|
||
dynamic_gen.wit_opts = self.wit_opts; | ||
|
||
Ok(dynamic_gen) | ||
} | ||
} |
Oops, something went wrong.