diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 7f0cf8ee840..d44da0781dc 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -364,6 +364,7 @@ module FourSlash { InsertSpaceAfterKeywordsInControlFlowStatements: true, InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false, InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, PlaceOpenBraceOnNewLineForFunctions: false, PlaceOpenBraceOnNewLineForControlBlocks: false, }; diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 7eaf944e916..11486264dea 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -990,6 +990,7 @@ namespace ts.server { InsertSpaceAfterKeywordsInControlFlowStatements: true, InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false, InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, PlaceOpenBraceOnNewLineForFunctions: false, PlaceOpenBraceOnNewLineForControlBlocks: false, } diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts index 99008770bba..2d694025c84 100644 --- a/src/server/protocol.d.ts +++ b/src/server/protocol.d.ts @@ -452,6 +452,9 @@ declare namespace ts.server.protocol { /** Defines space handling after opening and before closing non empty parenthesis. Default value is false. */ insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis?: boolean; + + /** Defines space handling after opening and before closing non empty brackets. Default value is false. */ + insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets?: boolean; /** Defines whether an open brace is put onto a new line for functions or not. Default value is false. */ placeOpenBraceOnNewLineForFunctions?: boolean; diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 497c5114400..50b8d1ef24c 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -39,12 +39,12 @@ namespace ts.formatting { public SpaceBetweenCloseBraceAndWhile: Rule; public NoSpaceAfterCloseBrace: Rule; - // No space for indexer and dot + // No space for dot public NoSpaceBeforeDot: Rule; public NoSpaceAfterDot: Rule; + + // No space before and after indexer public NoSpaceBeforeOpenBracket: Rule; - public NoSpaceAfterOpenBracket: Rule; - public NoSpaceBeforeCloseBracket: Rule; public NoSpaceAfterCloseBracket: Rule; // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}. @@ -191,6 +191,13 @@ namespace ts.formatting { public NoSpaceAfterOpenParen: Rule; public NoSpaceBeforeCloseParen: Rule; + // Insert space after opening and before closing nonempty brackets + public SpaceAfterOpenBracket: Rule; + public SpaceBeforeCloseBracket: Rule; + public NoSpaceBetweenBrackets: Rule; + public NoSpaceAfterOpenBracket: Rule; + public NoSpaceBeforeCloseBracket: Rule; + // Insert space after function keyword for anonymous functions public SpaceAfterAnonymousFunctionKeyword: Rule; public NoSpaceAfterAnonymousFunctionKeyword: Rule; @@ -232,13 +239,13 @@ namespace ts.formatting { this.SpaceBetweenCloseBraceAndWhile = new Rule(RuleDescriptor.create1(SyntaxKind.CloseBraceToken, SyntaxKind.WhileKeyword), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space)); this.NoSpaceAfterCloseBrace = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBraceToken, Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.CloseBracketToken, SyntaxKind.CommaToken, SyntaxKind.SemicolonToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); - // No space for indexer and dot - this.NoSpaceBeforeDot = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.DotToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceAfterDot = new Rule(RuleDescriptor.create3(SyntaxKind.DotToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceBeforeOpenBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.OpenBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceAfterOpenBracket = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceBeforeCloseBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceAfterCloseBracket = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBeforeBlockInFunctionDeclarationContext), RuleAction.Delete)); + // No space for dot + this.NoSpaceBeforeDot = new Rule( RuleDescriptor.create2( Shared.TokenRange.Any, SyntaxKind.DotToken ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); + this.NoSpaceAfterDot = new Rule( RuleDescriptor.create3( SyntaxKind.DotToken, Shared.TokenRange.Any ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); + + // No space before and after indexer + this.NoSpaceBeforeOpenBracket = new Rule( RuleDescriptor.create2( Shared.TokenRange.Any, SyntaxKind.OpenBracketToken ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); + this.NoSpaceAfterCloseBracket = new Rule( RuleDescriptor.create3( SyntaxKind.CloseBracketToken, Shared.TokenRange.Any ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext, Rules.IsNotBeforeBlockInFunctionDeclarationContext ), RuleAction.Delete ) ); // Place a space before open brace in a function declaration this.FunctionOpenBraceLeftTokenRange = Shared.TokenRange.AnyIncludingMultilineComments; @@ -405,8 +412,8 @@ namespace ts.formatting { this.NoSpaceBeforeSemicolon, this.SpaceBeforeOpenBraceInControl, this.SpaceBeforeOpenBraceInFunction, this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock, this.NoSpaceBeforeComma, - this.NoSpaceBeforeOpenBracket, this.NoSpaceAfterOpenBracket, - this.NoSpaceBeforeCloseBracket, this.NoSpaceAfterCloseBracket, + this.NoSpaceBeforeOpenBracket, + this.NoSpaceAfterCloseBracket, this.SpaceAfterSemicolon, this.NoSpaceBeforeOpenParenInFuncDecl, this.SpaceBetweenStatements, this.SpaceAfterTryFinally @@ -451,6 +458,13 @@ namespace ts.formatting { this.NoSpaceAfterOpenParen = new Rule(RuleDescriptor.create3(SyntaxKind.OpenParenToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); this.NoSpaceBeforeCloseParen = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); + // Insert space after opening and before closing nonempty brackets + this.SpaceAfterOpenBracket = new Rule( RuleDescriptor.create3( SyntaxKind.OpenBracketToken, Shared.TokenRange.Any ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Space ) ); + this.SpaceBeforeCloseBracket = new Rule( RuleDescriptor.create2( Shared.TokenRange.Any, SyntaxKind.CloseBracketToken ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Space ) ); + this.NoSpaceBetweenBrackets = new Rule( RuleDescriptor.create1( SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); + this.NoSpaceAfterOpenBracket = new Rule( RuleDescriptor.create3( SyntaxKind.OpenBracketToken, Shared.TokenRange.Any ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); + this.NoSpaceBeforeCloseBracket = new Rule( RuleDescriptor.create2( Shared.TokenRange.Any, SyntaxKind.CloseBracketToken ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); + // 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)); diff --git a/src/services/formatting/rulesProvider.ts b/src/services/formatting/rulesProvider.ts index ac1494571d1..f6cf1de474b 100644 --- a/src/services/formatting/rulesProvider.ts +++ b/src/services/formatting/rulesProvider.ts @@ -71,6 +71,17 @@ namespace ts.formatting { rules.push(this.globalRules.NoSpaceBetweenParens); } + if ( options.InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets ) { + rules.push( this.globalRules.SpaceAfterOpenBracket ); + rules.push( this.globalRules.SpaceBeforeCloseBracket ); + rules.push( this.globalRules.NoSpaceBetweenBrackets ); + } + else { + rules.push( this.globalRules.NoSpaceAfterOpenBracket ); + rules.push( this.globalRules.NoSpaceBeforeCloseBracket ); + rules.push( this.globalRules.NoSpaceBetweenBrackets ); + } + if (options.InsertSpaceAfterSemicolonInForStatements) { rules.push(this.globalRules.SpaceAfterSemicolonInFor); } diff --git a/src/services/services.ts b/src/services/services.ts index 07ba30f4e1d..bfee19b3a6a 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1149,6 +1149,7 @@ namespace ts { InsertSpaceAfterKeywordsInControlFlowStatements: boolean; InsertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean; InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean; + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; [s: string]: boolean | number| string; diff --git a/tests/cases/fourslash/formattingOptionsChange.ts b/tests/cases/fourslash/formattingOptionsChange.ts index d84e876f06b..3ac994ab6fc 100644 --- a/tests/cases/fourslash/formattingOptionsChange.ts +++ b/tests/cases/fourslash/formattingOptionsChange.ts @@ -6,6 +6,7 @@ /////*InsertSpaceAfterKeywordsInControlFlowStatements*/if (true) { } /////*InsertSpaceAfterFunctionKeywordForAnonymousFunctions*/(function () { }) /////*InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis*/(1 ) +/////*InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets*/[1 ] /////*PlaceOpenBraceOnNewLineForFunctions*/class foo { ////} /////*PlaceOpenBraceOnNewLineForControlBlocks*/if (true) { @@ -17,6 +18,7 @@ runTest("InsertSpaceBeforeAndAfterBinaryOperators", "1 + 2 - 3", "1+2-3"); runTest("InsertSpaceAfterKeywordsInControlFlowStatements", "if (true) { }", "if(true) { }"); runTest("InsertSpaceAfterFunctionKeywordForAnonymousFunctions", "(function () { })", "(function() { })"); runTest("InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis", " ( 1 )", " (1)"); +runTest( "InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets", "[ 1 ]", "[1]" ); runTest("PlaceOpenBraceOnNewLineForFunctions", "class foo", "class foo {"); runTest("PlaceOpenBraceOnNewLineForControlBlocks", "if ( true )", "if ( true ) {"); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 8ce5869a004..42cfc1248b0 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -90,6 +90,7 @@ module FourSlashInterface { InsertSpaceAfterKeywordsInControlFlowStatements: boolean; InsertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean; InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean; + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; [s: string]: boolean | number| string;