From 7777ca006af0f49507cd2d005c957f5fff3a96df Mon Sep 17 00:00:00 2001
From: Martin Probst <martin@probst.io>
Date: Fri, 4 Aug 2017 17:07:15 +0000
Subject: [PATCH] clang-format: [JS] support fields with case/switch/default
 labels.

Summary:
`case:` and `default:` would normally parse as labels for a `switch` block.
However in TypeScript, they can be used in field declarations, e.g.:

    interface I {
      case: string;
    }

This change special cases parsing them in declaration lines to avoid wrapping
them.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D36148

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@310070 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Format/UnwrappedLineParser.cpp | 14 ++++++++++++++
 unittests/Format/FormatTestJS.cpp  |  6 ++++++
 2 files changed, 20 insertions(+)

diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index 32853dc209..e6afd1f988 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/lib/Format/UnwrappedLineParser.cpp
@@ -326,6 +326,11 @@ void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
       break;
     case tok::kw_default:
     case tok::kw_case:
+      if (Style.Language == FormatStyle::LK_JavaScript && Line->MustBeDeclaration) {
+        // A 'case: string' style field declaration.
+        parseStructuralElement();
+        break;
+      }
       if (!SwitchLabelEncountered &&
           (Style.IndentCaseLabels || (Line->InPPDirective && Line->Level == 1)))
         ++Line->Level;
@@ -953,13 +958,22 @@ void UnwrappedLineParser::parseStructuralElement() {
     parseDoWhile();
     return;
   case tok::kw_switch:
+    if (Style.Language == FormatStyle::LK_JavaScript && Line->MustBeDeclaration)
+      // 'switch: string' field declaration.
+      break;
     parseSwitch();
     return;
   case tok::kw_default:
+    if (Style.Language == FormatStyle::LK_JavaScript && Line->MustBeDeclaration)
+      // 'default: string' field declaration.
+      break;
     nextToken();
     parseLabel();
     return;
   case tok::kw_case:
+    if (Style.Language == FormatStyle::LK_JavaScript && Line->MustBeDeclaration)
+      // 'case: string' field declaration.
+      break;
     parseCaseLabel();
     return;
   case tok::kw_try:
diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp
index 06f096a1d6..67004f223f 100644
--- a/unittests/Format/FormatTestJS.cpp
+++ b/unittests/Format/FormatTestJS.cpp
@@ -242,6 +242,12 @@ TEST_F(FormatTestJS, ReservedWords) {
   verifyFormat("var interface = 2;");
   verifyFormat("interface = 2;");
   verifyFormat("x = interface instanceof y;");
+  verifyFormat("interface Test {\n"
+               "  x: string;\n"
+               "  switch: string;\n"
+               "  case: string;\n"
+               "  default: string;\n"
+               "}\n");
 }
 
 TEST_F(FormatTestJS, ReservedWordsMethods) {
-- 
2.40.0