From dbf8f4c579dcabbaa04fe01b4f7ff97cedd4cb5f Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 20 Sep 2025 16:26:00 +0200 Subject: [PATCH 1/4] Add test case --- tests/inputs/excess-parentheses-comments-2.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/inputs/excess-parentheses-comments-2.lua diff --git a/tests/inputs/excess-parentheses-comments-2.lua b/tests/inputs/excess-parentheses-comments-2.lua new file mode 100644 index 00000000..f59f69c8 --- /dev/null +++ b/tests/inputs/excess-parentheses-comments-2.lua @@ -0,0 +1,11 @@ +-- https://github.com/JohnnyMorganz/StyLua/issues/1033 + +_ = { + ("foo"), + ("foo"), + -- ("foo") + -- ("foo") + -- ("foo") + ("foo"), + ("foo") +} From af08596cf874e64d007a95aaae3081f72c7d6aae Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 20 Sep 2025 16:26:13 +0200 Subject: [PATCH 2/4] Preserve comments when removing parentheses in hanging expression --- src/formatters/expression.rs | 60 ++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/src/formatters/expression.rs b/src/formatters/expression.rs index cc69ddb8..d30e3301 100644 --- a/src/formatters/expression.rs +++ b/src/formatters/expression.rs @@ -253,29 +253,8 @@ fn format_expression_internal( // If the context is for a prefix, we should always keep the parentheses, as they are always required if use_internal_expression && !keep_parentheses { - // Get the leading and trailing comments from contained span and append them onto the expression - let (start_parens, end_parens) = contained.tokens(); - let leading_comments = start_parens - .leading_trivia() - .filter(|token| trivia_util::trivia_is_comment(token)) - .flat_map(|x| { - vec![ - create_indent_trivia(ctx, shape), - x.to_owned(), - create_newline_trivia(ctx), - ] - }) - // .chain(std::iter::once(create_indent_trivia(ctx, shape))) - .collect(); - - let trailing_comments = end_parens - .trailing_trivia() - .filter(|token| trivia_util::trivia_is_comment(token)) - .flat_map(|x| { - // Prepend a single space beforehand - vec![Token::new(TokenType::spaces(1)), x.to_owned()] - }) - .collect(); + let (leading_comments, trailing_comments) = + contained_span_comments(ctx, contained, shape); format_expression(ctx, expression, shape) .update_leading_trivia(FormatTriviaType::Append(leading_comments)) @@ -358,6 +337,37 @@ fn format_expression_internal( } } +fn contained_span_comments( + ctx: &Context, + contained_span: &ContainedSpan, + shape: Shape, +) -> (Vec, Vec) { + // Get the leading and trailing comments from contained span and append them onto the expression + let (start_parens, end_parens) = contained_span.tokens(); + let leading_comments = start_parens + .leading_trivia() + .filter(|token| trivia_util::trivia_is_comment(token)) + .flat_map(|x| { + vec![ + create_indent_trivia(ctx, shape), + x.to_owned(), + create_newline_trivia(ctx), + ] + }) + // .chain(std::iter::once(create_indent_trivia(ctx, shape))) + .collect(); + + let trailing_comments = end_parens + .trailing_trivia() + .filter(|token| trivia_util::trivia_is_comment(token)) + .flat_map(|x| { + // Prepend a single space beforehand + vec![Token::new(TokenType::spaces(1)), x.to_owned()] + }) + .collect(); + (leading_comments, trailing_comments) +} + /// Determines whether the provided [`Expression`] is a brackets string, i.e. `[[string]]` /// We care about this because `[ [[string] ]` is invalid syntax if we remove the whitespace pub fn is_brackets_string(expression: &Expression) -> bool { @@ -1352,6 +1362,8 @@ fn format_hanging_expression_( // If the context is for a prefix, we should always keep the parentheses, as they are always required if use_internal_expression && !keep_parentheses { + let (leading_comments, trailing_comments) = + contained_span_comments(ctx, contained, shape); format_hanging_expression_( ctx, expression, @@ -1359,6 +1371,8 @@ fn format_hanging_expression_( expression_context, lhs_range, ) + .update_leading_trivia(FormatTriviaType::Append(leading_comments)) + .update_trailing_trivia(FormatTriviaType::Append(trailing_comments)) } else { let contained = format_contained_span(ctx, contained, lhs_shape); From 1b028f1d869dbd9bcfb32305c1112744a13b7bdd Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 20 Sep 2025 16:26:29 +0200 Subject: [PATCH 3/4] Update snapshot --- ...andard@excess-parentheses-comments-2.lua.snap | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tests/snapshots/tests__standard@excess-parentheses-comments-2.lua.snap diff --git a/tests/snapshots/tests__standard@excess-parentheses-comments-2.lua.snap b/tests/snapshots/tests__standard@excess-parentheses-comments-2.lua.snap new file mode 100644 index 00000000..8ae6fc4e --- /dev/null +++ b/tests/snapshots/tests__standard@excess-parentheses-comments-2.lua.snap @@ -0,0 +1,16 @@ +--- +source: tests/tests.rs +expression: "format(&contents, LuaVersion::Lua51)" +input_file: tests/inputs/excess-parentheses-comments-2.lua +--- +-- https://github.com/JohnnyMorganz/StyLua/issues/1033 + +_ = { + "foo", + "foo", + -- ("foo") + -- ("foo") + -- ("foo") + "foo", + "foo", +} From bed68cfff98f7698dabb57c1d2a85afbbc6a139d Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 20 Sep 2025 16:26:33 +0200 Subject: [PATCH 4/4] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2716eb3a..8e0b1a75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Fixed comments lost from expression after parentheses are removed when we are attempting to "hang" the expression. ([#1033](https://github.com/JohnnyMorganz/StyLua/issues/1033)) + ## [2.2.0] - 2025-09-14 ### Added