[PATCH] Clang-format: added -fromline and -toline options to specify ranges in line numbers instead of byte offsets.

Alexander Kornienko alexfh at google.com
Wed Jul 17 00:44:15 PDT 2013


Hi djasper,

The new options should simplify using clang-format in shell scripts
with utilities that operate line numbers (diff, sed, etc.).

http://llvm-reviews.chandlerc.com/D1160

Files:
  test/Format/line-ranges.cpp
  test/Format/multiple-inputs-error.cpp
  tools/clang-format/ClangFormat.cpp

Index: test/Format/line-ranges.cpp
===================================================================
--- /dev/null
+++ test/Format/line-ranges.cpp
@@ -0,0 +1,11 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: clang-format -style=LLVM -fromline=1 -toline=1 -fromline=5 -toline=5 -i %t.cpp
+// RUN: FileCheck -strict-whitespace -input-file=%t.cpp %s
+// CHECK: {{^int\ \*i;$}}
+  int*i;
+
+// CHECK: {{^\ \ int\ \ \*\ \ i;$}}
+  int  *  i; 
+
+// CHECK: {{^\ \ int\ \*i;$}}
+  int   *   i;
Index: test/Format/multiple-inputs-error.cpp
===================================================================
--- test/Format/multiple-inputs-error.cpp
+++ test/Format/multiple-inputs-error.cpp
@@ -1,6 +1,8 @@
 // RUN: cp %s %t-1.cpp
 // RUN: cp %s %t-2.cpp
 // RUN: not clang-format 2>&1 >/dev/null -offset=1 -length=0 %t-1.cpp %t-2.cpp |FileCheck %s
-// CHECK: error: "-offset" and "-length" can only be used for single file.
+// RUN: not clang-format 2>&1 >/dev/null -fromline=1 -toline=1 %t-1.cpp %t-2.cpp |FileCheck %s -check-prefix=CHECK-LINE
+// CHECK: error: "-offset", "-length", "-fromline" and "-toline" can only be used for single file.
+// CHECK-LINE: error: "-offset", "-length", "-fromline" and "-toline" can only be used for single file.
 
 int i ;
Index: tools/clang-format/ClangFormat.cpp
===================================================================
--- tools/clang-format/ClangFormat.cpp
+++ tools/clang-format/ClangFormat.cpp
@@ -53,6 +53,24 @@
                      "of the file.\n"
                      "Can only be used with one input file."),
             cl::cat(ClangFormatCategory));
+static cl::list<unsigned>
+FromLines("fromline",
+          cl::desc("Format a range starting at this line (1-based).\n"
+                   "Multiple ranges can be formatted by specifying\n"
+                   "several -fromline and -toline pairs.\n"
+                   "Can't be used with -offset and -length\n"
+                   "Can only be used with one input file."),
+          cl::cat(ClangFormatCategory));
+static cl::list<unsigned>
+ToLines("toline", cl::desc("Format a range ending at this line.\n"
+                           "Multiple ranges can be formatted by specifying\n"
+                           "several -fromline and -toline pairs.\n"
+                           "When only a single -fromline is specified without\n"
+                           "-length, clang-format will format up to the end\n"
+                           "of the file.\n"
+                           "Can't be used with -offset and -length\n"
+                           "Can only be used with one input file."),
+        cl::cat(ClangFormatCategory));
 static cl::opt<std::string>
     Style("style",
           cl::desc("Coding style, currently supports:\n"
@@ -151,6 +169,56 @@
 }
 
 // Returns true on error.
+static bool getLineStartOffset(unsigned LineNumber, StringRef Contents,
+                               unsigned &Offset) {
+  StringRef::size_type LineOffset = 0;
+  for (unsigned CurrentLine = 1; CurrentLine < LineNumber; ++CurrentLine) {
+    LineOffset = Contents.find('\n', LineOffset);
+    if (LineOffset == StringRef::npos)
+      return true;
+    ++LineOffset;
+  }
+  Offset = LineOffset;
+  return false;
+}
+
+// Returns true on error.
+static bool convertLinesToOffsets(StringRef FileContents) {
+  if (FromLines.size() != ToLines.size() &&
+      !(FromLines.size() == 1 && ToLines.empty())) {
+    llvm::errs() << "error: number of -fromline and -toline must match\n";
+    return true;
+  }
+  if (FromLines.empty())
+    return false;
+
+  if (!Offsets.empty() || !Lengths.empty()) {
+    llvm::errs() << "error: can not use -fromline with -offset/-length\n";
+    return true;
+  }
+
+  for (unsigned i = 0, e = FromLines.size(); i < e; ++i) {
+    unsigned Offset;
+    if (getLineStartOffset(FromLines[i], FileContents, Offset))
+      return true;
+    Offsets.push_back(Offset);
+    if (i < ToLines.size()) {
+      unsigned EndOffset;
+      if (getLineStartOffset(ToLines[i] + 1, FileContents, EndOffset))
+        return true;
+      --EndOffset;
+      if (EndOffset < Offset) {
+        llvm::errs() << "error: -fromline must be less or equal to -toline\n";
+        return true;
+      }
+      Lengths.push_back(EndOffset - Offset);
+    }
+  }
+
+  return false;
+}
+
+// Returns true on error.
 static bool format(std::string FileName) {
   FileManager Files((FileSystemOptions()));
   DiagnosticsEngine Diagnostics(
@@ -164,6 +232,8 @@
   }
   if (Code->getBufferSize() == 0)
     return true; // Empty files are formatted correctly.
+  if (convertLinesToOffsets(Code->getBuffer()))
+    return true;
   FileID ID = createInMemoryFile(FileName, Code.get(), Sources, Files);
   if (Offsets.empty())
     Offsets.push_back(0);
@@ -282,9 +352,10 @@
     Error = clang::format::format(FileNames[0]);
     break;
   default:
-    if (!Offsets.empty() || !Lengths.empty()) {
-      llvm::errs() << "error: \"-offset\" and \"-length\" can only be used for "
-                      "single file.\n";
+    if (!Offsets.empty() || !Lengths.empty() || !FromLines.empty() ||
+        !ToLines.empty()) {
+      llvm::errs() << "error: \"-offset\", \"-length\", \"-fromline\" and "
+                      "\"-toline\" can only be used for single file.\n";
       return 1;
     }
     for (unsigned i = 0; i < FileNames.size(); ++i)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1160.1.patch
Type: text/x-patch
Size: 5388 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130717/96754ee8/attachment.bin>


More information about the cfe-commits mailing list