Add clang-tidy -line-filter option to filter findings by line ranges.

Summary:
This is going to be used for a clang-tidy-diff script to display
warnings in changed lines only. The option uses JSON, as its value is not
intended to be entered manually.

Reviewers: klimek

Reviewed By: klimek

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D3873

llvm-svn: 209450
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
new file mode 100644
index 0000000..fcf66ee
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
@@ -0,0 +1,64 @@
+//===--- ClangTidyOptions.cpp - clang-tidy ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangTidyOptions.h"
+#include "llvm/Support/YAMLTraits.h"
+
+using clang::tidy::FileFilter;
+
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter::LineRange)
+
+namespace llvm {
+namespace yaml {
+
+// Map std::pair<int, int> to a JSON array of size 2.
+template <> struct SequenceTraits<FileFilter::LineRange> {
+  static size_t size(IO &IO, FileFilter::LineRange &Range) {
+    return Range.first == 0 ? 0 : Range.second == 0 ? 1 : 2;
+  }
+  static unsigned &element(IO &IO, FileFilter::LineRange &Range, size_t Index) {
+    if (Index > 1)
+      IO.setError("Too many elements in line range.");
+    return Index == 0 ? Range.first : Range.second;
+  }
+};
+
+template <> struct MappingTraits<FileFilter> {
+  static void mapping(IO &IO, FileFilter &File) {
+    IO.mapRequired("name", File.Name);
+    IO.mapOptional("lines", File.LineRanges);
+  }
+  static StringRef validate(IO &io, FileFilter &File) {
+    if (File.Name.empty())
+      return "No file name specified";
+    for (const FileFilter::LineRange &Range : File.LineRanges) {
+      if (Range.first <= 0 || Range.second <= 0)
+        return "Invalid line range";
+    }
+    return StringRef();
+  }
+};
+
+} // namespace yaml
+} // namespace llvm
+
+namespace clang {
+namespace tidy {
+
+/// \brief Parses -line-filter option and stores it to the \c Options.
+llvm::error_code parseLineFilter(const std::string &LineFilter,
+                                 clang::tidy::ClangTidyOptions &Options) {
+  llvm::yaml::Input Input(LineFilter);
+  Input >> Options.LineFilter;
+  return Input.error();
+}
+
+} // namespace tidy
+} // namespace clang