Skip to content
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- (`lua52`) Support LuaJIT number suffixes LL/ULL/i ([#621](https://github.com/JohnnyMorganz/StyLua/issues/621))
- (`lua52`) Support `\z` escape sequences in strings ([#613](https://github.com/JohnnyMorganz/StyLua/issues/613))
- (`luau`) Support Luau string interpolation ([#607](https://github.com/JohnnyMorganz/StyLua/issues/607))
- Several optimisations applied to formatting functions to reduce time taken. Files which previously did not terminate (6MB+) now finish in reasonable time

## [0.15.3] - 2022-12-07

Expand Down
6 changes: 1 addition & 5 deletions src/formatters/assignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,11 +323,7 @@ pub fn format_assignment_no_trivia(
// Check if the assignment expressions or equal token contain comments. If they do, we bail out of determining any tactics
// and format multiline
let contains_comments = trivia_util::token_contains_comments(assignment.equal_token())
|| assignment.expressions().pairs().any(|pair| {
pair.punctuation()
.map_or(false, trivia_util::token_contains_comments)
|| trivia_util::expression_contains_inline_comments(pair.value())
});
|| trivia_util::punctuated_expression_inline_comments(assignment.expressions());

// Firstly attempt to format the assignment onto a single line, using an infinite column width shape
let mut var_list = try_format_punctuated(
Expand Down
7 changes: 2 additions & 5 deletions src/formatters/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,7 @@ pub fn format_return(ctx: &Context, return_node: &Return, shape: Shape) -> Retur
);

let contains_comments = return_token_trailing_comments
|| trivia_util::contains_comments(
returns.update_trailing_trivia(FormatTriviaType::Replace(Vec::new())), // We can ignore trailing trivia, as that won't affect anything
);
|| trivia_util::punctuated_expression_inline_comments(returns);

// See if we need to format multiline
// If we contain comments, we immediately force multiline, and return an empty Punctuated sequence as a placeholder (it will never be used)
Expand Down Expand Up @@ -590,8 +588,7 @@ pub fn format_block(ctx: &Context, block: &Block, shape: Shape) -> Block {
None => None,
};

block
.to_owned()
Block::new()
.with_stmts(formatted_statements)
.with_last_stmt(formatted_last_stmt)
}
20 changes: 10 additions & 10 deletions src/formatters/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,14 +447,8 @@ pub fn format_table_constructor(

let (start_brace, end_brace) = table_constructor.braces().tokens();

// Determine if we need to force the table multiline
let should_expand = should_expand(ctx, table_constructor);

let table_type = match (should_expand, table_constructor.fields().iter().next()) {
// We should expand, so force multiline
(true, _) => TableType::MultiLine,

(false, Some(_)) => {
let table_type = match table_constructor.fields().iter().next() {
Some(_) => {
// Determine if there was a new line at the end of the start brace
// If so, then we should always be multiline
if start_brace
Expand Down Expand Up @@ -511,12 +505,18 @@ pub fn format_table_constructor(

match singleline_shape.over_budget() {
true => TableType::MultiLine,
false => TableType::SingleLine,
false => match should_expand(ctx, table_constructor) {
true => TableType::MultiLine,
false => TableType::SingleLine,
},
}
}
}

(false, None) => TableType::Empty,
None => match should_expand(ctx, table_constructor) {
true => TableType::MultiLine,
false => TableType::Empty,
},
};

let (braces, fields) = match table_type {
Expand Down
44 changes: 42 additions & 2 deletions src/formatters/trivia_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1222,8 +1222,9 @@ pub fn token_contains_comments(token: &TokenReference) -> bool {
token_contains_comments_search(token, CommentSearch::All)
}

/// CAUTION: VERY EXPENSIVE FUNCTION FOR LARGE NODES
pub fn contains_comments(node: impl Node) -> bool {
node.tokens().into_iter().any(token_contains_comments)
node.tokens().any(token_contains_comments)
}

#[allow(dead_code)]
Expand Down Expand Up @@ -1272,7 +1273,46 @@ pub fn table_field_trailing_trivia(field: &Field) -> Vec<Token> {
// This can only happen if the expression is a BinOp
// We should ignore any comments which are trailing for the whole expression, as they are not inline
pub fn expression_contains_inline_comments(expression: &Expression) -> bool {
contains_comments(expression.update_trailing_trivia(FormatTriviaType::Replace(vec![])))
match expression {
Expression::BinaryOperator { lhs, binop, rhs } => {
contains_comments(binop)
|| contains_comments(lhs)
|| expression_contains_inline_comments(rhs)
}
Expression::UnaryOperator { unop, expression } => {
let op_contains_comments = match unop {
UnOp::Minus(token) | UnOp::Not(token) | UnOp::Hash(token) => {
contains_comments(token)
}
#[cfg(feature = "lua53")]
UnOp::Tilde(token) => contains_comments(token),
other => panic!("unknown node {:?}", other),
};
op_contains_comments || expression_contains_inline_comments(expression)
}
Expression::Parentheses {
contained,
expression,
} => {
token_contains_trailing_comments(contained.tokens().0)
|| token_contains_leading_comments(contained.tokens().1)
|| contains_comments(expression)
}
Expression::Value { value, .. } => match &**value {
Value::ParenthesesExpression(expression) => {
expression_contains_inline_comments(expression)
}
_ => false,
},
other => panic!("unknown node {:?}", other),
}
}

pub fn punctuated_expression_inline_comments(punctuated: &Punctuated<Expression>) -> bool {
punctuated.pairs().any(|pair| {
pair.punctuation().map_or(false, token_contains_comments)
|| expression_contains_inline_comments(pair.value())
})
}

// Commonly, we update trivia to add in a newline and indent trivia to the leading trivia of a token/node.
Expand Down