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