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
16namespace clang {
17namespace format {
18
19class FormatTestJson : public ::testing::Test {
20protected:
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 R: tooling::Replacement(tooling::Replacement("", 0, 0, "x = ")));
33 if (Err)
34 llvm::errs() << "Bad Json variable insertion\n";
35 }
36 auto ChangedCode = applyAllReplacements(Code, Replaces);
37 if (!ChangedCode)
38 llvm::errs() << "Bad Json varibale replacement\n";
39 StringRef NewCode = *ChangedCode;
40
41 std::vector<tooling::Range> Ranges(1, tooling::Range(0, NewCode.size()));
42 Replaces = reformat(Style, Code: NewCode, Ranges);
43 auto Result = applyAllReplacements(Code: NewCode, Replaces);
44 EXPECT_TRUE(static_cast<bool>(Result));
45 LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
46 return *Result;
47 }
48
49 static std::string
50 format(llvm::StringRef Code,
51 const FormatStyle &Style = getLLVMStyle(Language: FormatStyle::LK_Json)) {
52 return format(Code, Offset: 0, Length: Code.size(), Style);
53 }
54
55 static FormatStyle getStyleWithColumns(unsigned ColumnLimit) {
56 FormatStyle Style = getLLVMStyle(Language: FormatStyle::LK_Json);
57 Style.ColumnLimit = ColumnLimit;
58 return Style;
59 }
60
61 static void verifyFormatStable(llvm::StringRef Code,
62 const FormatStyle &Style) {
63 EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable";
64 }
65
66 static void
67 verifyFormat(llvm::StringRef Code,
68 const FormatStyle &Style = getLLVMStyle(Language: FormatStyle::LK_Json)) {
69 verifyFormatStable(Code, Style);
70 EXPECT_EQ(Code.str(), format(test::messUp(Code), Style));
71 }
72};
73
74TEST_F(FormatTestJson, JsonRecord) {
75 verifyFormat(Code: "{}");
76 verifyFormat(Code: "{\n"
77 " \"name\": 1\n"
78 "}");
79 verifyFormat(Code: "{\n"
80 " \"name\": \"Foo\"\n"
81 "}");
82 verifyFormat(Code: "{\n"
83 " \"name\": {\n"
84 " \"value\": 1\n"
85 " }\n"
86 "}");
87 verifyFormat(Code: "{\n"
88 " \"name\": {\n"
89 " \"value\": 1\n"
90 " },\n"
91 " \"name\": {\n"
92 " \"value\": 2\n"
93 " }\n"
94 "}");
95 verifyFormat(Code: "{\n"
96 " \"name\": {\n"
97 " \"value\": [\n"
98 " 1,\n"
99 " 2,\n"
100 " ]\n"
101 " }\n"
102 "}");
103 verifyFormat(Code: "{\n"
104 " \"name\": {\n"
105 " \"value\": [\n"
106 " \"name\": {\n"
107 " \"value\": 1\n"
108 " },\n"
109 " \"name\": {\n"
110 " \"value\": 2\n"
111 " }\n"
112 " ]\n"
113 " }\n"
114 "}");
115 verifyFormat(Code: R"({
116 "firstName": "John",
117 "lastName": "Smith",
118 "isAlive": true,
119 "age": 27,
120 "address": {
121 "streetAddress": "21 2nd Street",
122 "city": "New York",
123 "state": "NY",
124 "postalCode": "10021-3100"
125 },
126 "phoneNumbers": [
127 {
128 "type": "home",
129 "number": "212 555-1234"
130 },
131 {
132 "type": "office",
133 "number": "646 555-4567"
134 }
135 ],
136 "children": [],
137 "spouse": null
138})");
139}
140
141TEST_F(FormatTestJson, JsonArray) {
142 verifyFormat(Code: "[]");
143 verifyFormat(Code: "[\n"
144 " 1\n"
145 "]");
146 verifyFormat(Code: "[\n"
147 " 1,\n"
148 " 2\n"
149 "]");
150 verifyFormat(Code: "[\n"
151 " {},\n"
152 " {}\n"
153 "]");
154 verifyFormat(Code: "[\n"
155 " {\n"
156 " \"name\": 1\n"
157 " },\n"
158 " {}\n"
159 "]");
160}
161
162TEST_F(FormatTestJson, JsonArrayOneLine) {
163 FormatStyle Style = getLLVMStyle(Language: FormatStyle::LK_Json);
164 Style.BreakArrays = false;
165 Style.SpacesInContainerLiterals = false;
166 verifyFormat(Code: "[]", Style);
167 verifyFormat(Code: "[1]", Style);
168 verifyFormat(Code: "[1, 2]", Style);
169 verifyFormat(Code: "[1, 2, 3]", Style);
170 verifyFormat(Code: "[1, 2, 3, 4]", Style);
171 verifyFormat(Code: "[1, 2, 3, 4, 5]", Style);
172
173 verifyFormat(Code: "[\n"
174 " 1,\n"
175 " 2,\n"
176 " {\n"
177 " A: 1\n"
178 " }\n"
179 "]",
180 Style);
181}
182
183TEST_F(FormatTestJson, JsonNoStringSplit) {
184 FormatStyle Style = getLLVMStyle(Language: FormatStyle::LK_Json);
185 Style.IndentWidth = 4;
186 verifyFormat(
187 Code: "[\n"
188 " {\n"
189 " "
190 "\"naaaaaaaa\": \"foooooooooooooooooooooo oooooooooooooooooooooo\"\n"
191 " },\n"
192 " {}\n"
193 "]",
194 Style);
195 verifyFormat(Code: "[\n"
196 " {\n"
197 " "
198 "\"naaaaaaaa\": "
199 "\"foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
200 "oooooooooooooooooooooooooo\"\n"
201 " },\n"
202 " {}\n"
203 "]",
204 Style);
205
206 Style.ColumnLimit = 80;
207 verifyFormat(Code: "[\n"
208 " {\n"
209 " "
210 "\"naaaaaaaa\":\n"
211 " "
212 "\"foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
213 "oooooooooooooooooooooooooo\"\n"
214 " },\n"
215 " {}\n"
216 "]",
217 Style);
218}
219
220TEST_F(FormatTestJson, DisableJsonFormat) {
221 FormatStyle Style = getLLVMStyle(Language: FormatStyle::LK_Json);
222 verifyFormatStable(Code: "{}", Style);
223 verifyFormatStable(Code: "{\n"
224 " \"name\": 1\n"
225 "}",
226 Style);
227
228 // Since we have to disable formatting to run this test, we shall refrain from
229 // calling test::messUp lest we change the unformatted code and cannot format
230 // it back to how it started.
231 Style.DisableFormat = true;
232 verifyFormatStable(Code: "{}", Style);
233 verifyFormatStable(Code: "{\n"
234 " \"name\": 1\n"
235 "}",
236 Style);
237}
238
239TEST_F(FormatTestJson, SpaceBeforeJsonColon) {
240 FormatStyle Style = getLLVMStyle(Language: FormatStyle::LK_Json);
241 verifyFormatStable(Code: "{\n"
242 " \"name\": 1\n"
243 "}",
244 Style);
245
246 Style.SpaceBeforeJsonColon = true;
247 verifyFormatStable(Code: "{}", Style);
248 verifyFormatStable(Code: "{\n"
249 " \"name\" : 1\n"
250 "}",
251 Style);
252}
253
254TEST_F(FormatTestJson, StartsWithWhitespaces) {
255 FormatStyle Style = getLLVMStyle(Language: FormatStyle::LK_Json);
256 EXPECT_EQ("{\n"
257 " \"name\": 1\n"
258 "}",
259 format(" {\n"
260 " \"name\": 1\n"
261 "}",
262 Style));
263
264 // FIXME: The block below is over-indented.
265 EXPECT_EQ(" {\n"
266 " \"name\": 1\n"
267 " }",
268 format("\n{\n"
269 " \"name\": 1\n"
270 "}",
271 Style));
272}
273
274} // namespace format
275} // end namespace clang
276

source code of clang/unittests/Format/FormatTestJson.cpp