xref: /llvm-project/clang/unittests/Format/FormatTestJson.cpp (revision 63a565768e8fdbb3260a88f584aa2c11a58fea93)
1 //===- unittest/Format/FormatTestJson.cpp - Formatting tests for Json     -===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "FormatTestUtils.h"
10 #include "clang/Format/Format.h"
11 #include "llvm/Support/Debug.h"
12 #include "gtest/gtest.h"
13 
14 #define DEBUG_TYPE "format-test-json"
15 
16 namespace clang {
17 namespace format {
18 
19 class FormatTestJson : public ::testing::Test {
20 protected:
21   static std::string format(llvm::StringRef Code, unsigned Offset,
22                             unsigned Length, const FormatStyle &Style) {
23     LLVM_DEBUG(llvm::errs() << "---\n");
24     LLVM_DEBUG(llvm::errs() << Code << "\n\n");
25 
26     tooling::Replacements Replaces;
27 
28     // Mock up what ClangFormat.cpp will do for JSON by adding a variable
29     // to trick JSON into being JavaScript
30     if (Style.isJson() && !Style.DisableFormat) {
31       auto Err = Replaces.add(
32           tooling::Replacement(tooling::Replacement("", 0, 0, "x = ")));
33       if (Err) {
34         llvm::errs() << "Bad Json variable insertion\n";
35       }
36     }
37     auto ChangedCode = applyAllReplacements(Code, Replaces);
38     if (!ChangedCode) {
39       llvm::errs() << "Bad Json varibale replacement\n";
40     }
41     StringRef NewCode = *ChangedCode;
42 
43     std::vector<tooling::Range> Ranges(1, tooling::Range(0, NewCode.size()));
44     Replaces = reformat(Style, NewCode, Ranges);
45     auto Result = applyAllReplacements(NewCode, Replaces);
46     EXPECT_TRUE(static_cast<bool>(Result));
47     LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
48     return *Result;
49   }
50 
51   static std::string
52   format(llvm::StringRef Code,
53          const FormatStyle &Style = getLLVMStyle(FormatStyle::LK_Json)) {
54     return format(Code, 0, Code.size(), Style);
55   }
56 
57   static FormatStyle getStyleWithColumns(unsigned ColumnLimit) {
58     FormatStyle Style = getLLVMStyle(FormatStyle::LK_Json);
59     Style.ColumnLimit = ColumnLimit;
60     return Style;
61   }
62 
63   static void verifyFormatStable(llvm::StringRef Code,
64                                  const FormatStyle &Style) {
65     EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable";
66   }
67 
68   static void
69   verifyFormat(llvm::StringRef Code,
70                const FormatStyle &Style = getLLVMStyle(FormatStyle::LK_Json)) {
71     verifyFormatStable(Code, Style);
72     EXPECT_EQ(Code.str(), format(test::messUp(Code), Style));
73   }
74 };
75 
76 TEST_F(FormatTestJson, JsonRecord) {
77   verifyFormat("{}");
78   verifyFormat("{\n"
79                "  \"name\": 1\n"
80                "}");
81   verifyFormat("{\n"
82                "  \"name\": \"Foo\"\n"
83                "}");
84   verifyFormat("{\n"
85                "  \"name\": {\n"
86                "    \"value\": 1\n"
87                "  }\n"
88                "}");
89   verifyFormat("{\n"
90                "  \"name\": {\n"
91                "    \"value\": 1\n"
92                "  },\n"
93                "  \"name\": {\n"
94                "    \"value\": 2\n"
95                "  }\n"
96                "}");
97   verifyFormat("{\n"
98                "  \"name\": {\n"
99                "    \"value\": [\n"
100                "      1,\n"
101                "      2,\n"
102                "    ]\n"
103                "  }\n"
104                "}");
105   verifyFormat("{\n"
106                "  \"name\": {\n"
107                "    \"value\": [\n"
108                "      \"name\": {\n"
109                "        \"value\": 1\n"
110                "      },\n"
111                "      \"name\": {\n"
112                "        \"value\": 2\n"
113                "      }\n"
114                "    ]\n"
115                "  }\n"
116                "}");
117   verifyFormat(R"({
118   "firstName": "John",
119   "lastName": "Smith",
120   "isAlive": true,
121   "age": 27,
122   "address": {
123     "streetAddress": "21 2nd Street",
124     "city": "New York",
125     "state": "NY",
126     "postalCode": "10021-3100"
127   },
128   "phoneNumbers": [
129     {
130       "type": "home",
131       "number": "212 555-1234"
132     },
133     {
134       "type": "office",
135       "number": "646 555-4567"
136     }
137   ],
138   "children": [],
139   "spouse": null
140 })");
141 }
142 
143 TEST_F(FormatTestJson, JsonArray) {
144   verifyFormat("[]");
145   verifyFormat("[\n"
146                "  1\n"
147                "]");
148   verifyFormat("[\n"
149                "  1,\n"
150                "  2\n"
151                "]");
152   verifyFormat("[\n"
153                "  {},\n"
154                "  {}\n"
155                "]");
156   verifyFormat("[\n"
157                "  {\n"
158                "    \"name\": 1\n"
159                "  },\n"
160                "  {}\n"
161                "]");
162 }
163 
164 TEST_F(FormatTestJson, JsonNoStringSplit) {
165   FormatStyle Style = getLLVMStyle(FormatStyle::LK_Json);
166   Style.IndentWidth = 4;
167   verifyFormat(
168       "[\n"
169       "    {\n"
170       "        "
171       "\"naaaaaaaa\": \"foooooooooooooooooooooo oooooooooooooooooooooo\"\n"
172       "    },\n"
173       "    {}\n"
174       "]",
175       Style);
176   verifyFormat("[\n"
177                "    {\n"
178                "        "
179                "\"naaaaaaaa\": "
180                "\"foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
181                "oooooooooooooooooooooooooo\"\n"
182                "    },\n"
183                "    {}\n"
184                "]",
185                Style);
186 
187   Style.ColumnLimit = 80;
188   verifyFormat("[\n"
189                "    {\n"
190                "        "
191                "\"naaaaaaaa\":\n"
192                "            "
193                "\"foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
194                "oooooooooooooooooooooooooo\"\n"
195                "    },\n"
196                "    {}\n"
197                "]",
198                Style);
199 }
200 
201 TEST_F(FormatTestJson, DisableJsonFormat) {
202   FormatStyle Style = getLLVMStyle(FormatStyle::LK_Json);
203   verifyFormatStable("{}", Style);
204   verifyFormatStable("{\n"
205                      "  \"name\": 1\n"
206                      "}",
207                      Style);
208 
209   // Since we have to disable formatting to run this test, we shall refrain from
210   // calling test::messUp lest we change the unformatted code and cannot format
211   // it back to how it started.
212   Style.DisableFormat = true;
213   verifyFormatStable("{}", Style);
214   verifyFormatStable("{\n"
215                      "  \"name\": 1\n"
216                      "}",
217                      Style);
218 }
219 
220 } // namespace format
221 } // end namespace clang
222