diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index b5470579787f4..320df83e35acf 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -35,9 +35,13 @@ module ts.formatting { // Space after keyword but not before ; or : or ? public NoSpaceBeforeSemicolon: Rule; public NoSpaceBeforeColon: Rule; - public NoSpaceBeforeQMark: Rule; + public NoSpaceBeforeQuestionMark: Rule; public SpaceAfterColon: Rule; - public SpaceAfterQMark: Rule; + // insert space after '?' only when it is used in conditional operator + public SpaceAfterQuestionMarkInConditionalOperator: Rule; + // in other cases there should be no space between '?' and next token + public NoSpaceAfterQuestionMark: Rule; + public SpaceAfterSemicolon: Rule; // Space/new line after }. @@ -215,9 +219,10 @@ module ts.formatting { // Space after keyword but not before ; or : or ? this.NoSpaceBeforeSemicolon = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.SemicolonToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); this.NoSpaceBeforeColon = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.ColonToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Delete)); - this.NoSpaceBeforeQMark = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.QuestionToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Delete)); + this.NoSpaceBeforeQuestionMark = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.QuestionToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Delete)); this.SpaceAfterColon = new Rule(RuleDescriptor.create3(SyntaxKind.ColonToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Space)); - this.SpaceAfterQMark = new Rule(RuleDescriptor.create3(SyntaxKind.QuestionToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Space)); + this.SpaceAfterQuestionMarkInConditionalOperator = new Rule(RuleDescriptor.create3(SyntaxKind.QuestionToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsConditionalOperatorContext), RuleAction.Space)); + this.NoSpaceAfterQuestionMark = new Rule(RuleDescriptor.create3(SyntaxKind.QuestionToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); this.SpaceAfterSemicolon = new Rule(RuleDescriptor.create3(SyntaxKind.SemicolonToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space)); // Space after }. @@ -341,7 +346,8 @@ module ts.formatting { this.HighPriorityCommonRules = [ this.IgnoreBeforeComment, this.IgnoreAfterLineComment, - this.NoSpaceBeforeColon, this.SpaceAfterColon, this.NoSpaceBeforeQMark, this.SpaceAfterQMark, + this.NoSpaceBeforeColon, this.SpaceAfterColon, this.NoSpaceBeforeQuestionMark, this.SpaceAfterQuestionMarkInConditionalOperator, + this.NoSpaceAfterQuestionMark, this.NoSpaceBeforeDot, this.NoSpaceAfterDot, this.NoSpaceAfterUnaryPrefixOperator, this.NoSpaceAfterUnaryPreincrementOperator, this.NoSpaceAfterUnaryPredecrementOperator, @@ -475,6 +481,10 @@ module ts.formatting { return !Rules.IsBinaryOpContext(context); } + static IsConditionalOperatorContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.ConditionalExpression; + } + static IsSameLineTokenOrBeforeMultilineBlockContext(context: FormattingContext): boolean { //// This check is mainly used inside SpaceBeforeOpenBraceInControl and SpaceBeforeOpenBraceInFunction. //// diff --git a/tests/cases/fourslash/formattingConditionalOperator.ts b/tests/cases/fourslash/formattingConditionalOperator.ts new file mode 100644 index 0000000000000..545adb572b152 --- /dev/null +++ b/tests/cases/fourslash/formattingConditionalOperator.ts @@ -0,0 +1,6 @@ +/// + +////var x=true?1:2 +format.document(); +goTo.bof(); +verify.currentLineContentIs("var x = true ? 1 : 2");; \ No newline at end of file diff --git a/tests/cases/fourslash/formattingQMark.ts b/tests/cases/fourslash/formattingQMark.ts new file mode 100644 index 0000000000000..83ca56a49f660 --- /dev/null +++ b/tests/cases/fourslash/formattingQMark.ts @@ -0,0 +1,12 @@ +/// + +////interface A { +/////*1*/ foo? (); +/////*2*/ foo? (); +////} + +format.document(); +goTo.marker("1"); +verify.currentLineContentIs(" foo?();"); +goTo.marker("2"); +verify.currentLineContentIs(" foo?();"); \ No newline at end of file diff --git a/tests/cases/fourslash/genericsFormatting.ts b/tests/cases/fourslash/genericsFormatting.ts index f6f1426316c64..36833cadd10a1 100644 --- a/tests/cases/fourslash/genericsFormatting.ts +++ b/tests/cases/fourslash/genericsFormatting.ts @@ -30,4 +30,4 @@ goTo.marker("inNewSignature"); verify.currentLineContentIs(" new (a: T);"); goTo.marker("inOptionalMethodSignature"); -verify.currentLineContentIs(" op? (a: T, b: M);"); \ No newline at end of file +verify.currentLineContentIs(" op?(a: T, b: M);"); \ No newline at end of file