diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index b727a2e2cb7..ee92a409c7b 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -363,6 +363,7 @@ namespace FourSlash { InsertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true, InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false, InsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false, + InsertSpaceAfterTypeAssertion: false, PlaceOpenBraceOnNewLineForFunctions: false, PlaceOpenBraceOnNewLineForControlBlocks: false, }; diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index e0f9e8d5cf6..e8df088a5c2 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1597,6 +1597,7 @@ namespace ts.server { InsertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true, InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false, InsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false, + InsertSpaceAfterTypeAssertion: false, PlaceOpenBraceOnNewLineForFunctions: false, PlaceOpenBraceOnNewLineForControlBlocks: false, }); diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 17ee9d435bf..2095f062bd1 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -138,7 +138,6 @@ namespace ts.formatting { public NoSpaceAfterOpenAngularBracket: Rule; public NoSpaceBeforeCloseAngularBracket: Rule; public NoSpaceAfterCloseAngularBracket: Rule; - public NoSpaceAfterTypeAssertion: Rule; // Remove spaces in empty interface literals. e.g.: x: {} public NoSpaceBetweenEmptyInterfaceBraceBrackets: Rule; @@ -240,6 +239,10 @@ namespace ts.formatting { public NoSpaceBeforeEqualInJsxAttribute: Rule; public NoSpaceAfterEqualInJsxAttribute: Rule; + // No space after type assertions + public NoSpaceAfterTypeAssertion: Rule; + public SpaceAfterTypeAssertion: Rule; + constructor() { /// /// Common Rules @@ -375,7 +378,6 @@ namespace ts.formatting { this.NoSpaceAfterOpenAngularBracket = new Rule(RuleDescriptor.create3(SyntaxKind.LessThanToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); this.NoSpaceBeforeCloseAngularBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.GreaterThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); this.NoSpaceAfterCloseAngularBracket = new Rule(RuleDescriptor.create3(SyntaxKind.GreaterThanToken, Shared.TokenRange.FromTokens([SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.GreaterThanToken, SyntaxKind.CommaToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); - this.NoSpaceAfterTypeAssertion = new Rule(RuleDescriptor.create3(SyntaxKind.GreaterThanToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeAssertionContext), RuleAction.Delete)); // Remove spaces in empty interface literals. e.g.: x: {} this.NoSpaceBetweenEmptyInterfaceBraceBrackets = new Rule(RuleDescriptor.create1(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsObjectTypeContext), RuleAction.Delete)); @@ -447,7 +449,6 @@ namespace ts.formatting { this.NoSpaceAfterOpenAngularBracket, this.NoSpaceBeforeCloseAngularBracket, this.NoSpaceAfterCloseAngularBracket, - this.NoSpaceAfterTypeAssertion, this.SpaceBeforeAt, this.NoSpaceAfterAt, this.SpaceAfterDecorator, @@ -526,6 +527,11 @@ namespace ts.formatting { // Insert space after function keyword for anonymous functions this.SpaceAfterAnonymousFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Space)); this.NoSpaceAfterAnonymousFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Delete)); + + // No space after type assertion + this.NoSpaceAfterTypeAssertion = new Rule(RuleDescriptor.create3(SyntaxKind.GreaterThanToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeAssertionContext), RuleAction.Delete)); + this.SpaceAfterTypeAssertion = new Rule(RuleDescriptor.create3(SyntaxKind.GreaterThanToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeAssertionContext), RuleAction.Space)); + } /// diff --git a/src/services/formatting/rulesProvider.ts b/src/services/formatting/rulesProvider.ts index b885accaf5e..eac99ce2b28 100644 --- a/src/services/formatting/rulesProvider.ts +++ b/src/services/formatting/rulesProvider.ts @@ -137,9 +137,16 @@ namespace ts.formatting { rules.push(this.globalRules.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock); } + if (options.InsertSpaceAfterTypeAssertion) { + rules.push(this.globalRules.SpaceAfterTypeAssertion); + } + else { + rules.push(this.globalRules.NoSpaceAfterTypeAssertion); + } + rules = rules.concat(this.globalRules.LowPriorityCommonRules); return rules; } } -} \ No newline at end of file +} diff --git a/src/services/types.ts b/src/services/types.ts index 5b0635e706d..ee3482a8c3a 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -353,6 +353,7 @@ namespace ts { InsertSpaceAfterOpeningAndBeforeClosingNonemptyBraces?: boolean; InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: boolean; InsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean; + InsertSpaceAfterTypeAssertion?: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; [s: string]: boolean | number | string | undefined; diff --git a/tests/cases/fourslash/formattingOptionsChange.ts b/tests/cases/fourslash/formattingOptionsChange.ts index 62272958b8a..63d51eec0ca 100644 --- a/tests/cases/fourslash/formattingOptionsChange.ts +++ b/tests/cases/fourslash/formattingOptionsChange.ts @@ -8,6 +8,7 @@ /////*InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis*/(1 ) /////*InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets*/[1 ]; [ ]; []; [,]; /////*InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces*/`${1}`;`${ 1 }` +/////*InsertSpaceAfterTypeAssertion*/const bar = Thing.getFoo(); /////*PlaceOpenBraceOnNewLineForFunctions*/class foo { ////} /////*PlaceOpenBraceOnNewLineForControlBlocks*/if (true) { @@ -22,6 +23,7 @@ runTest("InsertSpaceAfterFunctionKeywordForAnonymousFunctions", "(function () { runTest("InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis", " ( 1 )", " (1)"); runTest("InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets", "[ 1 ];[];[];[ , ];", "[1];[];[];[,];"); runTest("InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces", "`${ 1 }`; `${ 1 }`", "`${1}`; `${1}`"); +runTest("InsertSpaceAfterTypeAssertion", "const bar = Thing.getFoo();", "const bar = Thing.getFoo();"); runTest("PlaceOpenBraceOnNewLineForFunctions", "class foo", "class foo {"); runTest("PlaceOpenBraceOnNewLineForControlBlocks", "if ( true )", "if ( true ) {"); runTest("InsertSpaceAfterOpeningAndBeforeClosingNonemptyBraces", "{ var t = 1 };", "{var t = 1};"); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index a8216de8145..089bb52b215 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -83,6 +83,7 @@ declare namespace FourSlashInterface { InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean; InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: boolean; + InsertSpaceAfterTypeAssertion: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; [s: string]: boolean | number | string | undefined;