From 782f9f8620063719926907f922d9d27c1f280f21 Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 27 Sep 2025 11:57:48 +0200 Subject: [PATCH 1/4] Add test case --- .../excess-parentheses-type-pack-default.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/inputs-luau/excess-parentheses-type-pack-default.lua diff --git a/tests/inputs-luau/excess-parentheses-type-pack-default.lua b/tests/inputs-luau/excess-parentheses-type-pack-default.lua new file mode 100644 index 00000000..a19b0958 --- /dev/null +++ b/tests/inputs-luau/excess-parentheses-type-pack-default.lua @@ -0,0 +1,10 @@ +-- https://github.com/JohnnyMorganz/StyLua/issues/1038 + +type Object1 = { + method: (T) -> (), +} + +type Object2 = { + method: (T...) -> (), +} + From d0ce6c4ecfeddf7f937fe06321b94c7e54c2e843 Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 27 Sep 2025 11:58:00 +0200 Subject: [PATCH 2/4] Pass through variadic context when formatting default for generic declaration --- src/formatters/luau.rs | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/formatters/luau.rs b/src/formatters/luau.rs index 408d8623..b8312304 100644 --- a/src/formatters/luau.rs +++ b/src/formatters/luau.rs @@ -1097,6 +1097,7 @@ fn attempt_assigned_type_tactics( ctx: &Context, equal_token: TokenReference, type_info: &TypeInfo, + context: TypeInfoContext, shape: Shape, ) -> (TokenReference, TypeInfo) { const EQUAL_TOKEN_LENGTH: usize = " = ".len(); @@ -1109,11 +1110,11 @@ fn attempt_assigned_type_tactics( // Format declaration, hanging if it contains comments (ignoring leading and trailing comments, as they won't affect anything) let declaration = if contains_comments(strip_trivia(type_info)) { - hang_type_info(ctx, type_info, TypeInfoContext::new(), shape, 0) + hang_type_info(ctx, type_info, context, shape, 0) } else { - let proper_declaration = format_type_info(ctx, type_info, shape); + let proper_declaration = format_type_info_internal(ctx, type_info, context, shape); if shape.test_over_budget(&proper_declaration) { - hang_type_info(ctx, type_info, TypeInfoContext::new(), shape, 0) + hang_type_info(ctx, type_info, context, shape, 0) } else { proper_declaration } @@ -1141,8 +1142,9 @@ fn attempt_assigned_type_tactics( let mut equal_token = equal_token; let type_definition; let singleline_type_definition = - format_type_info(ctx, type_info, shape.with_infinite_width()); - let proper_type_definition = format_type_info(ctx, type_info, shape + EQUAL_TOKEN_LENGTH); + format_type_info_internal(ctx, type_info, context, shape.with_infinite_width()); + let proper_type_definition = + format_type_info_internal(ctx, type_info, context, shape + EQUAL_TOKEN_LENGTH); // Test to see whether the type definition must be hung due to comments let must_hang = should_hang_type(type_info, CommentSearch::All); @@ -1165,8 +1167,7 @@ fn attempt_assigned_type_tactics( equal_token = hang_equal_token(ctx, &equal_token, shape, true); let shape = shape.reset().increment_additional_indent(); - let hanging_type_definition = - hang_type_info(ctx, type_info, TypeInfoContext::new(), shape, 0); + let hanging_type_definition = hang_type_info(ctx, type_info, context, shape, 0); type_definition = hanging_type_definition; } } else { @@ -1178,7 +1179,7 @@ fn attempt_assigned_type_tactics( // Add the expression list into the indent range, as it will be indented by one let shape = shape.reset().increment_additional_indent(); - type_definition = format_type_info(ctx, type_info, shape); + type_definition = format_type_info_internal(ctx, type_info, context, shape); } else { // Use the proper formatting type_definition = proper_type_definition; @@ -1232,8 +1233,13 @@ fn format_type_declaration( }; let equal_token = fmt_symbol!(ctx, type_declaration.equal_token(), " = ", shape); - let (equal_token, type_definition) = - attempt_assigned_type_tactics(ctx, equal_token, type_declaration.type_definition(), shape); + let (equal_token, type_definition) = attempt_assigned_type_tactics( + ctx, + equal_token, + type_declaration.type_definition(), + TypeInfoContext::new(), + shape, + ); // Handle comments in between the type name and generics + generics and equal token // (or just type name and equal token if generics not present) @@ -1413,11 +1419,16 @@ fn format_generic_parameter( other => panic!("unknown node {:?}", other), }; + let context = match generic_parameter.parameter() { + GenericParameterInfo::Variadic { .. } => TypeInfoContext::new().mark_within_generic(), + _ => TypeInfoContext::new(), + }; + let default_type = match (generic_parameter.equals(), generic_parameter.default_type()) { (Some(equals), Some(default_type)) => { let equals = fmt_symbol!(ctx, equals, " = ", shape); let (equals, default_type) = - attempt_assigned_type_tactics(ctx, equals, default_type, shape); + attempt_assigned_type_tactics(ctx, equals, default_type, context, shape); Some((equals, default_type)) } (None, None) => None, From a059e6efbe137799affe7153130340bc0d32eac2 Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 27 Sep 2025 11:58:08 +0200 Subject: [PATCH 3/4] Update snapshot --- ...u@excess-parentheses-type-pack-default.lua.snap | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/snapshots/tests__luau@excess-parentheses-type-pack-default.lua.snap diff --git a/tests/snapshots/tests__luau@excess-parentheses-type-pack-default.lua.snap b/tests/snapshots/tests__luau@excess-parentheses-type-pack-default.lua.snap new file mode 100644 index 00000000..fdcf311a --- /dev/null +++ b/tests/snapshots/tests__luau@excess-parentheses-type-pack-default.lua.snap @@ -0,0 +1,14 @@ +--- +source: tests/tests.rs +expression: "format(&contents, LuaVersion::Luau)" +input_file: tests/inputs-luau/excess-parentheses-type-pack-default.lua +--- +-- https://github.com/JohnnyMorganz/StyLua/issues/1038 + +type Object1 = { + method: (T) -> (), +} + +type Object2 = { + method: (T...) -> (), +} From 0484a39569c4889095c0d972ab68a99becb78c65 Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 27 Sep 2025 11:58:12 +0200 Subject: [PATCH 4/4] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e8597dc..a40f7478 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed `document_range_formatting_provider` capability missing from `ServerCapabilities` in language server mode - Fixed current working directory incorrectly used as config search root in language server mode -- now, the root of the opened workspace is used instead ([#1032](https://github.com/JohnnyMorganz/StyLua/issues/1032)) - Language server mode now correctly respects `.styluaignore` files ([#1035](https://github.com/JohnnyMorganz/StyLua/issues/1035)) +- Luau: Fixed parentheses incorrectly removed on a single type that is the default for a variadic generic parameter ([#1038](https://github.com/JohnnyMorganz/StyLua/issues/1038)) ## [2.2.0] - 2025-09-14