r253860 - clang-format: Make moving of the Cursor work properly when sorting #includes.

Daniel Jasper via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 23 00:37:22 PST 2015


Author: djasper
Date: Mon Nov 23 02:36:35 2015
New Revision: 253860

URL: http://llvm.org/viewvc/llvm-project?rev=253860&view=rev
Log:
clang-format: Make moving of the Cursor work properly when sorting #includes.

Modified:
    cfe/trunk/include/clang/Format/Format.h
    cfe/trunk/lib/Format/Format.cpp
    cfe/trunk/tools/clang-format/ClangFormat.cpp
    cfe/trunk/unittests/Format/SortIncludesTest.cpp

Modified: cfe/trunk/include/clang/Format/Format.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Format/Format.h?rev=253860&r1=253859&r2=253860&view=diff
==============================================================================
--- cfe/trunk/include/clang/Format/Format.h (original)
+++ cfe/trunk/include/clang/Format/Format.h Mon Nov 23 02:36:35 2015
@@ -688,7 +688,8 @@ std::string configurationAsText(const Fo
 /// are affected by 'Ranges'.
 tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
                                    ArrayRef<tooling::Range> Ranges,
-                                   StringRef FileName);
+                                   StringRef FileName,
+                                   unsigned *Cursor = nullptr);
 
 /// \brief Reformats the given \p Ranges in the file \p ID.
 ///

Modified: cfe/trunk/lib/Format/Format.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=253860&r1=253859&r2=253860&view=diff
==============================================================================
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Mon Nov 23 02:36:35 2015
@@ -1706,7 +1706,7 @@ static bool affectsRange(ArrayRef<toolin
 static void sortIncludes(const FormatStyle &Style,
                          const SmallVectorImpl<IncludeDirective> &Includes,
                          ArrayRef<tooling::Range> Ranges, StringRef FileName,
-                         tooling::Replacements &Replaces) {
+                         tooling::Replacements &Replaces, unsigned *Cursor) {
   if (!affectsRange(Ranges, Includes.front().Offset,
                     Includes.back().Offset + Includes.back().Text.size()))
     return;
@@ -1730,10 +1730,21 @@ static void sortIncludes(const FormatSty
   if (!OutOfOrder)
     return;
 
-  std::string result = Includes[Indices[0]].Text;
-  for (unsigned i = 1, e = Indices.size(); i != e; ++i) {
-    result += "\n";
-    result += Includes[Indices[i]].Text;
+  std::string result;
+  bool CursorMoved = false;
+  for (unsigned Index : Indices) {
+    if (!result.empty())
+      result += "\n";
+    result += Includes[Index].Text;
+
+    if (Cursor && !CursorMoved) {
+      unsigned Start = Includes[Index].Offset;
+      unsigned End = Start + Includes[Index].Text.size();
+      if (*Cursor >= Start && *Cursor < End) {
+        *Cursor = Includes.front().Offset + result.size() + *Cursor - End;
+        CursorMoved = true;
+      }
+    }
   }
 
   // Sorting #includes shouldn't change their total number of characters.
@@ -1748,7 +1759,7 @@ static void sortIncludes(const FormatSty
 
 tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
                                    ArrayRef<tooling::Range> Ranges,
-                                   StringRef FileName) {
+                                   StringRef FileName, unsigned *Cursor) {
   tooling::Replacements Replaces;
   if (!Style.SortIncludes)
     return Replaces;
@@ -1811,7 +1822,8 @@ tooling::Replacements sortIncludes(const
         LookForMainHeader = false;
         IncludesInBlock.push_back({IncludeName, Line, Prev, Category});
       } else if (!IncludesInBlock.empty()) {
-        sortIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces);
+        sortIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces,
+                     Cursor);
         IncludesInBlock.clear();
       }
       Prev = Pos + 1;
@@ -1821,7 +1833,7 @@ tooling::Replacements sortIncludes(const
     SearchFrom = Pos + 1;
   }
   if (!IncludesInBlock.empty())
-    sortIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces);
+    sortIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces, Cursor);
   return Replaces;
 }
 

Modified: cfe/trunk/tools/clang-format/ClangFormat.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-format/ClangFormat.cpp?rev=253860&r1=253859&r2=253860&view=diff
==============================================================================
--- cfe/trunk/tools/clang-format/ClangFormat.cpp (original)
+++ cfe/trunk/tools/clang-format/ClangFormat.cpp Mon Nov 23 02:36:35 2015
@@ -140,18 +140,18 @@ static bool fillRanges(MemoryBuffer *Cod
                                  InMemoryFileSystem.get());
   if (!LineRanges.empty()) {
     if (!Offsets.empty() || !Lengths.empty()) {
-      llvm::errs() << "error: cannot use -lines with -offset/-length\n";
+      errs() << "error: cannot use -lines with -offset/-length\n";
       return true;
     }
 
     for (unsigned i = 0, e = LineRanges.size(); i < e; ++i) {
       unsigned FromLine, ToLine;
       if (parseLineRange(LineRanges[i], FromLine, ToLine)) {
-        llvm::errs() << "error: invalid <start line>:<end line> pair\n";
+        errs() << "error: invalid <start line>:<end line> pair\n";
         return true;
       }
       if (FromLine > ToLine) {
-        llvm::errs() << "error: start line should be less than end line\n";
+        errs() << "error: start line should be less than end line\n";
         return true;
       }
       SourceLocation Start = Sources.translateLineCol(ID, FromLine, 1);
@@ -169,14 +169,12 @@ static bool fillRanges(MemoryBuffer *Cod
     Offsets.push_back(0);
   if (Offsets.size() != Lengths.size() &&
       !(Offsets.size() == 1 && Lengths.empty())) {
-    llvm::errs()
-        << "error: number of -offset and -length arguments must match.\n";
+    errs() << "error: number of -offset and -length arguments must match.\n";
     return true;
   }
   for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
     if (Offsets[i] >= Code->getBufferSize()) {
-      llvm::errs() << "error: offset " << Offsets[i]
-                   << " is outside the file\n";
+      errs() << "error: offset " << Offsets[i] << " is outside the file\n";
       return true;
     }
     SourceLocation Start =
@@ -184,9 +182,9 @@ static bool fillRanges(MemoryBuffer *Cod
     SourceLocation End;
     if (i < Lengths.size()) {
       if (Offsets[i] + Lengths[i] > Code->getBufferSize()) {
-        llvm::errs() << "error: invalid length " << Lengths[i]
-                     << ", offset + length (" << Offsets[i] + Lengths[i]
-                     << ") is outside the file.\n";
+        errs() << "error: invalid length " << Lengths[i]
+               << ", offset + length (" << Offsets[i] + Lengths[i]
+               << ") is outside the file.\n";
         return true;
       }
       End = Start.getLocWithOffset(Lengths[i]);
@@ -206,26 +204,26 @@ static void outputReplacementXML(StringR
   size_t From = 0;
   size_t Index;
   while ((Index = Text.find_first_of("\n\r<&", From)) != StringRef::npos) {
-    llvm::outs() << Text.substr(From, Index - From);
+    outs() << Text.substr(From, Index - From);
     switch (Text[Index]) {
     case '\n':
-      llvm::outs() << "
";
+      outs() << "
";
       break;
     case '\r':
-      llvm::outs() << "
";
+      outs() << "
";
       break;
     case '<':
-      llvm::outs() << "<";
+      outs() << "<";
       break;
     case '&':
-      llvm::outs() << "&";
+      outs() << "&";
       break;
     default:
       llvm_unreachable("Unexpected character encountered!");
     }
     From = Index + 1;
   }
-  llvm::outs() << Text.substr(From);
+  outs() << Text.substr(From);
 }
 
 static void outputReplacementsXML(const Replacements &Replaces) {
@@ -243,7 +241,7 @@ static bool format(StringRef FileName) {
   ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
       MemoryBuffer::getFileOrSTDIN(FileName);
   if (std::error_code EC = CodeOrErr.getError()) {
-    llvm::errs() << EC.message() << "\n";
+    errs() << EC.message() << "\n";
     return true;
   }
   std::unique_ptr<llvm::MemoryBuffer> Code = std::move(CodeOrErr.get());
@@ -256,28 +254,29 @@ static bool format(StringRef FileName) {
   FormatStyle FormatStyle = getStyle(Style, AssumedFileName, FallbackStyle);
   if (SortIncludes.getNumOccurrences() != 0)
     FormatStyle.SortIncludes = SortIncludes;
-  Replacements Replaces =
-      sortIncludes(FormatStyle, Code->getBuffer(), Ranges, AssumedFileName);
+  unsigned CursorPosition = Cursor;
+  Replacements Replaces = sortIncludes(FormatStyle, Code->getBuffer(), Ranges,
+                                       AssumedFileName, &CursorPosition);
   std::string ChangedCode =
       tooling::applyAllReplacements(Code->getBuffer(), Replaces);
   for (const auto &R : Replaces)
     Ranges.push_back({R.getOffset(), R.getLength()});
 
   bool IncompleteFormat = false;
-  Replaces = tooling::mergeReplacements(
-      Replaces, reformat(FormatStyle, ChangedCode, Ranges, AssumedFileName,
-                         &IncompleteFormat));
+  Replacements FormatChanges = reformat(FormatStyle, ChangedCode, Ranges,
+                                        AssumedFileName, &IncompleteFormat);
+  Replaces = tooling::mergeReplacements(Replaces, FormatChanges);
   if (OutputXML) {
-    llvm::outs() << "<?xml version='1.0'?>\n<replacements "
-                    "xml:space='preserve' incomplete_format='"
-                 << (IncompleteFormat ? "true" : "false") << "'>\n";
+    outs() << "<?xml version='1.0'?>\n<replacements "
+              "xml:space='preserve' incomplete_format='"
+           << (IncompleteFormat ? "true" : "false") << "'>\n";
     if (Cursor.getNumOccurrences() != 0)
-      llvm::outs() << "<cursor>"
-                   << tooling::shiftedCodePosition(Replaces, Cursor)
-                   << "</cursor>\n";
+      outs() << "<cursor>"
+             << tooling::shiftedCodePosition(FormatChanges, CursorPosition)
+             << "</cursor>\n";
 
     outputReplacementsXML(Replaces); 
-    llvm::outs() << "</replacements>\n";
+    outs() << "</replacements>\n";
   } else {
     IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
         new vfs::InMemoryFileSystem);
@@ -292,13 +291,13 @@ static bool format(StringRef FileName) {
     tooling::applyAllReplacements(Replaces, Rewrite);
     if (Inplace) {
       if (FileName == "-")
-        llvm::errs() << "error: cannot use -i when reading from stdin.\n";
+        errs() << "error: cannot use -i when reading from stdin.\n";
       else if (Rewrite.overwriteChangedFiles())
         return true;
     } else {
       if (Cursor.getNumOccurrences() != 0)
         outs() << "{ \"Cursor\": "
-               << tooling::shiftedCodePosition(Replaces, Cursor)
+               << tooling::shiftedCodePosition(FormatChanges, CursorPosition)
                << ", \"IncompleteFormat\": "
                << (IncompleteFormat ? "true" : "false") << " }\n";
       Rewrite.getEditBuffer(ID).write(outs());
@@ -338,7 +337,7 @@ int main(int argc, const char **argv) {
         clang::format::configurationAsText(clang::format::getStyle(
             Style, FileNames.empty() ? AssumeFileName : FileNames[0],
             FallbackStyle));
-    llvm::outs() << Config << "\n";
+    outs() << Config << "\n";
     return 0;
   }
 
@@ -352,8 +351,8 @@ int main(int argc, const char **argv) {
     break;
   default:
     if (!Offsets.empty() || !Lengths.empty() || !LineRanges.empty()) {
-      llvm::errs() << "error: -offset, -length and -lines can only be used for "
-                      "single file.\n";
+      errs() << "error: -offset, -length and -lines can only be used for "
+                "single file.\n";
       return 1;
     }
     for (unsigned i = 0; i < FileNames.size(); ++i)

Modified: cfe/trunk/unittests/Format/SortIncludesTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/SortIncludesTest.cpp?rev=253860&r1=253859&r2=253860&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/SortIncludesTest.cpp (original)
+++ cfe/trunk/unittests/Format/SortIncludesTest.cpp Mon Nov 23 02:36:35 2015
@@ -28,7 +28,14 @@ protected:
                                 reformat(Style, Sorted, Ranges, FileName));
   }
 
+  unsigned newCursor(llvm::StringRef Code, unsigned Cursor) {
+    std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
+    sortIncludes(Style, Code, Ranges, "input.cpp", &Cursor);
+    return Cursor;
+  }
+
   FormatStyle Style = getLLVMStyle();
+
 };
 
 TEST_F(SortIncludesTest, BasicSorting) {
@@ -178,6 +185,19 @@ TEST_F(SortIncludesTest, LeavesMainHeade
                  "some_header.h"));
 }
 
+TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) {
+  std::string Code = "#include <ccc>\n"    // Start of line: 0
+                     "#include <bbbbbb>\n" // Start of line: 15
+                     "#include <a>\n";     // Start of line: 33
+  EXPECT_EQ(31u, newCursor(Code, 0));
+  EXPECT_EQ(13u, newCursor(Code, 15));
+  EXPECT_EQ(0u, newCursor(Code, 33));
+
+  EXPECT_EQ(41u, newCursor(Code, 10));
+  EXPECT_EQ(23u, newCursor(Code, 25));
+  EXPECT_EQ(10u, newCursor(Code, 43));
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang




More information about the cfe-commits mailing list