Hi klimek,

Also displays a hint to use -header-filter='.*' in case any warnings
are in non-user code. This will help discoverability of this option.

http://reviews.llvm.org/D3621

Files:
  clang-tidy/ClangTidy.cpp
  clang-tidy/ClangTidy.h
  clang-tidy/ClangTidyDiagnosticConsumer.cpp
  clang-tidy/ClangTidyDiagnosticConsumer.h
  clang-tidy/tool/ClangTidyMain.cpp
  test/clang-tidy/file-filter.cpp
  test/clang-tidy/nolint.cpp
  test/clang-tidy/redundant-smartptr-get.cpp
Index: clang-tidy/ClangTidy.cpp
===================================================================
--- clang-tidy/ClangTidy.cpp
+++ clang-tidy/ClangTidy.cpp
@@ -298,10 +298,10 @@
   return Factory.getCheckNames();
 }
 
-void runClangTidy(const ClangTidyOptions &Options,
-                  const tooling::CompilationDatabase &Compilations,
-                  ArrayRef<std::string> Ranges,
-                  SmallVectorImpl<ClangTidyError> *Errors) {
+ClangTidyStats runClangTidy(const ClangTidyOptions &Options,
+                            const tooling::CompilationDatabase &Compilations,
+                            ArrayRef<std::string> Ranges,
+                            SmallVectorImpl<ClangTidyError> *Errors) {
   // FIXME: Ranges are currently full files. Support selecting specific
   // (line-)ranges.
   ClangTool Tool(Compilations, Ranges);
@@ -333,6 +333,7 @@
   };
 
   Tool.run(new ActionFactory(new ClangTidyASTConsumerFactory(Context, Options)));
+  return Context.getStats();
 }
 
 void handleErrors(SmallVectorImpl<ClangTidyError> &Errors, bool Fix) {
Index: clang-tidy/ClangTidy.h
===================================================================
--- clang-tidy/ClangTidy.h
+++ clang-tidy/ClangTidy.h
@@ -121,10 +121,10 @@
 std::vector<std::string> getCheckNames(const ClangTidyOptions &Options);
 
 /// \brief Run a set of clang-tidy checks on a set of files.
-void runClangTidy(const ClangTidyOptions &Options,
-                  const tooling::CompilationDatabase &Compilations,
-                  ArrayRef<std::string> Ranges,
-                  SmallVectorImpl<ClangTidyError> *Errors);
+ClangTidyStats runClangTidy(const ClangTidyOptions &Options,
+                            const tooling::CompilationDatabase &Compilations,
+                            ArrayRef<std::string> Ranges,
+                            SmallVectorImpl<ClangTidyError> *Errors);
 
 // FIXME: This interface will need to be significantly extended to be useful.
 // FIXME: Implement confidence levels for displaying/fixing errors.
Index: clang-tidy/ClangTidyDiagnosticConsumer.cpp
===================================================================
--- clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -41,8 +41,6 @@
                              ArrayRef<CharSourceRange> Ranges,
                              const SourceManager *SM,
                              DiagOrStoredDiag Info) override {
-    if (Level == DiagnosticsEngine::Ignored)
-      return;
     ClangTidyMessage TidyMessage = Loc.isValid()
                                        ? ClangTidyMessage(Message, *SM, Loc)
                                        : ClangTidyMessage(Message);
@@ -111,8 +109,7 @@
   FileOffset = Sources.getFileOffset(Loc);
 }
 
-ClangTidyError::ClangTidyError(StringRef CheckName)
-    : CheckName(CheckName) {}
+ClangTidyError::ClangTidyError(StringRef CheckName) : CheckName(CheckName) {}
 
 ChecksFilter::ChecksFilter(const ClangTidyOptions &Options)
     : EnableChecks(Options.EnableChecksRegex),
@@ -139,8 +136,10 @@
       ++P;
     StringRef RestOfLine(CharacterData, P - CharacterData + 1);
     // FIXME: Handle /\bNOLINT\b(\([^)]*\))?/ as cpplint.py does.
-    if (RestOfLine.find("NOLINT") != StringRef::npos)
+    if (RestOfLine.find("NOLINT") != StringRef::npos) {
       Level = DiagnosticIDs::Ignored;
+      ++Stats.ErrorsIgnoredNOLINT;
+    }
   }
   unsigned ID = DiagEngine->getDiagnosticIDs()->getCustomDiagID(
       Level, (Description + " [" + CheckName + "]").str());
@@ -181,8 +180,18 @@
 }
 
 void ClangTidyDiagnosticConsumer::finalizeLastError() {
-  if (!LastErrorRelatesToUserCode && !Errors.empty())
-    Errors.pop_back();
+  if (!Errors.empty()) {
+    ClangTidyError &Error = Errors.back();
+    if (!Context.getChecksFilter().isCheckEnabled(Error.CheckName)) {
+      ++Context.Stats.ErrorsIgnoredCheckFilter;
+      Errors.pop_back();
+    } else if (!LastErrorRelatesToUserCode) {
+      ++Context.Stats.ErrorsIgnoredNonUserCode;
+      Errors.pop_back();
+    } else {
+      ++Context.Stats.ErrorsDisplayed;
+    }
+  }
   LastErrorRelatesToUserCode = false;
 }
 
@@ -259,10 +268,9 @@
 void ClangTidyDiagnosticConsumer::finish() {
   finalizeLastError();
   std::set<const ClangTidyError*, LessClangTidyError> UniqueErrors;
-  for (const ClangTidyError &Error : Errors) {
-    if (Context.getChecksFilter().isCheckEnabled(Error.CheckName))
-      UniqueErrors.insert(&Error);
-  }
+  for (const ClangTidyError &Error : Errors)
+    UniqueErrors.insert(&Error);
+
   for (const ClangTidyError *Error : UniqueErrors)
     Context.storeError(*Error);
   Errors.clear();
Index: clang-tidy/ClangTidyDiagnosticConsumer.h
===================================================================
--- clang-tidy/ClangTidyDiagnosticConsumer.h
+++ clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -68,6 +68,17 @@
   llvm::Regex DisableChecks;
 };
 
+struct ClangTidyStats {
+  ClangTidyStats()
+      : ErrorsDisplayed(0), ErrorsIgnoredCheckFilter(0), ErrorsIgnoredNOLINT(0),
+        ErrorsIgnoredNonUserCode(0) {}
+
+  unsigned ErrorsDisplayed;
+  unsigned ErrorsIgnoredCheckFilter;
+  unsigned ErrorsIgnoredNOLINT;
+  unsigned ErrorsIgnoredNonUserCode;
+};
+
 /// \brief Every \c ClangTidyCheck reports errors through a \c DiagnosticEngine
 /// provided by this context.
 ///
@@ -108,6 +119,7 @@
 
   ChecksFilter &getChecksFilter() { return Filter; }
   const ClangTidyOptions &getOptions() const { return Options; }
+  const ClangTidyStats &getStats() const { return Stats; }
 
 private:
   friend class ClangTidyDiagnosticConsumer; // Calls storeError().
@@ -119,6 +131,7 @@
   DiagnosticsEngine *DiagEngine;
   ClangTidyOptions Options;
   ChecksFilter Filter;
+  ClangTidyStats Stats;
 
   llvm::DenseMap<unsigned, std::string> CheckNamesByDiagnosticID;
 };
Index: clang-tidy/tool/ClangTidyMain.cpp
===================================================================
--- clang-tidy/tool/ClangTidyMain.cpp
+++ clang-tidy/tool/ClangTidyMain.cpp
@@ -59,6 +59,21 @@
     cl::init(false),
     cl::cat(ClangTidyCategory));
 
+static void printStats(const clang::tidy::ClangTidyStats &Stats) {
+  llvm::errs() << "Warnings: displayed " << Stats.ErrorsDisplayed;
+  if (Stats.ErrorsIgnoredNonUserCode)
+    llvm::errs() << ", in non-user code " << Stats.ErrorsIgnoredNonUserCode;
+  if (Stats.ErrorsIgnoredNOLINT)
+    llvm::errs() << ", suppressed with NOLINT " << Stats.ErrorsIgnoredNOLINT;
+  if (Stats.ErrorsIgnoredCheckFilter)
+    llvm::errs() << ", suppressed with check filters "
+                 << Stats.ErrorsIgnoredCheckFilter;
+  llvm::errs() << "\n";
+  if (Stats.ErrorsIgnoredNonUserCode)
+    llvm::errs() << "Use -header-filter='.*' to display errors from all "
+                    "non-system headers.\n";
+}
+
 int main(int argc, const char **argv) {
   CommonOptionsParser OptionsParser(argc, argv, ClangTidyCategory);
 
@@ -78,10 +93,12 @@
   }
 
   SmallVector<clang::tidy::ClangTidyError, 16> Errors;
-  clang::tidy::runClangTidy(Options, OptionsParser.getCompilations(),
-                            OptionsParser.getSourcePathList(), &Errors);
+  clang::tidy::ClangTidyStats Stats =
+      clang::tidy::runClangTidy(Options, OptionsParser.getCompilations(),
+                                OptionsParser.getSourcePathList(), &Errors);
   clang::tidy::handleErrors(Errors, Fix);
 
+  printStats(Stats);
   return 0;
 }
 
Index: test/clang-tidy/file-filter.cpp
===================================================================
--- test/clang-tidy/file-filter.cpp
+++ test/clang-tidy/file-filter.cpp
@@ -1,6 +1,6 @@
-// RUN: clang-tidy -checks=google-explicit-constructor -disable-checks='' -header-filter='' %s -- -I %S/Inputs/file-filter | FileCheck %s
-// RUN: clang-tidy -checks=google-explicit-constructor -disable-checks='' -header-filter='.*' %s -- -I %S/Inputs/file-filter | FileCheck --check-prefix=CHECK2 %s
-// RUN: clang-tidy -checks=google-explicit-constructor -disable-checks='' -header-filter='header2\.h' %s -- -I %S/Inputs/file-filter | FileCheck --check-prefix=CHECK3 %s
+// RUN: clang-tidy -checks=google-explicit-constructor -disable-checks='' -header-filter='' %s -- -I %S/Inputs/file-filter 2>&1 | FileCheck %s
+// RUN: clang-tidy -checks=google-explicit-constructor -disable-checks='' -header-filter='.*' %s -- -I %S/Inputs/file-filter 2>&1 | FileCheck --check-prefix=CHECK2 %s
+// RUN: clang-tidy -checks=google-explicit-constructor -disable-checks='' -header-filter='header2\.h' %s -- -I %S/Inputs/file-filter 2>&1 | FileCheck --check-prefix=CHECK3 %s
 
 #include "header1.h"
 // CHECK-NOT: warning:
@@ -20,3 +20,10 @@
 // CHECK-NOT: warning:
 // CHECK2-NOT: warning:
 // CHECK3-NOT: warning:
+
+// CHECK: Warnings: displayed 1, in non-user code 2
+// CHECK: Use -header-filter='.*' to display errors from all non-system headers.
+// CHECK2: Warnings: displayed 3
+// CHECK-NOT: Use -header-filter='.*' {{.*}}
+// CHECK3: Warnings: displayed 2, in non-user code 1
+// CHECK3: Use -header-filter='.*' {{.*}}
Index: test/clang-tidy/nolint.cpp
===================================================================
--- test/clang-tidy/nolint.cpp
+++ test/clang-tidy/nolint.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-tidy -checks=google-explicit-constructor -disable-checks='' %s -- | FileCheck %s
+// RUN: clang-tidy -checks=google-explicit-constructor -disable-checks='' %s -- 2>&1 | FileCheck %s
 
 class A { A(int i); };
 // CHECK: :[[@LINE-1]]:11: warning: Single-argument constructors must be explicit [google-explicit-constructor]
@@ -8,3 +8,4 @@
 
 class C { C(int i); }; // NOLINT(we-dont-care-about-categories-yet)
 // CHECK-NOT: :[[@LINE-1]]:11: warning: Single-argument constructors must be explicit [google-explicit-constructor]
+// CHECK: Warnings: displayed 1, suppressed with NOLINT 2
Index: test/clang-tidy/redundant-smartptr-get.cpp
===================================================================
--- test/clang-tidy/redundant-smartptr-get.cpp
+++ test/clang-tidy/redundant-smartptr-get.cpp
@@ -78,7 +78,7 @@
   // CHECK: nullptr != sp->get();
 }
 
-// CHECK-NOT: warning
+// CHECK-NOT: warning:
 
 void Negative() {
   struct NegPtr {
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to