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