Manikishan updated this revision to Diff 209933.

Repository:
  rC Clang

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

https://reviews.llvm.org/D64695

Files:
  docs/ClangFormatStyleOptions.rst
  include/clang/Format/Format.h
  lib/Format/Format.cpp
  unittests/Format/SortIncludesTest.cpp

Index: unittests/Format/SortIncludesTest.cpp
===================================================================
--- unittests/Format/SortIncludesTest.cpp
+++ unittests/Format/SortIncludesTest.cpp
@@ -665,6 +665,67 @@
                  "#include \"a.h\""));
 }
 
+TEST_F(SortIncludesTest, ParamAndTypesCheck) {
+  FmtStyle = getNetBSDStyle();
+  EXPECT_EQ("#include <sys/param.h>\n"
+			"#include <sys/types.h>\n"
+			"#include <sys/ioctl.h>\n"
+			"#include <sys/socket.h>\n"
+			"#include <sys/stat.h>\n"
+			"#include <sys/wait.h>\n",
+			sort("#include <sys/ioctl.h>\n"
+				 "#include <sys/stat.h>\n"
+				 "#include <sys/socket.h>\n"
+				 "#include <sys/types.h>\n"
+				 "#include <sys/param.h>\n"
+				 "#include <sys/wait.h>\n"));
+	
+}
+
+TEST_F(SortIncludesTest, SortedIncludesInSingleBlockReGroupWithNetBSDSpecifications) {
+  FmtStyle = getNetBSDStyle();
+  EXPECT_EQ("#include <sys/param.h>\n"  
+      "#include <sys/types.h>\n"  
+      "#include <sys/ioctl.h>\n"  
+      "#include <sys/socket.h>\n" 
+      "#include <sys/stat.h>\n"
+      "#include <sys/wait.h>\n"
+      "\n"
+      "#include <net/if.h>\n"
+      "#include <net/if_dl.h>\n"
+      "#include <net/route.h>\n"
+      "#include <netinet/in.h>\n"
+      "#include <protocols/rwhod.h>\n"
+      "\n"
+      "#include <assert.h>\n"
+      "#include <errno.h>\n"
+      "#include <inttypes.h>\n"
+      "#include <stdio.h>\n"
+      "#include <stdlib.h>\n"
+      "\n"
+      "#include <paths.h>\n"
+      "\n"
+      "#include \"pathnames.h\"\n",
+      sort("#include <sys/param.h>\n"		
+           "#include <sys/types.h>\n"		
+           "#include <sys/ioctl.h>\n"		
+           "#include <net/if_dl.h>\n"
+           "#include <net/route.h>\n"
+           "#include <netinet/in.h>\n"
+           "#include <sys/socket.h>\n"	
+           "#include <sys/stat.h>\n"
+           "#include <sys/wait.h>\n"		
+           "#include <net/if.h>\n"
+           "#include <protocols/rwhod.h>\n"
+           "#include <assert.h>\n"
+           "#include <paths.h>\n"
+           "#include \"pathnames.h\"\n"		
+           "#include <errno.h>\n"
+           "#include <inttypes.h>\n"
+           "#include <stdio.h>\n"
+           "#include <stdlib.h>\n"));
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang
Index: lib/Format/Format.cpp
===================================================================
--- lib/Format/Format.cpp
+++ lib/Format/Format.cpp
@@ -278,8 +278,15 @@
   }
 };
 
-template <>
-struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
+template <> struct ScalarEnumerationTraits<FormatStyle::IncludeHeadersStyle> {
+  static void enumeration(IO &IO,
+                          FormatStyle::IncludeHeadersStyle &Value) {
+    IO.enumCase(Value, "None", FormatStyle::SIS_None);
+    IO.enumCase(Value, "NetBSD", FormatStyle::SIS_NetBSD);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
   static void enumeration(IO &IO,
                           FormatStyle::SpaceBeforeParensOptions &Value) {
     IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
@@ -479,6 +486,7 @@
     IO.mapOptional("RawStringFormats", Style.RawStringFormats);
     IO.mapOptional("ReflowComments", Style.ReflowComments);
     IO.mapOptional("SortIncludes", Style.SortIncludes);
+    IO.mapOptional("SortIncludesStyle", Style.SortIncludesStyle);
     IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);
     IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
     IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot);
@@ -609,7 +617,7 @@
     return Style;
   FormatStyle Expanded = Style;
   Expanded.BraceWrapping = {false, false, false, false, false, false,
-                            false, false, false, false, false,
+                            false, false, false, false, false, 
                             false, false, true,  true,  true};
   switch (Style.BreakBeforeBraces) {
   case FormatStyle::BS_Linux:
@@ -759,6 +767,7 @@
 
   LLVMStyle.DisableFormat = false;
   LLVMStyle.SortIncludes = true;
+  LLVMStyle.SortIncludesStyle = FormatStyle::SIS_None;
   LLVMStyle.SortUsingDeclarations = true;
   LLVMStyle.StatementMacros.push_back("Q_UNUSED");
   LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");
@@ -919,6 +928,7 @@
         "javax",
     };
     ChromiumStyle.SortIncludes = true;
+    ChromiumStyle.SortIncludesStyle = FormatStyle::SIS_None;
   } else if (Language == FormatStyle::LK_JavaScript) {
     ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
     ChromiumStyle.AllowShortLoopsOnASingleLine = false;
@@ -1023,6 +1033,30 @@
   return Style;
 }
 
+FormatStyle getNetBSDStyle() {
+  FormatStyle NetBSDStyle = getLLVMStyle();
+  NetBSDStyle.AlignTrailingComments = true;
+  NetBSDStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
+  NetBSDStyle.AlignConsecutiveMacros = true;
+  NetBSDStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
+  NetBSDStyle.ColumnLimit = 80;
+  NetBSDStyle.ContinuationIndentWidth = 4;
+  NetBSDStyle.Cpp11BracedListStyle = false;
+  NetBSDStyle.FixNamespaceComments = true;
+  NetBSDStyle.IndentCaseLabels = false;
+  NetBSDStyle.IndentWidth = 8;
+  NetBSDStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
+  NetBSDStyle.IncludeStyle.IncludeCategories = {
+      {"^<sys/", 7},        {"^<uvm/", 6},  {"^<(net.*|protocols)/", 5},
+      {"^<(fs*)", 4},       {"^<path*", 3}, {"^<[^\/].*\.h>", 2},
+      {"^\"\w.*\.h\"$", 1}, {".*", 0}};
+  NetBSDStyle.SortIncludes = true;
+  NetBSDStyle.SortIncludesStyle = FormatStyle::SIS_NetBSD;
+  NetBSDStyle.TabWidth = 8;
+  NetBSDStyle.UseTab = FormatStyle::UT_Always;
+  return NetBSDStyle;
+}
+
 FormatStyle getNoStyle() {
   FormatStyle NoStyle = getLLVMStyle();
   NoStyle.DisableFormat = true;
@@ -1047,6 +1081,8 @@
     *Style = getGNUStyle();
   } else if (Name.equals_lower("microsoft")) {
     *Style = getMicrosoftStyle(Language);
+  } else if (Name.equals_lower("netbsd")) {
+    *Style = getNetBSDStyle();
   } else if (Name.equals_lower("none")) {
     *Style = getNoStyle();
   } else {
@@ -1763,6 +1799,81 @@
   }
   return std::make_pair(CursorIndex, OffsetToEOL);
 }
+enum CppIncludeHeadersKind {
+  IHK_KERNELHEADERS,
+  IHK_NETWORKHEADERS,
+  IHK_FILESYSHEADERS,
+  IHK_MACHINESHEADERS,
+  IHK_ARCHHEADERS,
+  IHK_USERHEADERS,
+  IHK_INCLUDESWITHQUOTES,
+};
+
+CppIncludeHeadersKind getHeadersKind(std::string Filename) {
+  SmallVector<StringRef, 4> Matches;
+  const char KernelHeaderPattern[] = R"(^<(sys.*|uvm|dev)/)";
+  const char NetworkHeaderPattern[] = R"(^<(net.*|protocols)/)";
+  const char FilesSystemHeaderPattern[] =
+      R"(^<(fs|miscfs|msdosfs|nfs|ntfs|ufs))";
+  const char MachineHeaderPattern[] = R"(^<machine/)";
+  const char ArchHeadersPattern[] = R"(^<(x86|amd64|i386|xen)/)";
+  const char UserHeaderPattern[] = R"(^<[a-zA-Z0-9]*\.h>)";
+  const char IncludeWithQuotesPattern[] = R"(^\"*$\")";
+  llvm::Regex MatchKernel = llvm::Regex(KernelHeaderPattern);
+  llvm::Regex MatchNetwork = llvm::Regex(NetworkHeaderPattern);
+  llvm::Regex MatchFileSys = llvm::Regex(FilesSystemHeaderPattern);
+  llvm::Regex MatchMachine = llvm::Regex(MachineHeaderPattern);
+  llvm::Regex MatchArch = llvm::Regex(ArchHeadersPattern);
+  llvm::Regex MatchUser = llvm::Regex(UserHeaderPattern);
+  llvm::Regex MatchQuotes = llvm::Regex(IncludeWithQuotesPattern);
+  if (MatchKernel.match(Filename))
+    return IHK_KERNELHEADERS;
+  else if (MatchNetwork.match(Filename))
+    return IHK_NETWORKHEADERS;
+  else if (MatchArch.match(Filename))
+    return IHK_ARCHHEADERS;
+  else if (MatchQuotes.match(Filename))
+    return IHK_INCLUDESWITHQUOTES;
+  else if (MatchUser.match(Filename))
+    return IHK_USERHEADERS;
+  else if (MatchFileSys.match(Filename))
+    return IHK_FILESYSHEADERS;
+  else if (MatchMachine.match(Filename))
+    return IHK_MACHINESHEADERS;
+  return IHK_INCLUDESWITHQUOTES;
+}
+
+unsigned getNetBSDIncludePriority(std::string Filename) {
+  CppIncludeHeadersKind CK = getHeadersKind(Filename);
+  switch (CK) {
+  case IHK_KERNELHEADERS:
+    return llvm::StringSwitch<unsigned>(Filename)
+        .Case("<sys/param.h>", 0)
+        .Case("<sys/types.h>", 1)
+        .StartsWith("<sys/", 2)
+        .StartsWith("<uvm/", 3)
+        .StartsWith("<dev/", 7)
+        .Default(1002);
+  case IHK_NETWORKHEADERS:
+    return llvm::StringSwitch<unsigned>(Filename)
+        .StartsWith("<net", 4)
+        .StartsWith("<protocols", 5)
+        .Default(1002);
+  case IHK_FILESYSHEADERS:
+    return 6;
+  case IHK_MACHINESHEADERS:
+    return 8;
+  case IHK_ARCHHEADERS:
+    return 9;
+  case IHK_USERHEADERS:
+    return llvm::StringSwitch<unsigned>(Filename)
+      .StartsWith("<path",11)
+      .Default(10);
+  case IHK_INCLUDESWITHQUOTES:
+    return 12;
+  }
+  return 100;
+}
 
 // Sorts and deduplicate a block of includes given by 'Includes' alphabetically
 // adding the necessary replacement to 'Replaces'. 'Includes' must be in strict
@@ -1774,8 +1885,8 @@
 static void sortCppIncludes(const FormatStyle &Style,
                             const SmallVectorImpl<IncludeDirective> &Includes,
                             ArrayRef<tooling::Range> Ranges, StringRef FileName,
-                            StringRef Code,
-                            tooling::Replacements &Replaces, unsigned *Cursor) {
+                            StringRef Code, tooling::Replacements &Replaces,
+                            unsigned *Cursor) {
   unsigned IncludesBeginOffset = Includes.front().Offset;
   unsigned IncludesEndOffset =
       Includes.back().Offset + Includes.back().Text.size();
@@ -1783,11 +1894,22 @@
   if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
     return;
   SmallVector<unsigned, 16> Indices;
-  for (unsigned i = 0, e = Includes.size(); i != e; ++i)
+  SmallVector<unsigned, 16> IncludesPriority;
+  for (unsigned i = 0, e = Includes.size(); i != e; ++i){
+    if(Style.SortIncludesStyle == FormatStyle::SIS_NetBSD)
+      IncludesPriority.push_back(getNetBSDIncludePriority(Includes[i].Filename));
+    else
+      IncludesPriority.push_back(i);  
     Indices.push_back(i);
+  }
+
   llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-    return std::tie(Includes[LHSI].Category, Includes[LHSI].Filename) <
-           std::tie(Includes[RHSI].Category, Includes[RHSI].Filename);
+    if (Style.SortIncludesStyle == FormatStyle::SIS_NetBSD)
+      return std::tie(IncludesPriority[LHSI], Includes[LHSI].Filename) <
+            std::tie(IncludesPriority[RHSI], Includes[RHSI].Filename);
+    else
+      return std::tie(Includes[LHSI].Category, Includes[LHSI].Filename) <
+            std::tie(Includes[RHSI].Category, Includes[RHSI].Filename);
   });
   // The index of the include on which the cursor will be put after
   // sorting/deduplicating.
@@ -1906,8 +2028,8 @@
           MainIncludeFound = true;
         IncludesInBlock.push_back({IncludeName, Line, Prev, Category});
       } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
-        sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code,
-                        Replaces, Cursor);
+          sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code,
+                          Replaces, Cursor);
         IncludesInBlock.clear();
         FirstIncludeBlock = false;
       }
@@ -1918,8 +2040,8 @@
     SearchFrom = Pos + 1;
   }
   if (!IncludesInBlock.empty()) {
-    sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces,
-                    Cursor);
+      sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces,
+                      Cursor);
   }
   return Replaces;
 }
Index: include/clang/Format/Format.h
===================================================================
--- include/clang/Format/Format.h
+++ include/clang/Format/Format.h
@@ -1681,6 +1681,15 @@
   /// \endcode
   bool SortIncludes;
 
+/// SortIncludes Style.
+  enum IncludeHeadersStyle{
+    ///Sorts includes lexicographically.
+    SIS_None,
+    ///Sorts includes according to NetBSD Style Guide.
+    SIS_NetBSD
+  };
+  IncludeHeadersStyle SortIncludesStyle;
+
   /// If ``true``, clang-format will sort using declarations.
   ///
   /// The order of using declarations is defined as follows:
@@ -1995,6 +2004,7 @@
                R.PenaltyBreakTemplateDeclaration &&
            PointerAlignment == R.PointerAlignment &&
            RawStringFormats == R.RawStringFormats &&
+           SortIncludesStyle == R.SortIncludesStyle &&
            SpaceAfterCStyleCast == R.SpaceAfterCStyleCast &&
            SpaceAfterLogicalNot == R.SpaceAfterLogicalNot &&
            SpaceAfterTemplateKeyword == R.SpaceAfterTemplateKeyword &&
@@ -2083,6 +2093,10 @@
 /// http://www.gnu.org/prep/standards/standards.html
 FormatStyle getGNUStyle();
 
+/// Returns a format style complying with NetBSD Coding Standards:
+/// http://cvsweb.netbsd.org/bsdweb.cgi/src/share/misc/style?rev=HEAD&content-type=text/x-cvsweb-markup
+FormatStyle getNetBSDStyle();
+
 /// Returns style indicating formatting should be not applied at all.
 FormatStyle getNoStyle();
 
Index: docs/ClangFormatStyleOptions.rst
===================================================================
--- docs/ClangFormatStyleOptions.rst
+++ docs/ClangFormatStyleOptions.rst
@@ -2001,6 +2001,10 @@
      #include "b.h"                 vs.     #include "a.h"
      #include "a.h"                         #include "b.h"
 
+**SortNetBSDIncludes** (``bool``)
+  If ``true``, clang-format will sort ``#includes`` according to NetBSD style.
+
+  
 **SortUsingDeclarations** (``bool``)
   If ``true``, clang-format will sort using declarations.
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to