Hi klimek, djasper,

Added tests for clang-format diagnostics. Added DiagnosticConsumer
argument to clang::format::reformat().

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

Files:
  include/clang/Format/Format.h
  lib/Format/Format.cpp
  unittests/Format/FormatTest.cpp
Index: include/clang/Format/Format.h
===================================================================
--- include/clang/Format/Format.h
+++ include/clang/Format/Format.h
@@ -25,6 +25,7 @@
 
 class Lexer;
 class SourceManager;
+class DiagnosticConsumer;
 
 namespace format {
 
@@ -57,7 +58,7 @@
   unsigned SpacesBeforeTrailingComments;
 
   /// \brief If the constructor initializers don't fit on a line, put each
-  /// initializer on its own line. 
+  /// initializer on its own line.
   bool ConstructorInitializerAllOnOneLineOrOnePerLine;
 
   /// \brief Add a space in front of an Objective-C protocol list, i.e. use
@@ -84,11 +85,15 @@
 /// everything that might influence its formatting or might be influenced by its
 /// formatting.
 ///
+/// \param DiagClient A custom DiagnosticConsumer. Can be 0, in this case
+/// diagnostic is output to llvm::errs().
+///
 /// Returns the \c Replacements necessary to make all \p Ranges comply with
 /// \p Style.
 tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
                                SourceManager &SourceMgr,
-                               std::vector<CharSourceRange> Ranges);
+                               std::vector<CharSourceRange> Ranges,
+                               DiagnosticConsumer *DiagClient = 0);
 
 /// \brief Returns the \c LangOpts that the formatter expects you to set.
 LangOptions getFormattingLangOpts();
Index: lib/Format/Format.cpp
===================================================================
--- lib/Format/Format.cpp
+++ lib/Format/Format.cpp
@@ -1261,7 +1261,7 @@
 
 class Formatter : public UnwrappedLineConsumer {
 public:
-  Formatter(clang::DiagnosticsEngine &Diag, const FormatStyle &Style,
+  Formatter(DiagnosticsEngine &Diag, const FormatStyle &Style,
             Lexer &Lex, SourceManager &SourceMgr,
             const std::vector<CharSourceRange> &Ranges)
       : Diag(Diag), Style(Style), Lex(Lex), SourceMgr(SourceMgr),
@@ -1378,7 +1378,7 @@
     return Indent;
   }
 
-  clang::DiagnosticsEngine &Diag;
+  DiagnosticsEngine &Diag;
   FormatStyle Style;
   Lexer &Lex;
   SourceManager &SourceMgr;
@@ -1390,13 +1390,18 @@
 
 tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
                                SourceManager &SourceMgr,
-                               std::vector<CharSourceRange> Ranges) {
+                               std::vector<CharSourceRange> Ranges,
+                               DiagnosticConsumer *DiagClient) {
   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
-  TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), &*DiagOpts);
-  DiagnosticPrinter.BeginSourceFile(Lex.getLangOpts(), Lex.getPP());
+  OwningPtr<DiagnosticConsumer> DiagPrinter;
+  if (DiagClient == 0) {
+    DiagPrinter.reset(new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts));
+    DiagPrinter->BeginSourceFile(Lex.getLangOpts(), Lex.getPP());
+    DiagClient = DiagPrinter.get();
+  }
   DiagnosticsEngine Diagnostics(
       llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
-      &DiagnosticPrinter, false);
+      DiagClient, false);
   Diagnostics.setSourceManager(&SourceMgr);
   Formatter formatter(Diagnostics, Style, Lex, SourceMgr, Ranges);
   return formatter.format();
Index: unittests/Format/FormatTest.cpp
===================================================================
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -8,16 +8,29 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Format/Format.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
 #include "../Tooling/RewriterTestContext.h"
 #include "clang/Lex/Lexer.h"
 #include "gtest/gtest.h"
+#include "llvm/ADT/ArrayRef.h"
 
 namespace clang {
 namespace format {
 
+struct ExpectedDiagMessage {
+  DiagnosticsEngine::Level Level;
+  int Line;
+  std::string Text;
+  bool Seen;
+};
+
+typedef llvm::MutableArrayRef<ExpectedDiagMessage> ExpectedDiagnostics;
+static const ExpectedDiagnostics NoDiagnostics;
+
 class FormatTest : public ::testing::Test {
 protected:
   std::string format(llvm::StringRef Code, unsigned Offset, unsigned Length,
+                     ExpectedDiagnostics ExpectedDiags,
                      const FormatStyle &Style) {
     RewriterTestContext Context;
     FileID ID = Context.createInMemoryFile("input.cc", Code);
@@ -28,15 +41,22 @@
         CharSourceRange::getCharRange(Start, Start.getLocWithOffset(Length)));
     Lexer Lex(ID, Context.Sources.getBuffer(ID), Context.Sources,
               getFormattingLangOpts());
+    TextDiagnosticBuffer DiagBuf;
     tooling::Replacements Replace = reformat(Style, Lex, Context.Sources,
-                                             Ranges);
+                                             Ranges, &DiagBuf);
+    checkDiagnostics(Context.Sources, DiagBuf, ExpectedDiags);
     EXPECT_TRUE(applyAllReplacements(Replace, Context.Rewrite));
     return Context.getRewrittenText(ID);
   }
 
+  std::string format(llvm::StringRef Code, ExpectedDiagnostics ExpectedDiags,
+                     const FormatStyle &Style = getLLVMStyle()) {
+    return format(Code, 0, Code.size(), ExpectedDiags, Style);
+  }
+
   std::string format(llvm::StringRef Code,
                      const FormatStyle &Style = getLLVMStyle()) {
-    return format(Code, 0, Code.size(), Style);
+    return format(Code, 0, Code.size(), NoDiagnostics, Style);
   }
 
   std::string messUp(llvm::StringRef Code) {
@@ -77,13 +97,60 @@
     return Style;
   }
 
+  void verifyFormat(llvm::StringRef Code, ExpectedDiagnostics ExpectedDiags,
+                    const FormatStyle &Style = getLLVMStyle()) {
+    EXPECT_EQ(Code.str(), format(messUp(Code), ExpectedDiags, Style));
+  }
+
   void verifyFormat(llvm::StringRef Code,
                     const FormatStyle &Style = getLLVMStyle()) {
-    EXPECT_EQ(Code.str(), format(messUp(Code), Style));
+    EXPECT_EQ(Code.str(), format(messUp(Code), NoDiagnostics, Style));
+  }
+
+  void verifyGoogleFormat(llvm::StringRef Code,
+                          ExpectedDiagnostics ExpectedDiags = NoDiagnostics) {
+    verifyFormat(Code, ExpectedDiags, getGoogleStyle());
+  }
+
+private:
+  template <typename Iter>
+  void markMessages(DiagnosticsEngine::Level Level, Iter Begin, Iter End,
+                    ExpectedDiagnostics ExpectedDiags,
+                    SourceManager &SourceMgr) {
+    const char *Levels[] = { "ignored", "note", "warning", "error", "fatal" };
+    for (Iter I = Begin; I != End; ++I) {
+      bool Found = false;
+      int Line = SourceMgr.getSpellingLineNumber(I->first);
+      for (size_t i = 0; i < ExpectedDiags.size(); ++i) {
+        ExpectedDiagMessage &Msg = ExpectedDiags[i];
+        if (!Msg.Seen && Msg.Level == Level && Line == Msg.Line &&
+            I->second.find(Msg.Text) != std::string::npos) {
+          Msg.Seen = true;
+          Found = true;
+          break;
+        }
+      }
+      EXPECT_TRUE(Found) << "Unexpected " << Levels[Level] << " on line "
+                         << Line << ": " << I->second;
+    }
+    for (size_t i = 0; i < ExpectedDiags.size(); ++i) {
+      ExpectedDiagMessage &Msg = ExpectedDiags[i];
+      if (Msg.Level == Level) {
+        EXPECT_TRUE(Msg.Seen) << "Expected " << Levels[Level]
+                              << " not found on line " << Msg.Line << ": "
+                              << Msg.Text;
+      }
+    }
   }
 
-  void verifyGoogleFormat(llvm::StringRef Code) {
-    verifyFormat(Code, getGoogleStyle());
+  void checkDiagnostics(SourceManager &SourceMgr, TextDiagnosticBuffer &DiagBuf,
+                        ExpectedDiagnostics ExpectedDiags) {
+    markMessages(DiagnosticsEngine::Error, DiagBuf.err_begin(),
+                 DiagBuf.err_end(), ExpectedDiags, SourceMgr);
+    markMessages(DiagnosticsEngine::Warning, DiagBuf.warn_begin(),
+                 DiagBuf.warn_end(), ExpectedDiags, SourceMgr);
+    markMessages(DiagnosticsEngine::Note, DiagBuf.note_begin(),
+                 DiagBuf.note_end(), ExpectedDiags, SourceMgr);
   }
 };
 
@@ -514,8 +581,8 @@
 }
 
 TEST_F(FormatTest, LayoutSingleUnwrappedLineInMacro) {
-  EXPECT_EQ("# define A\\\n  b;",
-            format("# define A b;", 11, 2, getLLVMStyleWithColumns(11)));
+  EXPECT_EQ("# define A\\\n  b;", format("# define A b;", 11, 2, NoDiagnostics,
+                                         getLLVMStyleWithColumns(11)));
 }
 
 TEST_F(FormatTest, MacroDefinitionInsideStatement) {
@@ -552,8 +619,13 @@
 TEST_F(FormatTest, FormatUnbalancedStructuralElements) {
   EXPECT_EQ("#define A \\\n  {       \\\n    {\nint i;",
             format("#define A { {\nint i;", getLLVMStyleWithColumns(11)));
+  ExpectedDiagMessage ExpectedDiags[] = {
+    { DiagnosticsEngine::Error, 1, "unexpected '}'", false},
+    { DiagnosticsEngine::Error, 1, "unexpected '}'", false}
+  };
   EXPECT_EQ("#define A \\\n  }       \\\n  }\nint i;",
-            format("#define A } }\nint i;", getLLVMStyleWithColumns(11)));
+            format("#define A } }\nint i;", ExpectedDiags,
+                   getLLVMStyleWithColumns(11)));
 }
 
 TEST_F(FormatTest, EscapedNewlineAtStartOfTokenInMacroDefinition) {
@@ -1135,18 +1207,22 @@
   EXPECT_EQ("{\n{}\n", format("{\n{\n}\n"));
   EXPECT_EQ("{\n  {}\n", format("{\n  {\n}\n"));
   EXPECT_EQ("{\n  {}\n", format("{\n  {\n  }\n"));
-  EXPECT_EQ("{\n  {}\n  }\n}\n", format("{\n  {\n    }\n  }\n}\n"));
 
-  FormatStyle Style = getLLVMStyle();
-  Style.ColumnLimit = 10;
+  ExpectedDiagMessage ExpectedDiags[] = {
+    { DiagnosticsEngine::Error, 5, "unexpected '}'", false}
+  };
+
+  EXPECT_EQ("{\n  {}\n  }\n}\n",
+            format("{\n  {\n    }\n  }\n}\n", ExpectedDiags));
+
   EXPECT_EQ("{\n"
             "    {\n"
             " breakme(\n"
             "     qwe);\n"
             "}\n", format("{\n"
                           "    {\n"
                           " breakme(qwe);\n"
-                          "}\n", Style));
+                          "}\n", getLLVMStyleWithColumns(10)));
 
 }
 
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to