diff options
author | Daniel Jasper <djasper@google.com> | 2012-12-03 18:12:45 +0000 |
---|---|---|
committer | Daniel Jasper <djasper@google.com> | 2012-12-03 18:12:45 +0000 |
commit | bac016bd3f67ca2f4db1ddc619e611759352b84d (patch) | |
tree | 82232dd80409934344e3f0c259da493e5fc35b0e /unittests/Format/FormatTest.cpp | |
parent | 189f2e421d06526ea8b4a3dcd9f4a072e10a859c (diff) |
Initial version of formatting library.
This formatting library will be used by a stand-alone clang-format tool
and can also be used when writing other refactorings.
Manuel's original design document:
https://docs.google.com/a/google.com/document/d/1gpckL2U_6QuU9YW2L1ABsc4Fcogn5UngKk7fE5dDOoA/edit
The library can already successfully format itself.
Review: http://llvm-reviews.chandlerc.com/D80
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@169137 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests/Format/FormatTest.cpp')
-rw-r--r-- | unittests/Format/FormatTest.cpp | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp new file mode 100644 index 0000000000..9929eebd3b --- /dev/null +++ b/unittests/Format/FormatTest.cpp @@ -0,0 +1,336 @@ +//===- unittest/Format/FormatTest.cpp - Formatting unit tests -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "../Tooling/RewriterTestContext.h" +#include "clang/Lex/Lexer.h" +#include "clang/Format/Format.h" +#include "gtest/gtest.h" + +namespace clang { +namespace format { + +class FormatTest : public ::testing::Test { +protected: + std::string format(llvm::StringRef Code, unsigned Offset, unsigned Length, + const FormatStyle &Style) { + RewriterTestContext Context; + FileID ID = Context.createInMemoryFile("input.cc", Code); + SourceLocation Start = + Context.Sources.getLocForStartOfFile(ID).getLocWithOffset(Offset); + std::vector<CharSourceRange> Ranges( + 1, + CharSourceRange::getCharRange(Start, Start.getLocWithOffset(Length))); + LangOptions LangOpts; + LangOpts.CPlusPlus = 1; + Lexer Lex(ID, Context.Sources.getBuffer(ID), Context.Sources, LangOpts); + tooling::Replacements Replace = + reformat(Style, Lex, Context.Sources, Ranges); + EXPECT_TRUE(applyAllReplacements(Replace, Context.Rewrite)); + return Context.getRewrittenText(ID); + } + + std::string format(llvm::StringRef Code, + const FormatStyle &Style = getLLVMStyle()) { + return format(Code, 0, Code.size(), Style); + } + + void verifyFormat(llvm::StringRef Code) { + std::string WithoutFormat(Code.str()); + for (unsigned i = 0, e = WithoutFormat.size(); i != e; ++i) { + if (WithoutFormat[i] == '\n') + WithoutFormat[i] = ' '; + } + EXPECT_EQ(Code.str(), format(WithoutFormat)); + } + + void verifyGoogleFormat(llvm::StringRef Code) { + std::string WithoutFormat(Code.str()); + for (unsigned i = 0, e = WithoutFormat.size(); i != e; ++i) { + if (WithoutFormat[i] == '\n') + WithoutFormat[i] = ' '; + } + EXPECT_EQ(Code.str(), format(WithoutFormat, getGoogleStyle())); + } +}; + +TEST_F(FormatTest, DoesNotChangeCorrectlyFormatedCode) { + EXPECT_EQ(";", format(";")); +} + +TEST_F(FormatTest, FormatsGlobalStatementsAt0) { + EXPECT_EQ("int i;", format(" int i;")); + EXPECT_EQ("\nint i;", format(" \n\t \r int i;")); + EXPECT_EQ("int i;\nint j;", format(" int i; int j;")); + EXPECT_EQ("int i;\nint j;", format(" int i;\n int j;")); +} + +TEST_F(FormatTest, FormatsUnwrappedLinesAtFirstFormat) { + EXPECT_EQ("int i;", format("int\ni;")); +} + +TEST_F(FormatTest, FormatsNestedBlockStatements) { + EXPECT_EQ("{\n {\n {\n }\n }\n}", format("{{{}}}")); +} + +TEST_F(FormatTest, FormatsForLoop) { + verifyFormat( + "for (int VeryVeryLongLoopVariable = 0; VeryVeryLongLoopVariable < 10;\n" + " ++VeryVeryLongLoopVariable);"); +} + +TEST_F(FormatTest, FormatsWhileLoop) { + verifyFormat("while (true) {\n}"); +} + +TEST_F(FormatTest, FormatsNestedCall) { + verifyFormat("Method(f1, f2(f3));"); + verifyFormat("Method(f1(f2, f3()));"); +} + +TEST_F(FormatTest, FormatsAwesomeMethodCall) { + verifyFormat( + "SomeLongMethodName(SomeReallyLongMethod(CallOtherReallyLongMethod(\n" + " parameter, parameter, parameter)), SecondLongCall(parameter));"); +} + +TEST_F(FormatTest, FormatsFunctionDefinition) { + verifyFormat("void f(int a, int b, int c, int d, int e, int f, int g," + " int h, int j, int f,\n" + " int c, int ddddddddddddd) {\n" + "}"); +} + +TEST_F(FormatTest, FormatIfWithoutCompountStatement) { + verifyFormat("if (true)\n f();\ng();"); + verifyFormat("if (a)\n if (b)\n if (c)\n g();\nh();"); + verifyFormat("if (a)\n if (b) {\n f();\n }\ng();"); +} + +TEST_F(FormatTest, ParseIfThenElse) { + verifyFormat("if (true)\n" + " if (true)\n" + " if (true)\n" + " f();\n" + " else\n" + " g();\n" + " else\n" + " h();\n" + "else\n" + " i();"); + verifyFormat("if (true)\n" + " if (true)\n" + " if (true) {\n" + " if (true)\n" + " f();\n" + " } else {\n" + " g();\n" + " }\n" + " else\n" + " h();\n" + "else {\n" + " i();\n" + "}"); +} + +TEST_F(FormatTest, UnderstandsSingleLineComments) { + EXPECT_EQ("// line 1\n// line 2\nvoid f() {\n}\n", + format("// line 1\n// line 2\nvoid f() {}\n")); + + EXPECT_EQ("void f() {\n // Doesn't do anything\n}", + format("void f() {\n// Doesn't do anything\n}")); + + EXPECT_EQ("int i // This is a fancy variable\n = 5;", + format("int i // This is a fancy variable\n= 5;")); + + verifyFormat("f(/*test=*/ true);"); +} + +TEST_F(FormatTest, DoesNotBreakSemiAfterClassDecl) { + verifyFormat("class A {\n};"); +} + +TEST_F(FormatTest, BreaksAsHighAsPossible) { + verifyFormat( + "if ((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && aaaaaaaaaaaaaaaaaaaaaaaaaa) ||\n" + " (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb && bbbbbbbbbbbbbbbbbbbbbbbbbb))\n" + " f();"); +} + +TEST_F(FormatTest, ElseIf) { + verifyFormat("if (a) {\n" + "} else if (b) {\n" + "}"); + verifyFormat("if (a)\n" + " f();\n" + "else if (b)\n" + " g();\n" + "else\n" + " h();"); +} + +TEST_F(FormatTest, UnderstandsAccessSpecifiers) { + verifyFormat("class A {\n" + "public:\n" + "protected:\n" + "private:\n" + " void f() {\n" + " }\n" + "};"); + verifyGoogleFormat("class A {\n" + " public:\n" + " protected:\n" + " private:\n" + " void f() {\n" + " }\n" + "};"); +} + +TEST_F(FormatTest, SwitchStatement) { + verifyFormat("switch (x) {\n" + "case 1:\n" + " f();\n" + " break;\n" + "case kFoo:\n" + "case ns::kBar:\n" + "case kBaz:\n" + " break;\n" + "default:\n" + " g();\n" + " break;\n" + "}"); + verifyFormat("switch (x) {\n" + "case 1: {\n" + " f();\n" + " break;\n" + "}\n" + "}"); + verifyFormat("switch (test)\n" + " ;"); +} + +TEST_F(FormatTest, Labels) { + verifyFormat("void f() {\n" + " some_code();\n" + "test_label:\n" + " some_other_code();\n" + " {\n" + " some_more_code();\n" + " another_label:\n" + " some_more_code();\n" + " }\n" + "}"); + verifyFormat("some_code();\n" + "test_label:\n" + "some_other_code();"); +} + +TEST_F(FormatTest, DerivedClass) { + verifyFormat("class A : public B {\n" + "};"); +} + +TEST_F(FormatTest, DoWhile) { + verifyFormat("do {\n" + " do_something();\n" + "} while (something());"); + verifyFormat("do\n" + " do_something();\n" + "while (something());"); +} + +TEST_F(FormatTest, BreaksDesireably) { + verifyFormat("if (aaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaa) ||\n" + " aaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaa) ||\n" + " aaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaa)) {\n};"); + + verifyFormat( + "aaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n}"); + + verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa));"); +} + +TEST_F(FormatTest, AlignsStringLiterals) { + verifyFormat("loooooooooooooooooooooooooongFunction(\"short literal \"\n" + " \"short literal\");"); + verifyFormat( + "looooooooooooooooooooooooongFunction(\n" + " \"short literal\"\n" + " \"looooooooooooooooooooooooooooooooooooooooooooooooong literal\");"); +} + +TEST_F(FormatTest, UnderstandsEquals) { + verifyFormat( + "aaaaaaaaaaaaaaaaa =\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;"); + verifyFormat( + "if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa =\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n" + "}"); + verifyFormat( + "if (a) {\n" + "} else if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa =\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n" + "}"); + + verifyFormat("if (int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa =\n" + " 100000000 + 100000000) {\n}"); +} + +TEST_F(FormatTest, UnderstandsTemplateParameters) { + verifyFormat("A<int> a;"); + verifyFormat("A<A<A<int> > > a;"); + verifyFormat("A<A<A<int, 2>, 3>, 4> a;"); + verifyFormat("bool x = a < 1 || 2 > a;"); + verifyFormat("bool x = 5 < f<int>();"); + verifyFormat("bool x = f<int>() > 5;"); + verifyFormat("bool x = 5 < a<int>::x;"); + verifyFormat("bool x = a < 4 ? a > 2 : false;"); + verifyFormat("bool x = f() ? a < 2 : a > 2;"); + + verifyGoogleFormat("A<A<int>> a;"); + verifyGoogleFormat("A<A<A<int>>> a;"); + verifyGoogleFormat("A<A<A<A<int>>>> a;"); + + verifyFormat("test >> a >> b;"); + verifyFormat("test << a >> b;"); + + verifyFormat("f<int>();"); + verifyFormat("template <typename T> void f() {\n}"); +} + +TEST_F(FormatTest, UndestandsUnaryOperators) { + verifyFormat("int a = -2;"); +} + +TEST_F(FormatTest, UndestandsOverloadedOperators) { + verifyFormat("bool operator<() {\n}"); +} + +TEST_F(FormatTest, UnderstandsUsesOfStar) { + verifyFormat("int *f(int *a) {\n}"); + verifyFormat("f(a, *a);"); + verifyFormat("f(*a);"); + verifyFormat("int a = b * 10;"); + verifyFormat("int a = 10 * b;"); + // verifyFormat("int a = b * c;"); + verifyFormat("int a = *b;"); + // verifyFormat("int a = *b * c;"); + // verifyFormat("int a = b * *c;"); +} + +//TEST_F(FormatTest, IncorrectDerivedClass) { +// verifyFormat("public B {\n" +// "};"); +//} + +} // end namespace tooling +} // end namespace clang |