Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support bundling with Luau types #249

Merged
merged 5 commits into from
Jan 10, 2025
Merged
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: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Changelog

* support Luau types when bundling ([#249](https://github.com/seaofvoices/darklua/pull/249))

## 0.15.0

* improve file watching: re-process specific files, sourcemap changes re-process the project, bundling re-starts whenever a dependent file changes ([#239](https://github.com/seaofvoices/darklua/pull/239))
Expand Down
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.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ durationfmt = "0.1.1"
elsa = "1.10.0"
env_logger = "0.11.5"
full_moon = { version = "1.0.0", features = ["roblox"] }
indexmap = "2.7.0"
json5 = "0.4.1"
log = "0.4.22"
pathdiff = "0.2.3"
Expand Down
2 changes: 1 addition & 1 deletion src/nodes/arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ impl Arguments {
}
}

pub(crate) fn shift_token_line(&mut self, amount: usize) {
pub(crate) fn shift_token_line(&mut self, amount: isize) {
match self {
Arguments::Tuple(tuple) => tuple.shift_token_line(amount),
Arguments::String(_) | Arguments::Table(_) => {}
Expand Down
2 changes: 1 addition & 1 deletion src/nodes/expressions/interpolated_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ impl InterpolationSegment {
}
}

pub(crate) fn shift_token_line(&mut self, amount: usize) {
pub(crate) fn shift_token_line(&mut self, amount: isize) {
match self {
InterpolationSegment::String(segment) => segment.shift_token_line(amount),
InterpolationSegment::Value(segment) => segment.shift_token_line(amount),
Expand Down
2 changes: 1 addition & 1 deletion src/nodes/expressions/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ impl NumberExpression {
}
}

pub(crate) fn shift_token_line(&mut self, amount: usize) {
pub(crate) fn shift_token_line(&mut self, amount: isize) {
match self {
NumberExpression::Decimal(number) => number.shift_token_line(amount),
NumberExpression::Hex(number) => number.shift_token_line(amount),
Expand Down
2 changes: 1 addition & 1 deletion src/nodes/expressions/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ impl TableEntry {
}
}

pub(crate) fn shift_token_line(&mut self, amount: usize) {
pub(crate) fn shift_token_line(&mut self, amount: isize) {
match self {
TableEntry::Field(entry) => entry.shift_token_line(amount),
TableEntry::Index(entry) => entry.shift_token_line(amount),
Expand Down
2 changes: 1 addition & 1 deletion src/nodes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ macro_rules! impl_token_fns {
)*)?
}

pub(crate) fn shift_token_line(&mut self, amount: usize) {
pub(crate) fn shift_token_line(&mut self, amount: isize) {
$(
self.$field.shift_token_line(amount);
)*
Expand Down
10 changes: 9 additions & 1 deletion src/nodes/statements/type_declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ impl TypeDeclarationStatement {
self.exported = true;
}

#[inline]
pub fn remove_exported(&mut self) {
self.exported = false;
if let Some(tokens) = self.tokens.as_mut() {
tokens.export.take();
}
}

#[inline]
pub fn is_exported(&self) -> bool {
self.exported
Expand Down Expand Up @@ -195,7 +203,7 @@ impl TypeDeclarationStatement {
}
}

pub(crate) fn shift_token_line(&mut self, amount: usize) {
pub(crate) fn shift_token_line(&mut self, amount: isize) {
self.name.shift_token_line(amount);
if let Some(tokens) = &mut self.tokens {
tokens.shift_token_line(amount);
Expand Down
6 changes: 4 additions & 2 deletions src/nodes/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,12 @@ impl Token {
}
}

pub(crate) fn shift_token_line(&mut self, amount: usize) {
pub(crate) fn shift_token_line(&mut self, amount: isize) {
match &mut self.position {
Position::LineNumberReference { line_number, .. }
| Position::LineNumber { line_number, .. } => *line_number += amount,
| Position::LineNumber { line_number, .. } => {
*line_number = line_number.saturating_add_signed(amount);
}
Position::Any { .. } => {}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/nodes/types/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ impl TableEntryType {
}
}

pub(crate) fn shift_token_line(&mut self, amount: usize) {
pub(crate) fn shift_token_line(&mut self, amount: isize) {
match self {
TableEntryType::Property(property) => property.shift_token_line(amount),
TableEntryType::Literal(literal) => literal.shift_token_line(amount),
Expand Down
2 changes: 1 addition & 1 deletion src/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ pub use node_counter::NodeCounter;
pub use node_processor::{NodePostProcessor, NodeProcessor};
pub use post_visitor::{DefaultPostVisitor, NodePostVisitor};
pub(crate) use scope_visitor::IdentifierTracker;
pub use scope_visitor::{Scope, ScopeVisitor};
pub use scope_visitor::{Scope, ScopePostVisitor, ScopeVisitor};
pub use visitors::{DefaultVisitor, NodeVisitor};
221 changes: 221 additions & 0 deletions src/process/scope_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::process::utils::is_valid_identifier;
use crate::process::{NodeProcessor, NodeVisitor};

use super::utils::{identifier_permutator, Permutator};
use super::{NodePostProcessor, NodePostVisitor};

/// Defines methods to interact with the concept of lexical scoping. The struct implementing this
/// trait should be able to keep track of identifiers when used along the ScopeVisitor.
Expand Down Expand Up @@ -228,6 +229,226 @@ impl<T: NodeProcessor + Scope> NodeVisitor<T> for ScopeVisitor {
}
}

/// A visitor that can be used only with a NodeProcessor that also implements the Scope trait.
pub struct ScopePostVisitor;

impl ScopePostVisitor {
fn visit_block_without_push<T: NodeProcessor + NodePostProcessor + Scope>(
block: &mut Block,
scope: &mut T,
) {
scope.process_block(block);

block
.iter_mut_statements()
.for_each(|statement| Self::visit_statement(statement, scope));

if let Some(last_statement) = block.mutate_last_statement() {
Self::visit_last_statement(last_statement, scope);
};
scope.process_after_block(block);
}
}

impl<T: NodeProcessor + NodePostProcessor + Scope> NodePostVisitor<T> for ScopePostVisitor {
fn visit_block(block: &mut Block, scope: &mut T) {
scope.push();
Self::visit_block_without_push(block, scope);
scope.pop();
}

fn visit_local_assign(statement: &mut LocalAssignStatement, scope: &mut T) {
scope.process_local_assign_statement(statement);

statement
.iter_mut_values()
.for_each(|value| Self::visit_expression(value, scope));

for r#type in statement
.iter_mut_variables()
.filter_map(TypedIdentifier::mutate_type)
{
Self::visit_type(r#type, scope);
}

statement.for_each_assignment(|variable, expression| {
scope.insert_local(variable.mutate_name(), expression)
});

scope.process_after_local_assign_statement(statement);
}

fn visit_function_expression(function: &mut FunctionExpression, scope: &mut T) {
scope.process_function_expression(function);

for r#type in function
.iter_mut_parameters()
.filter_map(TypedIdentifier::mutate_type)
{
Self::visit_type(r#type, scope);
}

if let Some(variadic_type) = function.mutate_variadic_type() {
Self::visit_function_variadic_type(variadic_type, scope);
}

if let Some(return_type) = function.mutate_return_type() {
Self::visit_function_return_type(return_type, scope);
}

scope.push();
function
.mutate_parameters()
.iter_mut()
.for_each(|parameter| scope.insert(parameter.mutate_name()));

scope.process_scope(function.mutate_block(), None);

Self::visit_block(function.mutate_block(), scope);
scope.pop();

scope.process_after_function_expression(function);
}

fn visit_function_statement(statement: &mut FunctionStatement, scope: &mut T) {
scope.process_function_statement(statement);
scope.process_variable_expression(statement.mutate_function_name().mutate_identifier());

for r#type in statement
.iter_mut_parameters()
.filter_map(TypedIdentifier::mutate_type)
{
Self::visit_type(r#type, scope);
}

if let Some(variadic_type) = statement.mutate_variadic_type() {
Self::visit_function_variadic_type(variadic_type, scope);
}

if let Some(return_type) = statement.mutate_return_type() {
Self::visit_function_return_type(return_type, scope);
}

scope.push();
if statement.get_name().has_method() {
scope.insert_self();
}
statement
.mutate_parameters()
.iter_mut()
.for_each(|parameter| scope.insert(parameter.mutate_name()));

scope.process_scope(statement.mutate_block(), None);

Self::visit_block(statement.mutate_block(), scope);
scope.pop();

scope.process_after_function_statement(statement);
}

fn visit_local_function(statement: &mut LocalFunctionStatement, scope: &mut T) {
scope.process_local_function_statement(statement);

scope.insert_local_function(statement);

for r#type in statement
.iter_mut_parameters()
.filter_map(TypedIdentifier::mutate_type)
{
Self::visit_type(r#type, scope);
}

if let Some(variadic_type) = statement.mutate_variadic_type() {
Self::visit_function_variadic_type(variadic_type, scope);
}

if let Some(return_type) = statement.mutate_return_type() {
Self::visit_function_return_type(return_type, scope);
}

scope.push();
statement
.mutate_parameters()
.iter_mut()
.for_each(|parameter| scope.insert(parameter.mutate_name()));

scope.process_scope(statement.mutate_block(), None);

Self::visit_block(statement.mutate_block(), scope);
scope.pop();

scope.process_after_local_function_statement(statement);
}

fn visit_generic_for(statement: &mut GenericForStatement, scope: &mut T) {
scope.process_generic_for_statement(statement);

statement
.iter_mut_expressions()
.for_each(|expression| Self::visit_expression(expression, scope));

scope.push();
statement
.iter_mut_identifiers()
.for_each(|identifier| scope.insert(identifier.mutate_name()));

for r#type in statement
.iter_mut_identifiers()
.filter_map(TypedIdentifier::mutate_type)
{
Self::visit_type(r#type, scope);
}

scope.process_scope(statement.mutate_block(), None);

Self::visit_block(statement.mutate_block(), scope);
scope.pop();

scope.process_after_generic_for_statement(statement);
}

fn visit_numeric_for(statement: &mut NumericForStatement, scope: &mut T) {
scope.process_numeric_for_statement(statement);

Self::visit_expression(statement.mutate_start(), scope);
Self::visit_expression(statement.mutate_end(), scope);

if let Some(step) = statement.mutate_step() {
Self::visit_expression(step, scope);
};

if let Some(r#type) = statement.mutate_identifier().mutate_type() {
Self::visit_type(r#type, scope);
}

scope.push();
scope.insert(statement.mutate_identifier().mutate_name());

scope.process_scope(statement.mutate_block(), None);

Self::visit_block(statement.mutate_block(), scope);
scope.pop();

scope.process_after_numeric_for_statement(statement);
}

fn visit_repeat_statement(statement: &mut RepeatStatement, scope: &mut T) {
scope.process_repeat_statement(statement);

scope.push();

let (block, condition) = statement.mutate_block_and_condition();
scope.process_scope(block, Some(condition));

Self::visit_block_without_push(statement.mutate_block(), scope);
Self::visit_expression(statement.mutate_condition(), scope);

scope.pop();

scope.process_after_repeat_statement(statement);
}
}

#[derive(Debug, Clone, Default)]
pub(crate) struct IdentifierTracker {
identifiers: Vec<HashSet<String>>,
Expand Down
2 changes: 1 addition & 1 deletion src/rules/append_text_comment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ impl Rule for AppendTextComment {
}

let shift_lines = text.lines().count();
ShiftTokenLine::new(shift_lines).flawless_process(block, context);
ShiftTokenLine::new(shift_lines as isize).flawless_process(block, context);

match self.location {
AppendLocation::Start => {
Expand Down
2 changes: 2 additions & 0 deletions src/rules/bundle/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub(crate) mod path_require_mode;
mod rename_type_declaration;
mod require_mode;

use std::path::Path;
Expand All @@ -9,6 +10,7 @@ use crate::rules::{
};
use crate::Parser;

pub(crate) use rename_type_declaration::RenameTypeDeclarationProcessor;
pub use require_mode::BundleRequireMode;
use wax::Pattern;

Expand Down
Loading
Loading