1//===- unittest/Format/FormatTestProto.cpp --------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "FormatTestUtils.h" 11#include "clang/Format/Format.h" 12#include "llvm/Support/Debug.h" 13#include "gtest/gtest.h" 14 15#define DEBUG_TYPE "format-test" 16 17namespace clang { 18namespace format { 19 20class FormatTestProto : public ::testing::Test { 21protected: 22 static std::string format(llvm::StringRef Code, unsigned Offset, 23 unsigned Length, const FormatStyle &Style) { 24 DEBUG(llvm::errs() << "---\n"); 25 DEBUG(llvm::errs() << Code << "\n\n"); 26 std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length)); 27 tooling::Replacements Replaces = reformat(Style, Code, Ranges); 28 auto Result = applyAllReplacements(Code, Replaces); 29 EXPECT_TRUE(static_cast<bool>(Result)); 30 DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); 31 return *Result; 32 } 33 34 static std::string format(llvm::StringRef Code) { 35 FormatStyle Style = getGoogleStyle(FormatStyle::LK_Proto); 36 Style.ColumnLimit = 60; // To make writing tests easier. 37 return format(Code, 0, Code.size(), Style); 38 } 39 40 static void verifyFormat(llvm::StringRef Code) { 41 EXPECT_EQ(Code.str(), format(test::messUp(Code))); 42 } 43}; 44 45TEST_F(FormatTestProto, FormatsMessages) { 46 verifyFormat("message SomeMessage {\n" 47 " required int32 field1 = 1;\n" 48 "}"); 49 verifyFormat("message SomeMessage {\n" 50 " required .absolute.Reference field1 = 1;\n" 51 "}"); 52 verifyFormat("message SomeMessage {\n" 53 " required int32 field1 = 1;\n" 54 " optional string field2 = 2 [default = \"2\"]\n" 55 "}"); 56 57 verifyFormat("message SomeMessage {\n" 58 " optional really.really.long.qualified.type.aaa.aaaaaaa\n" 59 " fiiiiiiiiiiiiiiiiiiiiiiiiield = 1;\n" 60 " optional\n" 61 " really.really.long.qualified.type.aaa.aaaaaaa.aaaaaaaa\n" 62 " another_fiiiiiiiiiiiiiiiiiiiiield = 2;\n" 63 "}"); 64} 65 66TEST_F(FormatTestProto, KeywordsInOtherLanguages) { 67 verifyFormat("optional string operator = 1;"); 68} 69 70TEST_F(FormatTestProto, FormatsEnums) { 71 verifyFormat("enum Type {\n" 72 " UNKNOWN = 0;\n" 73 " TYPE_A = 1;\n" 74 " TYPE_B = 2;\n" 75 "};"); 76 verifyFormat("enum Type {\n" 77 " UNKNOWN = 0 [(some_options) = {a: aa, b: bb}];\n" 78 "};"); 79 verifyFormat("enum Type {\n" 80 " UNKNOWN = 0 [(some_options) = {\n" 81 " a: aa, // wrap\n" 82 " b: bb\n" 83 " }];\n" 84 "};"); 85} 86 87TEST_F(FormatTestProto, UnderstandsReturns) { 88 verifyFormat("rpc Search(SearchRequest) returns (SearchResponse);"); 89} 90 91TEST_F(FormatTestProto, MessageFieldAttributes) { 92 verifyFormat("optional string test = 1 [default = \"test\"];"); 93 verifyFormat("optional bool a = 1 [default = true, deprecated = true];"); 94 verifyFormat("optional LongMessageType long_proto_field = 1 [\n" 95 " default = REALLY_REALLY_LONG_CONSTANT_VALUE,\n" 96 " deprecated = true\n" 97 "];"); 98 verifyFormat("optional LongMessageType long_proto_field = 1\n" 99 " [default = REALLY_REALLY_LONG_CONSTANT_VALUE];"); 100 verifyFormat("repeated double value = 1\n" 101 " [(aaaaaaa.aaaaaaaaa) = {aaaaaaaaaaaaaaaaa: AAAAAAAA}];"); 102 verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n" 103 " aaaaaaaaaaaaaaaa: AAAAAAAAAA,\n" 104 " bbbbbbbbbbbbbbbb: BBBBBBBBBB\n" 105 "}];"); 106 verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n" 107 " aaaaaaaaaaaaaaaa: AAAAAAAAAA\n" 108 " bbbbbbbbbbbbbbbb: BBBBBBBBBB\n" 109 "}];"); 110 verifyFormat("repeated double value = 1 [\n" 111 " (aaaaaaa.aaaaaaaaa) = {\n" 112 " aaaaaaaaaaaaaaaa: AAAAAAAAAA\n" 113 " bbbbbbbbbbbbbbbb: BBBBBBBBBB\n" 114 " },\n" 115 " (bbbbbbb.bbbbbbbbb) = {\n" 116 " aaaaaaaaaaaaaaaa: AAAAAAAAAA\n" 117 " bbbbbbbbbbbbbbbb: BBBBBBBBBB\n" 118 " }\n" 119 "];"); 120 verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n" 121 " type: \"AAAAAAAAAA\"\n" 122 " is: \"AAAAAAAAAA\"\n" 123 " or: \"BBBBBBBBBB\"\n" 124 "}];"); 125 verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n" 126 " aaaaaaaaaaaaaaaa: AAAAAAAAAA,\n" 127 " bbbbbbb: BBBB,\n" 128 " bbbb: BBB\n" 129 "}];"); 130 verifyFormat("optional AAA aaa = 1 [\n" 131 " foo = {\n" 132 " key: 'a' //\n" 133 " },\n" 134 " bar = {\n" 135 " key: 'a' //\n" 136 " }\n" 137 "];"); 138} 139 140TEST_F(FormatTestProto, DoesntWrapFileOptions) { 141 EXPECT_EQ( 142 "option java_package = " 143 "\"some.really.long.package.that.exceeds.the.column.limit\";", 144 format("option java_package = " 145 "\"some.really.long.package.that.exceeds.the.column.limit\";")); 146} 147 148TEST_F(FormatTestProto, FormatsOptions) { 149 verifyFormat("option (MyProto.options) = {\n" 150 " field_a: OK\n" 151 " field_b: \"OK\"\n" 152 " field_c: \"OK\"\n" 153 " msg_field: {field_d: 123}\n" 154 "};"); 155 verifyFormat("option (MyProto.options) = {\n" 156 " field_a: OK\n" 157 " field_b: \"OK\"\n" 158 " field_c: \"OK\"\n" 159 " msg_field: {field_d: 123 field_e: OK}\n" 160 "};"); 161 verifyFormat("option (MyProto.options) = {\n" 162 " field_a: OK // Comment\n" 163 " field_b: \"OK\"\n" 164 " field_c: \"OK\"\n" 165 " msg_field: {field_d: 123}\n" 166 "};"); 167 verifyFormat("option (MyProto.options) = {\n" 168 " field_c: \"OK\"\n" 169 " msg_field{field_d: 123}\n" 170 "};"); 171 172 // Support syntax with <> instead of {}. 173 verifyFormat("option (MyProto.options) = {\n" 174 " field_c: \"OK\",\n" 175 " msg_field: <field_d: 123>\n" 176 "};"); 177} 178 179TEST_F(FormatTestProto, FormatsService) { 180 verifyFormat("service SearchService {\n" 181 " rpc Search(SearchRequest) returns (SearchResponse) {\n" 182 " option foo = true;\n" 183 " }\n" 184 "};"); 185} 186 187TEST_F(FormatTestProto, ExtendingMessage) { 188 verifyFormat("extend .foo.Bar {\n" 189 "}"); 190} 191 192TEST_F(FormatTestProto, FormatsImports) { 193 verifyFormat("import \"a.proto\";\n" 194 "import \"b.proto\";\n" 195 "// comment\n" 196 "message A {\n" 197 "}"); 198 199 verifyFormat("import public \"a.proto\";\n" 200 "import \"b.proto\";\n" 201 "// comment\n" 202 "message A {\n" 203 "}"); 204 205 // Missing semicolons should not confuse clang-format. 206 verifyFormat("import \"a.proto\"\n" 207 "import \"b.proto\"\n" 208 "// comment\n" 209 "message A {\n" 210 "}"); 211} 212 213} // end namespace tooling 214} // end namespace clang 215