taymonbeal created this revision.
taymonbeal added reviewers: MyDeveloperDay, owenpan.
Herald added a project: All.
taymonbeal requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

The satisfies operator was added in TypeScript 4.9.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D146247

Files:
  clang/lib/Format/FormatToken.h
  clang/lib/Format/TokenAnnotator.cpp
  clang/lib/Format/UnwrappedLineParser.cpp
  clang/unittests/Format/FormatTestJS.cpp

Index: clang/unittests/Format/FormatTestJS.cpp
===================================================================
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2182,6 +2182,21 @@
                getGoogleJSStyleWithColumns(40));
 }
 
+TEST_F(FormatTestJS, SatisfiesSyntax) {
+  verifyFormat("let x = foo satisfies Type;");
+  verifyFormat("let x = (a + b) satisfies\n"
+               "    LongTypeIsLong;",
+               getGoogleJSStyleWithColumns(30));
+  verifyFormat("let x = [{x: 1} satisfies Type];");
+  verifyFormat("x = x satisfies [A, B];");
+  verifyFormat("x = x satisfies {a: string};");
+  verifyFormat("x = x satisfies (string);");
+  verifyFormat("x = x! satisfies (string);");
+  verifyFormat("let x = something.someFunction() satisfies\n"
+               "    LongTypeIsLong;",
+               getGoogleJSStyleWithColumns(50));
+}
+
 TEST_F(FormatTestJS, TypeArguments) {
   verifyFormat("class X<Y> {}");
   verifyFormat("new X<Y>();");
Index: clang/lib/Format/UnwrappedLineParser.cpp
===================================================================
--- clang/lib/Format/UnwrappedLineParser.cpp
+++ clang/lib/Format/UnwrappedLineParser.cpp
@@ -556,10 +556,11 @@
           // must also be part of it.
           ProbablyBracedList = LBraceStack.back()->is(TT_BracedListLBrace);
 
-          ProbablyBracedList = ProbablyBracedList ||
+          ProbablyBracedList =
+              ProbablyBracedList ||
                                (Style.isJavaScript() &&
-                                NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
-                                                 Keywords.kw_as));
+               NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in, Keywords.kw_as,
+                                Keywords.kw_satisfies));
           ProbablyBracedList = ProbablyBracedList ||
                                (Style.isCpp() && NextTok->is(tok::l_paren));
 
@@ -1213,7 +1214,8 @@
               Keywords.kw_let, Keywords.kw_var, tok::kw_const,
               Keywords.kw_abstract, Keywords.kw_extends, Keywords.kw_implements,
               Keywords.kw_instanceof, Keywords.kw_interface,
-              Keywords.kw_override, Keywords.kw_throws, Keywords.kw_from));
+              Keywords.kw_override, Keywords.kw_satisfies, Keywords.kw_throws,
+              Keywords.kw_from));
 }
 
 static bool mustBeJSIdentOrValue(const AdditionalKeywords &Keywords,
Index: clang/lib/Format/TokenAnnotator.cpp
===================================================================
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -1882,7 +1882,8 @@
         }
       }
       if (Current.Next &&
-          Current.Next->isOneOf(TT_BinaryOperator, Keywords.kw_as)) {
+          Current.Next->isOneOf(TT_BinaryOperator, Keywords.kw_as,
+                                Keywords.kw_satisfies)) {
         Current.setType(TT_NonNullAssertion);
         return;
       }
@@ -2074,7 +2075,7 @@
       return false;
 
     if (Tok.Previous->isOneOf(TT_LeadingJavaAnnotation, Keywords.kw_instanceof,
-                              Keywords.kw_as)) {
+                              Keywords.kw_as, Keywords.kw_satisfies)) {
       return false;
     }
     if (Style.isJavaScript() && Tok.Previous->is(Keywords.kw_in))
@@ -2725,7 +2726,8 @@
         return prec::Relational;
       }
       if (Style.isJavaScript() &&
-          Current->isOneOf(Keywords.kw_in, Keywords.kw_as)) {
+          Current->isOneOf(Keywords.kw_in, Keywords.kw_as,
+                           Keywords.kw_satisfies)) {
         return prec::Relational;
       }
       if (Current->is(TT_BinaryOperator) || Current->is(tok::comma))
@@ -4268,11 +4270,12 @@
         (!Left.Previous || !Left.Previous->is(tok::period))) {
       return true;
     }
-    if (Left.isOneOf(tok::kw_for, Keywords.kw_as) && Left.Previous &&
-        Left.Previous->is(tok::period) && Right.is(tok::l_paren)) {
+    if (Left.isOneOf(tok::kw_for, Keywords.kw_as, Keywords.kw_satisfies) &&
+        Left.Previous && Left.Previous->is(tok::period) &&
+        Right.is(tok::l_paren)) {
       return false;
     }
-    if (Left.is(Keywords.kw_as) &&
+    if (Left.isOneOf(Keywords.kw_as, Keywords.kw_satisfies) &&
         Right.isOneOf(tok::l_square, tok::l_brace, tok::l_paren)) {
       return true;
     }
@@ -4303,8 +4306,8 @@
     if (Right.is(TT_NonNullAssertion))
       return false;
     if (Left.is(TT_NonNullAssertion) &&
-        Right.isOneOf(Keywords.kw_as, Keywords.kw_in)) {
-      return true; // "x! as string", "x! in y"
+        Right.isOneOf(Keywords.kw_as, Keywords.kw_satisfies, Keywords.kw_in)) {
+      return true; // "x! as string", "x! satisfies string", "x! in y"
     }
   } else if (Style.Language == FormatStyle::LK_Java) {
     if (Left.is(tok::r_square) && Right.is(tok::l_brace))
@@ -5108,15 +5111,16 @@
       return Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None;
     if (Right.is(Keywords.kw_in))
       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_as, Keywords.kw_satisfies))
+      return false; // must not break before as or satisfies 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))
+    if (Left.isOneOf(Keywords.kw_as, Keywords.kw_satisfies))
       return true;
     if (Left.is(TT_NonNullAssertion))
       return true;
Index: clang/lib/Format/FormatToken.h
===================================================================
--- clang/lib/Format/FormatToken.h
+++ clang/lib/Format/FormatToken.h
@@ -960,6 +960,7 @@
     kw_let = &IdentTable.get("let");
     kw_module = &IdentTable.get("module");
     kw_readonly = &IdentTable.get("readonly");
+    kw_satisfies = &IdentTable.get("satisfies");
     kw_set = &IdentTable.get("set");
     kw_type = &IdentTable.get("type");
     kw_typeof = &IdentTable.get("typeof");
@@ -1170,7 +1171,8 @@
     JsExtraKeywords = std::unordered_set<IdentifierInfo *>(
         {kw_as, kw_async, kw_await, kw_declare, kw_finally, kw_from,
          kw_function, kw_get, kw_import, kw_is, kw_let, kw_module, kw_override,
-         kw_readonly, kw_set, kw_type, kw_typeof, kw_var, kw_yield,
+         kw_readonly, kw_satisfies, kw_set, kw_type, kw_typeof, kw_var,
+         kw_yield,
          // Keywords from the Java section.
          kw_abstract, kw_extends, kw_implements, kw_instanceof, kw_interface});
 
@@ -1349,6 +1351,7 @@
   IdentifierInfo *kw_let;
   IdentifierInfo *kw_module;
   IdentifierInfo *kw_readonly;
+  IdentifierInfo *kw_satisfies;
   IdentifierInfo *kw_set;
   IdentifierInfo *kw_type;
   IdentifierInfo *kw_typeof;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to