diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 91c133ca352f5..bf1c57b218852 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -231,8 +231,8 @@ namespace ts.formatting { rule("SpaceAfterConstructor", SyntaxKind.ConstructorKeyword, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], RuleAction.Space), rule("NoSpaceAfterConstructor", SyntaxKind.ConstructorKeyword, SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], RuleAction.Delete), - rule("SpaceAfterComma", SyntaxKind.CommaToken, anyToken, [isOptionEnabled("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementContext, isNextTokenNotCloseBracket], RuleAction.Space), - rule("NoSpaceAfterComma", SyntaxKind.CommaToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementContext], RuleAction.Delete), + rule("SpaceAfterComma", SyntaxKind.CommaToken, anyToken, [isOptionEnabled("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNextTokenNotCloseBracket], RuleAction.Space), + rule("NoSpaceAfterComma", SyntaxKind.CommaToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext], RuleAction.Delete), // Insert space after function keyword for anonymous functions rule("SpaceAfterAnonymousFunctionKeyword", SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], RuleAction.Space), @@ -319,7 +319,7 @@ namespace ts.formatting { "SpaceBetweenStatements", [SyntaxKind.CloseParenToken, SyntaxKind.DoKeyword, SyntaxKind.ElseKeyword, SyntaxKind.CaseKeyword], anyToken, - [isNonJsxSameLineTokenContext, isNonJsxElementContext, isNotForContext], + [isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNotForContext], RuleAction.Space), // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter. rule("SpaceAfterTryFinally", [SyntaxKind.TryKeyword, SyntaxKind.FinallyKeyword], SyntaxKind.OpenBraceToken, [isNonJsxSameLineTokenContext], RuleAction.Space), @@ -614,8 +614,8 @@ namespace ts.formatting { return context.TokensAreOnSameLine() && context.contextNode.kind !== SyntaxKind.JsxText; } - function isNonJsxElementContext(context: FormattingContext): boolean { - return context.contextNode.kind !== SyntaxKind.JsxElement; + function isNonJsxElementOrFragmentContext(context: FormattingContext): boolean { + return context.contextNode.kind !== SyntaxKind.JsxElement && context.contextNode.kind !== SyntaxKind.JsxFragment; } function isJsxExpressionContext(context: FormattingContext): boolean { diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 0a444a7280afd..443a63a204225 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -508,6 +508,7 @@ namespace ts.formatting { case SyntaxKind.ArrayBindingPattern: case SyntaxKind.ObjectBindingPattern: case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxOpeningFragment: case SyntaxKind.JsxSelfClosingElement: case SyntaxKind.JsxExpression: case SyntaxKind.MethodSignature: @@ -554,6 +555,8 @@ namespace ts.formatting { (!!(child).namedBindings && (child).namedBindings.kind !== SyntaxKind.NamedImports); case SyntaxKind.JsxElement: return childKind !== SyntaxKind.JsxClosingElement; + case SyntaxKind.JsxFragment: + return childKind !== SyntaxKind.JsxClosingFragment; } // No explicit rule for given nodes so the result will follow the default value argument return indentByDefault; diff --git a/tests/cases/fourslash/formattingJsxElements.ts b/tests/cases/fourslash/formattingJsxElements.ts index a27bc8094565e..58326c5a9e943 100644 --- a/tests/cases/fourslash/formattingJsxElements.ts +++ b/tests/cases/fourslash/formattingJsxElements.ts @@ -47,6 +47,16 @@ //// ) ////} //// +////const bar = ( +//// <> +//// /*fragmentChildIndent*/

text

+//// +////); +//// +////const bar2 = <> +////

text

+//// /*fragmentClosingTagIndent*/; +//// ////(function () { //// return
,{integer}
;/*commaInJsxElement*/ ////
, {integer}
;/*commaInJsxElement2*/ +////<>,{integer};/*commaInJsxFragment*/ +////<>, {integer};/*commaInJsxFragment2*/ ////);/*closingParenInJsxElement*/ ////) ;/*closingParenInJsxElement2*/ +////<>);/*closingParenInJsxFragment*/ +////<>) ;/*closingParenInJsxFragment2*/ ////;/*jsxExpressionSpaces*/ ////;/*jsxExpressionSpaces2*/ //// {}}/*jsxExpressionSpaces3*/ @@ -111,6 +125,10 @@ verify.currentLineContentIs(' class3={'); goTo.marker("6"); verify.currentLineContentIs(' } />'); +goTo.marker("fragmentChildIndent"); +verify.currentLineContentIs("

text

"); +goTo.marker("fragmentClosingTagIndent"); +verify.currentLineContentIs(";"); goTo.marker("attrAutoformat"); verify.currentLineContentIs(' className=""'); @@ -139,10 +157,18 @@ goTo.marker("commaInJsxElement"); verify.currentLineContentIs("
,{integer}
;"); goTo.marker("commaInJsxElement2"); verify.currentLineContentIs("
, {integer}
;"); +goTo.marker("commaInJsxFragment"); +verify.currentLineContentIs("<>,{integer};"); +goTo.marker("commaInJsxFragment2"); +verify.currentLineContentIs("<>, {integer};"); goTo.marker("closingParenInJsxElement"); verify.currentLineContentIs(");"); goTo.marker("closingParenInJsxElement2"); verify.currentLineContentIs(") ;"); +goTo.marker("closingParenInJsxFragment"); +verify.currentLineContentIs("<>);"); +goTo.marker("closingParenInJsxFragment2"); +verify.currentLineContentIs("<>) ;"); goTo.marker("jsxExpressionSpaces"); verify.currentLineContentIs(";"); goTo.marker("jsxExpressionSpaces2");