]> granicus.if.org Git - clang/commitdiff
clang-format: [JS] conditional types.
authorMartin Probst <martin@probst.io>
Thu, 27 Sep 2018 06:48:13 +0000 (06:48 +0000)
committerMartin Probst <martin@probst.io>
Thu, 27 Sep 2018 06:48:13 +0000 (06:48 +0000)
Summary:
This change adds some rudimentary support for conditional types.
Specifically it avoids breaking before `extends` and `infer` keywords,
which are subject to Automatic Semicolon Insertion, so breaking before
them creates incorrect syntax.

The actual formatting of the type expression is odd, but there is as of
yet no clear idea on how to format these.

See https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types.

Reviewers: krasimir

Subscribers: cfe-commits

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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@343179 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Format/FormatToken.h
lib/Format/TokenAnnotator.cpp
unittests/Format/FormatTestJS.cpp

index e3b31f924444629f86ce434bfbfe360deb7750d7..3733b888dd52889b5937448bcbb261f43fe37569 100644 (file)
@@ -680,6 +680,7 @@ struct AdditionalKeywords {
     kw_function = &IdentTable.get("function");
     kw_get = &IdentTable.get("get");
     kw_import = &IdentTable.get("import");
+    kw_infer = &IdentTable.get("infer");
     kw_is = &IdentTable.get("is");
     kw_let = &IdentTable.get("let");
     kw_module = &IdentTable.get("module");
@@ -751,6 +752,7 @@ struct AdditionalKeywords {
   IdentifierInfo *kw_function;
   IdentifierInfo *kw_get;
   IdentifierInfo *kw_import;
+  IdentifierInfo *kw_infer;
   IdentifierInfo *kw_is;
   IdentifierInfo *kw_let;
   IdentifierInfo *kw_module;
index 83c5b2e8b96402f821e276ed95849d464394a4d1..2cb4c0361b9d8265131cfbab94dbe62e433157af 100644 (file)
@@ -3088,6 +3088,12 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
       return Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None;
     if (Right.is(Keywords.kw_as))
       return false; // must not break before as in 'x as type' casts
+    if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_infer)) {
+      // extends and infer can appear as keywords in conditional types:
+      //   https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types
+      // do not break before them, as the expressions are subject to ASI.
+      return false;
+    }
     if (Left.is(Keywords.kw_as))
       return true;
     if (Left.is(TT_JsNonNullAssertion))
index ba0700edd4fa5751670d13e33e3bcb2a1081e10e..5a71f003371b9f9abc2a5daa33ce734e1f2a24ae 100644 (file)
@@ -2308,5 +2308,14 @@ TEST_F(FormatTestJS, ParameterNamingComment) {
   verifyFormat("callFoo(/*spaceAfterParameterNamingComment=*/ 1);");
 }
 
+TEST_F(FormatTestJS, ConditionalTypes) {
+  // Formatting below is not necessarily intentional, this just ensures that
+  // clang-format does not break the code.
+  verifyFormat( // wrap
+      "type UnionToIntersection<U> =\n"
+      "    (U extends any ? (k: U) => void :\n"
+      "                     never) extends((k: infer I) => void) ? I : never;");
+}
+
 } // end namespace tooling
 } // end namespace clang