Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

.vscode

bench_content/**/
bench_content/**/
15 changes: 6 additions & 9 deletions src/frontend/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ use serde::{Deserialize, Serialize};
use crate::{
generator::{DenseLuaGenerator, LuaGenerator, ReadableLuaGenerator, TokenBasedLuaGenerator},
nodes::Block,
rules::{
bundle::{BundleRequireMode, Bundler},
get_default_rules, Rule,
},
rules::{bundle::Bundler, get_default_rules, RequireMode, Rule},
utils::{deserialize_one_or_many, FilterPattern},
DarkluaError, Parser,
};
Expand Down Expand Up @@ -311,8 +308,8 @@ impl FromStr for GeneratorParameters {
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields, rename_all = "snake_case")]
pub struct BundleConfiguration {
#[serde(deserialize_with = "crate::utils::string_or_struct")]
require_mode: BundleRequireMode,
#[serde(deserialize_with = "crate::utils::string_or_default")]
require_mode: RequireMode,
#[serde(skip_serializing_if = "Option::is_none")]
modules_identifier: Option<String>,
#[serde(default, skip_serializing_if = "HashSet::is_empty")]
Expand All @@ -321,7 +318,7 @@ pub struct BundleConfiguration {

impl BundleConfiguration {
/// Creates a new bundle configuration with the specified require mode.
pub fn new(require_mode: impl Into<BundleRequireMode>) -> Self {
pub fn new(require_mode: impl Into<RequireMode>) -> Self {
Self {
require_mode: require_mode.into(),
modules_identifier: None,
Expand All @@ -341,7 +338,7 @@ impl BundleConfiguration {
self
}

pub(crate) fn require_mode(&self) -> &BundleRequireMode {
pub(crate) fn require_mode(&self) -> &RequireMode {
&self.require_mode
}

Expand Down Expand Up @@ -557,7 +554,7 @@ mod test {

insta::assert_snapshot!(
result.expect_err("deserialization should fail").to_string(),
@"invalid require mode `oops` at line 1 column 26"
@"invalid require mode name `oops` at line 1 column 26"
);
}
}
Expand Down
16 changes: 8 additions & 8 deletions src/rules/bundle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use wax::Program;

use crate::nodes::Block;
use crate::rules::{
Context, Rule, RuleConfiguration, RuleConfigurationError, RuleMetadata, RuleProcessResult,
RuleProperties,
Context, RequireMode, Rule, RuleConfiguration, RuleConfigurationError, RuleMetadata,
RuleProcessResult, RuleProperties,
};
use crate::Parser;

Expand All @@ -19,7 +19,7 @@ pub use require_mode::BundleRequireMode;
pub const BUNDLER_RULE_NAME: &str = "bundler";

#[derive(Debug)]
pub(crate) struct BundleOptions {
pub struct BundleOptions {
parser: Parser,
modules_identifier: String,
excludes: Option<wax::Any<'static>>,
Expand Down Expand Up @@ -77,14 +77,14 @@ impl BundleOptions {
#[derive(Debug)]
pub(crate) struct Bundler {
metadata: RuleMetadata,
require_mode: BundleRequireMode,
require_mode: RequireMode,
options: BundleOptions,
}

impl Bundler {
pub(crate) fn new<'a>(
parser: Parser,
require_mode: BundleRequireMode,
require_mode: RequireMode,
excludes: impl Iterator<Item = &'a str>,
) -> Self {
Self {
Expand Down Expand Up @@ -136,19 +136,19 @@ const DEFAULT_MODULE_IDENTIFIER: &str = "__DARKLUA_BUNDLE_MODULES";
#[cfg(test)]
mod test {
use super::*;
use crate::rules::{require::PathRequireMode, Rule};
use crate::rules::{require::PathRequireMode, RequireMode, Rule};

use insta::assert_json_snapshot;

fn new_rule() -> Bundler {
Bundler::new(
Parser::default(),
BundleRequireMode::default(),
RequireMode::default(),
std::iter::empty(),
)
}

fn new_rule_with_require_mode(mode: impl Into<BundleRequireMode>) -> Bundler {
fn new_rule_with_require_mode(mode: impl Into<RequireMode>) -> Bundler {
Bundler::new(Parser::default(), mode.into(), std::iter::empty())
}

Expand Down
16 changes: 9 additions & 7 deletions src/rules/bundle/path_require_mode/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::nodes::{
use crate::process::{
to_expression, DefaultVisitor, IdentifierTracker, NodeProcessor, NodeVisitor, ScopeVisitor,
};
use crate::rules::require::{is_require_call, match_path_require_call, PathLocator};
use crate::rules::require::{is_require_call, PathLocator, SingularPathLocator};
use crate::rules::{
Context, ContextBuilder, FlawlessRule, ReplaceReferencedTokens, RuleProcessResult,
};
Expand Down Expand Up @@ -81,16 +81,20 @@ impl<'a, 'b, 'resources, PathLocatorImpl: PathLocator>
}
}

fn require_call(&self, call: &FunctionCall) -> Option<PathBuf> {
fn require_call(
&self,
call: &FunctionCall,
source: &Path,
) -> Option<(PathBuf, SingularPathLocator<'_, '_, '_>)> {
if is_require_call(call, self) {
match_path_require_call(call)
self.path_locator.match_path_require_call(call, source)
} else {
None
}
}

fn try_inline_call(&mut self, call: &FunctionCall) -> Option<Expression> {
let literal_require_path = self.require_call(call)?;
let (literal_require_path, path_locator) = self.require_call(call, &self.source)?;

if self.options.is_excluded(&literal_require_path) {
log::info!(
Expand All @@ -101,9 +105,7 @@ impl<'a, 'b, 'resources, PathLocatorImpl: PathLocator>
return None;
}

let require_path = match self
.path_locator
.find_require_path(&literal_require_path, &self.source)
let require_path = match path_locator.find_require_path(&literal_require_path, &self.source)
{
Ok(path) => path,
Err(err) => {
Expand Down
146 changes: 98 additions & 48 deletions src/rules/bundle/require_mode.rs
Original file line number Diff line number Diff line change
@@ -1,79 +1,129 @@
use std::str::FromStr;

use serde::{Deserialize, Serialize};

use crate::rules::{
require::{LuauPathLocator, LuauRequireMode, PathRequireMode, RequirePathLocator},
RuleProcessResult,
require::{
HybridPathLocator, LuauPathLocator, LuauRequireMode, PathRequireMode, RequirePathLocator,
RobloxPathLocator,
},
RequireMode, RequireModeLike, RobloxRequireMode, RuleProcessResult, SingularRequireMode,
};
use crate::{nodes::Block, rules::Context};

use super::{path_require_mode, BundleOptions};

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields, rename_all = "snake_case", tag = "name")]
pub enum BundleRequireMode {
Path(PathRequireMode),
Luau(LuauRequireMode),
pub trait BundleRequireMode {
fn process_block(
&self,
block: &mut Block,
context: &Context,
options: &BundleOptions,
) -> RuleProcessResult;
}

impl From<PathRequireMode> for BundleRequireMode {
fn from(mode: PathRequireMode) -> Self {
Self::Path(mode)
impl BundleRequireMode for PathRequireMode {
fn process_block(
&self,
block: &mut Block,
context: &Context,
options: &BundleOptions,
) -> RuleProcessResult {
let mut require_mode = self.clone();
require_mode
.initialize(context)
.map_err(|err| err.to_string())?;

let locator = RequirePathLocator::new(
&require_mode,
context.project_location(),
context.resources(),
);

path_require_mode::process_block(block, context, options, locator)
}
}

impl FromStr for BundleRequireMode {
type Err = String;
impl BundleRequireMode for LuauRequireMode {
fn process_block(
&self,
block: &mut Block,
context: &Context,
options: &BundleOptions,
) -> RuleProcessResult {
let mut require_mode = self.clone();
require_mode
.initialize(context)
.map_err(|err| err.to_string())?;

let locator = LuauPathLocator::new(
&require_mode,
context.project_location(),
context.resources(),
);

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"path" => Self::Path(Default::default()),
"luau" => Self::Luau(Default::default()),
_ => return Err(format!("invalid require mode `{}`", s)),
})
path_require_mode::process_block(block, context, options, locator)
}
}

impl Default for BundleRequireMode {
fn default() -> Self {
Self::Path(Default::default())
impl BundleRequireMode for RobloxRequireMode {
fn process_block(
&self,
block: &mut Block,
context: &Context,
options: &BundleOptions,
) -> RuleProcessResult {
let mut require_mode = self.clone();
require_mode
.initialize(context)
.map_err(|err| err.to_string())?;

let locator = RobloxPathLocator::new(
&require_mode,
context.project_location(),
context.resources(),
);

path_require_mode::process_block(block, context, options, locator)
}
}

impl BundleRequireMode {
pub(crate) fn process_block(
impl BundleRequireMode for SingularRequireMode {
fn process_block(
&self,
block: &mut Block,
context: &Context,
options: &BundleOptions,
) -> RuleProcessResult {
match self {
Self::Path(path_require_mode) => {
let mut require_mode = path_require_mode.clone();
require_mode
.initialize(context)
.map_err(|err| err.to_string())?;

let locator = RequirePathLocator::new(
&require_mode,
context.project_location(),
context.resources(),
);

path_require_mode::process_block(block, context, options, locator)
path_require_mode.process_block(block, context, options)
}
Self::Luau(luau_require_mode) => {
let mut require_mode = luau_require_mode.clone();
require_mode
.initialize(context)
.map_err(|err| err.to_string())?;
luau_require_mode.process_block(block, context, options)
}
Self::Roblox(roblox_require_mode) => {
roblox_require_mode.process_block(block, context, options)
}
}
}
}

impl BundleRequireMode for RequireMode {
fn process_block(
&self,
block: &mut Block,
context: &Context,
options: &BundleOptions,
) -> RuleProcessResult {
match self {
RequireMode::Single(singular_require_mode) => {
singular_require_mode.process_block(block, context, options)
}
RequireMode::Hybrid(singular_require_modes) => {
let mut modes = singular_require_modes.clone();
for mode in modes.iter_mut() {
mode.initialize(context).map_err(|err| err.to_string())?;
}

let locator = LuauPathLocator::new(
&require_mode,
context.project_location(),
context.resources(),
);
let locator =
HybridPathLocator::new(&modes, context.project_location(), context.resources());

path_require_mode::process_block(block, context, options, locator)
}
Expand Down
Loading
Loading