aboutsummaryrefslogtreecommitdiff
path: root/unittests/Format/FormatTest.cpp
diff options
context:
space:
mode:
authorDaniel Jasper <djasper@google.com>2012-12-03 18:12:45 +0000
committerDaniel Jasper <djasper@google.com>2012-12-03 18:12:45 +0000
commitbac016bd3f67ca2f4db1ddc619e611759352b84d (patch)
tree82232dd80409934344e3f0c259da493e5fc35b0e /unittests/Format/FormatTest.cpp
parent189f2e421d06526ea8b4a3dcd9f4a072e10a859c (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.cpp336
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