MyDeveloperDay updated this revision to Diff 462959.
MyDeveloperDay added a comment.

Ensure the colon stick with the variable declaraion

  for (var name: String in names) {
     Console.Print(name);
   }


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D134652/new/

https://reviews.llvm.org/D134652

Files:
  clang/docs/ClangFormatStyleOptions.rst
  clang/include/clang/Format/Format.h
  clang/lib/Format/Format.cpp
  clang/lib/Format/FormatToken.h
  clang/lib/Format/TokenAnnotator.cpp
  clang/tools/clang-format/ClangFormat.cpp
  clang/unittests/Format/CMakeLists.txt
  clang/unittests/Format/FormatTestCarbon.cpp
  clang/unittests/Format/TokenAnnotatorTest.cpp

Index: clang/unittests/Format/TokenAnnotatorTest.cpp
===================================================================
--- clang/unittests/Format/TokenAnnotatorTest.cpp
+++ clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -1045,6 +1045,31 @@
   EXPECT_TOKEN(Tokens[9], tok::colon, TT_GotoLabelColon);
 }
 
+TEST_F(TokenAnnotatorTest, UnderstandsCarbonReturnType) {
+  FormatStyle Style = getGoogleStyle(FormatStyle::LK_Carbon);
+
+  auto Tokens = annotate("fn Sum(var a: i32, var b: i32) -> i32 {", Style);
+  ASSERT_EQ(Tokens.size(), 17u) << Tokens;
+  EXPECT_TOKEN(Tokens[13], tok::arrow, TT_TrailingReturnArrow);
+  EXPECT_TOKEN(Tokens[15], tok::l_brace, TT_FunctionLBrace);
+}
+
+TEST_F(TokenAnnotatorTest, UnderstandsCarbonTypeOnColon) {
+  FormatStyle Style = getGoogleStyle(FormatStyle::LK_Carbon);
+
+  auto Tokens = annotate("let id: i32 = 57;", Style);
+  ASSERT_EQ(Tokens.size(), 8u) << Tokens;
+  EXPECT_TOKEN(Tokens[2], tok::colon, TT_JsTypeColon);
+}
+
+TEST_F(TokenAnnotatorTest, UnderstandsCarbonTypeOnColonForLoop) {
+  FormatStyle Style = getGoogleStyle(FormatStyle::LK_Carbon);
+
+  auto Tokens = annotate("for (var name: String in names) {", Style);
+  ASSERT_EQ(Tokens.size(), 11u) << Tokens;
+  EXPECT_TOKEN(Tokens[4], tok::colon, TT_JsTypeColon);
+}
+
 } // namespace
 } // namespace format
 } // namespace clang
Index: clang/unittests/Format/FormatTestCarbon.cpp
===================================================================
--- /dev/null
+++ clang/unittests/Format/FormatTestCarbon.cpp
@@ -0,0 +1,87 @@
+//===- unittest/Format/FormatTestCarbon.cpp - Formatting tests for Carbon -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "FormatTestUtils.h"
+#include "clang/Format/Format.h"
+#include "llvm/Support/Debug.h"
+#include "gtest/gtest.h"
+
+#define DEBUG_TYPE "format-test-json"
+
+namespace clang {
+namespace format {
+
+class FormatTestCarbon : public ::testing::Test {
+protected:
+  static std::string format(llvm::StringRef Code, unsigned Offset,
+                            unsigned Length, const FormatStyle &Style) {
+    LLVM_DEBUG(llvm::errs() << "---\n");
+    LLVM_DEBUG(llvm::errs() << Code << "\n\n");
+    std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
+    tooling::Replacements Replaces = reformat(Style, Code, Ranges);
+    auto Result = applyAllReplacements(Code, Replaces);
+    EXPECT_TRUE(static_cast<bool>(Result));
+    LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
+    return *Result;
+  }
+
+  static std::string
+  format(llvm::StringRef Code,
+         const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_Carbon)) {
+    return format(Code, 0, Code.size(), Style);
+  }
+
+  static FormatStyle getStyleWithColumns(unsigned ColumnLimit) {
+    FormatStyle Style = getGoogleStyle(FormatStyle::LK_Carbon);
+    Style.ColumnLimit = ColumnLimit;
+    return Style;
+  }
+
+  static void verifyFormatStable(llvm::StringRef Code,
+                                 const FormatStyle &Style) {
+    EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable";
+  }
+
+  static void verifyFormat(
+      llvm::StringRef Code,
+      const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_Carbon)) {
+    verifyFormatStable(Code, Style);
+    EXPECT_EQ(Code.str(), format(test::messUp(Code), Style));
+  }
+};
+
+TEST_F(FormatTestCarbon, CarbonBasicFunctions) {
+  FormatStyle Style = getGoogleStyle(FormatStyle::LK_Carbon);
+  verifyFormat("fn Sum(var a: i32, var b: i32) -> i32 {\n"
+               "  return a + b;\n"
+               "}",
+               Style);
+  verifyFormat("// Empty or void return type.\n"
+               "fn PrintCount(var count: i32) {\n"
+               "  Print(\" The count is { 0 } \", count);\n"
+               "}\n",
+               Style);
+}
+
+TEST_F(FormatTestCarbon, CarbonVariable) {
+  FormatStyle Style = getGoogleStyle(FormatStyle::LK_Carbon);
+
+  verifyFormat("var name: auto = \"Carbon is an open-source programming\";",
+               Style);
+  verifyFormat("let id: i32 = 57;", Style);
+  verifyFormat("var total_articles_published: i32 = 4500;", Style);
+}
+
+TEST_F(FormatTestCarbon, CarbonVariableInLoop) {
+  FormatStyle Style = getGoogleStyle(FormatStyle::LK_Carbon);
+
+  verifyFormat("for (var name: String in names) {", Style);
+}
+
+} // namespace format
+} // end namespace clang
Index: clang/unittests/Format/CMakeLists.txt
===================================================================
--- clang/unittests/Format/CMakeLists.txt
+++ clang/unittests/Format/CMakeLists.txt
@@ -6,6 +6,7 @@
   CleanupTest.cpp
   DefinitionBlockSeparatorTest.cpp
   FormatTest.cpp
+  FormatTestCarbon.cpp
   FormatTestComments.cpp
   FormatTestCSharp.cpp
   FormatTestJS.cpp
Index: clang/tools/clang-format/ClangFormat.cpp
===================================================================
--- clang/tools/clang-format/ClangFormat.cpp
+++ clang/tools/clang-format/ClangFormat.cpp
@@ -582,7 +582,8 @@
   cl::SetVersionPrinter(PrintVersion);
   cl::ParseCommandLineOptions(
       argc, argv,
-      "A tool to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# "
+      "A tool to format "
+      "C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C#/Carbon "
       "code.\n\n"
       "If no arguments are specified, it formats the code from standard input\n"
       "and writes the result to the standard output.\n"
Index: clang/lib/Format/TokenAnnotator.cpp
===================================================================
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -1018,7 +1018,10 @@
           ++Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts;
         }
       } else if (Contexts.back().ColonIsForRangeExpr) {
-        Tok->setType(TT_RangeBasedForLoopColon);
+        if (Style.isCarbon())
+          Tok->setType(TT_JsTypeColon);
+        else
+          Tok->setType(TT_RangeBasedForLoopColon);
       } else if (CurrentToken && CurrentToken->is(tok::numeric_constant)) {
         Tok->setType(TT_BitFieldColon);
       } else if (Contexts.size() == 1 &&
@@ -1038,7 +1041,10 @@
           if (PrevPrev && PrevPrev->isOneOf(tok::r_paren, tok::kw_noexcept))
             Tok->setType(TT_CtorInitializerColon);
         } else {
-          Tok->setType(TT_InheritanceColon);
+          if (Style.isCarbon())
+            Tok->setType(TT_JsTypeColon);
+          else
+            Tok->setType(TT_InheritanceColon);
         }
       } else if (canBeObjCSelectorComponent(*Tok->Previous) && Tok->Next &&
                  (Tok->Next->isOneOf(tok::r_paren, tok::comma) ||
@@ -1048,7 +1054,10 @@
         // the colon are passed as macro arguments.
         Tok->setType(TT_ObjCMethodExpr);
       } else if (Contexts.back().ContextKind == tok::l_paren) {
-        Tok->setType(TT_InlineASMColon);
+        if (Style.isCarbon())
+          Tok->setType(TT_JsTypeColon);
+        else
+          Tok->setType(TT_InlineASMColon);
       }
       break;
     case tok::pipe:
@@ -1842,6 +1851,13 @@
       }
     }
 
+    if (Style.isCarbon() && Line.MustBeDeclaration) {
+      if (Current.is(tok::arrow) && Current.Next->Next &&
+          Current.Next->Next->is(TT_FunctionLBrace)) {
+        Current.setType(TT_TrailingReturnArrow);
+      }
+    }
+
     // Line.MightBeFunctionDecl can only be true after the parentheses of a
     // function declaration have been found. In this case, 'Current' is a
     // trailing token of this declaration and thus cannot be a name.
@@ -3908,6 +3924,9 @@
         Right.is(tok::l_paren)) {
       return true;
     }
+  } else if (Style.isCarbon()) {
+    if (Right.is(TT_JsTypeColon))
+      return false;
   } else if (Style.isJavaScript()) {
     if (Left.is(TT_FatArrow))
       return true;
Index: clang/lib/Format/FormatToken.h
===================================================================
--- clang/lib/Format/FormatToken.h
+++ clang/lib/Format/FormatToken.h
@@ -1143,6 +1143,10 @@
     kw_with = &IdentTable.get("with");
     kw_wor = &IdentTable.get("wor");
 
+    // Carbon keywords
+    kw_me = &IdentTable.get("me");
+    kw_fn = &IdentTable.get("fn");
+
     // Symbols that are treated as keywords.
     kw_verilogHash = &IdentTable.get("#");
     kw_verilogHashHash = &IdentTable.get("##");
@@ -1172,6 +1176,9 @@
          // Keywords from the Java section.
          kw_abstract, kw_extends, kw_implements, kw_instanceof, kw_interface});
 
+    CarbonExtraKeywords = std::unordered_set<IdentifierInfo *>(
+        {kw_me, kw_package, kw_fn, kw_abstract});
+
     // Some keywords are not included here because they don't need special
     // treatment like `showcancelled` or they should be treated as identifiers
     // like `int` and `logic`.
@@ -1406,6 +1413,10 @@
   IdentifierInfo *kw_when;
   IdentifierInfo *kw_where;
 
+  // Carbon keywords
+  IdentifierInfo *kw_me;
+  IdentifierInfo *kw_fn;
+
   // Verilog keywords
   IdentifierInfo *kw_always;
   IdentifierInfo *kw_always_comb;
@@ -1800,6 +1811,9 @@
 
   /// The Verilog keywords beyond the C++ keyword set.
   std::unordered_set<IdentifierInfo *> VerilogExtraKeywords;
+
+  /// The Carbon keywords beyond the C++ keyword set
+  std::unordered_set<IdentifierInfo *> CarbonExtraKeywords;
 };
 
 } // namespace format
Index: clang/lib/Format/Format.cpp
===================================================================
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -60,14 +60,15 @@
 template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
   static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
     IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
+    IO.enumCase(Value, "Carbon", FormatStyle::LK_Carbon);
+    IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp);
     IO.enumCase(Value, "Java", FormatStyle::LK_Java);
     IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
+    IO.enumCase(Value, "Json", FormatStyle::LK_Json);
     IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);
     IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
     IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);
     IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto);
-    IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp);
-    IO.enumCase(Value, "Json", FormatStyle::LK_Json);
   }
 };
 
@@ -1501,6 +1502,9 @@
     GoogleStyle.BreakStringLiterals = false;
     GoogleStyle.ColumnLimit = 100;
     GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
+  } else if (Language == FormatStyle::LK_Carbon) {
+    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
+    GoogleStyle.MaxEmptyLinesToKeep = 1;
   }
 
   return GoogleStyle;
@@ -3487,6 +3491,8 @@
     return FormatStyle::LK_TableGen;
   if (FileName.endswith_insensitive(".cs"))
     return FormatStyle::LK_CSharp;
+  if (FileName.endswith_insensitive(".carbon"))
+    return FormatStyle::LK_Carbon;
   if (FileName.endswith_insensitive(".json"))
     return FormatStyle::LK_Json;
   if (FileName.endswith_insensitive(".sv") ||
Index: clang/include/clang/Format/Format.h
===================================================================
--- clang/include/clang/Format/Format.h
+++ clang/include/clang/Format/Format.h
@@ -2587,6 +2587,8 @@
   enum LanguageKind : int8_t {
     /// Do not use.
     LK_None,
+    /// Should be used for Carbon
+    LK_Carbon,
     /// Should be used for C, C++.
     LK_Cpp,
     /// Should be used for C#.
@@ -2614,6 +2616,7 @@
   };
   bool isCpp() const { return Language == LK_Cpp || Language == LK_ObjC; }
   bool isCSharp() const { return Language == LK_CSharp; }
+  bool isCarbon() const { return Language == LK_Carbon; }
   bool isJson() const { return Language == LK_Json; }
   bool isJavaScript() const { return Language == LK_JavaScript; }
   bool isVerilog() const { return Language == LK_Verilog; }
@@ -4292,6 +4295,8 @@
   switch (Language) {
   case FormatStyle::LK_Cpp:
     return "C++";
+  case FormatStyle::LK_Carbon:
+    return "Carbon";
   case FormatStyle::LK_CSharp:
     return "CSharp";
   case FormatStyle::LK_ObjC:
Index: clang/docs/ClangFormatStyleOptions.rst
===================================================================
--- clang/docs/ClangFormatStyleOptions.rst
+++ clang/docs/ClangFormatStyleOptions.rst
@@ -3184,6 +3184,9 @@
   * ``LK_None`` (in configuration: ``None``)
     Do not use.
 
+  * ``LK_Carbon`` (in configuration: ``Carbon``)
+    Should be used for Carbon
+
   * ``LK_Cpp`` (in configuration: ``Cpp``)
     Should be used for C, C++.
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to