1//===- unittest/Format/ObjCPropertyAttributeOrderFixerTest.cpp - unit tests
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 "../lib/Format/ObjCPropertyAttributeOrderFixer.h"
10#include "FormatTestBase.h"
11#include "TestLexer.h"
12
13#define DEBUG_TYPE "format-objc-property-attribute-order-fixer-test"
14
15namespace clang {
16namespace format {
17namespace test {
18namespace {
19
20#define CHECK_PARSE(TEXT, FIELD, VALUE) \
21 EXPECT_NE(VALUE, Style.FIELD) << "Initial value already the same!"; \
22 EXPECT_EQ(0, parseConfiguration(TEXT, &Style).value()); \
23 EXPECT_EQ(VALUE, Style.FIELD) << "Unexpected value after parsing!"
24
25#define FAIL_PARSE(TEXT, FIELD, VALUE) \
26 EXPECT_NE(0, parseConfiguration(TEXT, &Style).value()); \
27 EXPECT_EQ(VALUE, Style.FIELD) << "Unexpected value after parsing!"
28
29class ObjCPropertyAttributeOrderFixerTest : public FormatTestBase {
30protected:
31 TokenList annotate(llvm::StringRef Code,
32 const FormatStyle &Style = getLLVMStyle()) {
33 return TestLexer(Allocator, Buffers, Style).annotate(Code);
34 }
35
36 llvm::SpecificBumpPtrAllocator<FormatToken> Allocator;
37 std::vector<std::unique_ptr<llvm::MemoryBuffer>> Buffers;
38};
39
40TEST_F(ObjCPropertyAttributeOrderFixerTest, ParsesStyleOption) {
41 FormatStyle Style = {};
42 Style.Language = FormatStyle::LK_ObjC;
43
44 CHECK_PARSE("ObjCPropertyAttributeOrder: [class]", ObjCPropertyAttributeOrder,
45 std::vector<std::string>({"class"}));
46
47 CHECK_PARSE("ObjCPropertyAttributeOrder: ["
48 "class, direct, atomic, nonatomic, "
49 "assign, retain, strong, copy, weak, unsafe_unretained, "
50 "readonly, readwrite, getter, setter, "
51 "nullable, nonnull, null_resettable, null_unspecified"
52 "]",
53 ObjCPropertyAttributeOrder,
54 std::vector<std::string>({
55 "class",
56 "direct",
57 "atomic",
58 "nonatomic",
59 "assign",
60 "retain",
61 "strong",
62 "copy",
63 "weak",
64 "unsafe_unretained",
65 "readonly",
66 "readwrite",
67 "getter",
68 "setter",
69 "nullable",
70 "nonnull",
71 "null_resettable",
72 "null_unspecified",
73 }));
74}
75
76TEST_F(ObjCPropertyAttributeOrderFixerTest, SortsSpecifiedAttributes) {
77 FormatStyle Style = getLLVMStyle();
78 Style.Language = FormatStyle::LK_ObjC;
79 Style.ObjCPropertyAttributeOrder = {"a", "b", "c"};
80
81 // Zero: nothing to do, but is legal.
82 verifyFormat("@property() int p;", Style);
83
84 // One: shouldn't move.
85 verifyFormat("@property(a) int p;", Style);
86 verifyFormat("@property(b) int p;", Style);
87 verifyFormat("@property(c) int p;", Style);
88
89 // Two in correct order already: no change.
90 verifyFormat("@property(a, b) int p;", Style);
91 verifyFormat("@property(a, c) int p;", Style);
92 verifyFormat("@property(b, c) int p;", Style);
93
94 // Three in correct order already: no change.
95 verifyFormat("@property(a, b, c) int p;", Style);
96
97 // Two wrong order.
98 verifyFormat("@property(a, b) int p;", "@property(b, a) int p;", Style);
99 verifyFormat("@property(a, c) int p;", "@property(c, a) int p;", Style);
100 verifyFormat("@property(b, c) int p;", "@property(c, b) int p;", Style);
101
102 // Three wrong order.
103 verifyFormat("@property(a, b, c) int p;", "@property(b, a, c) int p;", Style);
104 verifyFormat("@property(a, b, c) int p;", "@property(c, b, a) int p;", Style);
105
106 // Check that properties preceded by @optional/@required work.
107 verifyFormat("@optional\n"
108 "@property(a, b) int p;",
109 "@optional @property(b, a) int p;", Style);
110 verifyFormat("@required\n"
111 "@property(a, b) int p;",
112 "@required @property(b, a) int p;", Style);
113
114 // Check two `@property`s on one-line are reflowed (by other passes)
115 // and both have their attributes reordered.
116 verifyFormat("@property(a, b) int p;\n"
117 "@property(a, b) int q;",
118 "@property(b, a) int p; @property(b, a) int q;", Style);
119}
120
121TEST_F(ObjCPropertyAttributeOrderFixerTest, SortsAttributesWithValues) {
122 FormatStyle Style = getLLVMStyle();
123 Style.Language = FormatStyle::LK_ObjC;
124 Style.ObjCPropertyAttributeOrder = {"a", "getter", "c"};
125
126 // No change
127 verifyFormat("@property(getter=G, c) int p;", Style);
128 verifyFormat("@property(a, getter=G) int p;", Style);
129 verifyFormat("@property(a, getter=G, c) int p;", Style);
130
131 // Reorder
132 verifyFormat("@property(getter=G, c) int p;", "@property(c, getter=G) int p;",
133 Style);
134 verifyFormat("@property(a, getter=G) int p;", "@property(getter=G, a) int p;",
135 Style);
136 verifyFormat("@property(a, getter=G, c) int p;",
137 "@property(getter=G, c, a) int p;", Style);
138
139 // Multiple set properties, including ones not recognized
140 verifyFormat("@property(a=A, c=C, x=X, y=Y) int p;",
141 "@property(c=C, x=X, y=Y, a=A) int p;", Style);
142}
143
144TEST_F(ObjCPropertyAttributeOrderFixerTest, SortsUnspecifiedAttributesToBack) {
145 FormatStyle Style = getLLVMStyle();
146 Style.Language = FormatStyle::LK_ObjC;
147 Style.ObjCPropertyAttributeOrder = {"a", "b", "c"};
148
149 verifyFormat("@property(x) int p;", Style);
150
151 // No change in order.
152 verifyFormat("@property(a, x, y) int p;", Style);
153 verifyFormat("@property(b, x, y) int p;", Style);
154 verifyFormat("@property(a, b, c, x, y) int p;", Style);
155
156 // Reorder one unrecognized one.
157 verifyFormat("@property(a, x) int p;", "@property(x, a) int p;", Style);
158
159 // Prove the unrecognized ones have a stable sort order
160 verifyFormat("@property(a, b, x, y) int p;", "@property(x, b, y, a) int p;",
161 Style);
162 verifyFormat("@property(a, b, y, x) int p;", "@property(y, b, x, a) int p;",
163 Style);
164}
165
166TEST_F(ObjCPropertyAttributeOrderFixerTest, HandlesDuplicatedAttributes) {
167 // Duplicated attributes aren't rejected by the compiler even if it's silly
168 // to do so. Preserve them and sort them best-effort.
169 FormatStyle Style = getLLVMStyle();
170 Style.Language = FormatStyle::LK_ObjC;
171 Style.ObjCPropertyAttributeOrder = {"a", "b", "c"};
172
173 // Just a dup and nothing else.
174 verifyFormat("@property(a) int p;", "@property(a, a) int p;", Style);
175
176 // A dup and something else.
177 verifyFormat("@property(a, b) int p;", "@property(a, b, a) int p;", Style);
178
179 // Duplicates using `=`.
180 verifyFormat("@property(a=A, b=X) int p;",
181 "@property(a=A, b=X, a=A, b=Y) int p;", Style);
182 verifyFormat("@property(a=A, b=Y) int p;",
183 "@property(a=A, b=Y, a=A, b=X) int p;", Style);
184 verifyFormat("@property(a, b=B) int p;", "@property(a, b=B, a=A, b) int p;",
185 Style);
186}
187
188TEST_F(ObjCPropertyAttributeOrderFixerTest, SortsInPPDirective) {
189 FormatStyle Style = getLLVMStyle();
190 Style.Language = FormatStyle::LK_ObjC;
191 Style.ObjCPropertyAttributeOrder = {"a", "b", "c"};
192
193 // Spot-check a few simple cases that require sorting in a macro definition.
194 verifyFormat("#define MACRO @property() int p;", Style);
195 verifyFormat("#define MACRO @property(a) int p;", Style);
196 verifyFormat("#define MACRO @property(a, b) int p;",
197 "#define MACRO @property(b, a) int p;", Style);
198 verifyFormat("#define MACRO @property(a, b, c) int p;",
199 "#define MACRO @property(c, b, a) int p;", Style);
200}
201
202TEST_F(ObjCPropertyAttributeOrderFixerTest, HandlesAllAttributes) {
203 // `class` is the only attribute that is a keyword, so make sure it works too.
204 FormatStyle Style = getLLVMStyle();
205 Style.Language = FormatStyle::LK_ObjC;
206 Style.ObjCPropertyAttributeOrder = {"FIRST",
207 "class",
208 "direct",
209 "atomic",
210 "nonatomic",
211 "assign",
212 "retain",
213 "strong",
214 "copy",
215 "weak",
216 "unsafe_unretained",
217 "readonly",
218 "readwrite",
219 "getter",
220 "setter",
221 "nullable",
222 "nonnull",
223 "null_resettable",
224 "null_unspecified",
225 "LAST"};
226
227 // No change: specify all attributes in the correct order.
228 verifyFormat("@property(class, LAST) int p;", Style);
229 verifyFormat("@property(direct, LAST) int p;", Style);
230 verifyFormat("@property(atomic, LAST) int p;", Style);
231 verifyFormat("@property(nonatomic, LAST) int p;", Style);
232 verifyFormat("@property(assign, LAST) int p;", Style);
233 verifyFormat("@property(retain, LAST) int p;", Style);
234 verifyFormat("@property(strong, LAST) int p;", Style);
235 verifyFormat("@property(copy, LAST) int p;", Style);
236 verifyFormat("@property(weak, LAST) int p;", Style);
237 verifyFormat("@property(unsafe_unretained, LAST) int p;", Style);
238 verifyFormat("@property(readonly, LAST) int p;", Style);
239 verifyFormat("@property(readwrite, LAST) int p;", Style);
240 verifyFormat("@property(getter, LAST) int p;", Style);
241 verifyFormat("@property(setter, LAST) int p;", Style);
242 verifyFormat("@property(nullable, LAST) int p;", Style);
243 verifyFormat("@property(nonnull, LAST) int p;", Style);
244 verifyFormat("@property(null_resettable, LAST) int p;", Style);
245 verifyFormat("@property(null_unspecified, LAST) int p;", Style);
246
247 verifyFormat("@property(FIRST, class) int p;", Style);
248 verifyFormat("@property(FIRST, direct) int p;", Style);
249 verifyFormat("@property(FIRST, atomic) int p;", Style);
250 verifyFormat("@property(FIRST, nonatomic) int p;", Style);
251 verifyFormat("@property(FIRST, assign) int p;", Style);
252 verifyFormat("@property(FIRST, retain) int p;", Style);
253 verifyFormat("@property(FIRST, strong) int p;", Style);
254 verifyFormat("@property(FIRST, copy) int p;", Style);
255 verifyFormat("@property(FIRST, weak) int p;", Style);
256 verifyFormat("@property(FIRST, unsafe_unretained) int p;", Style);
257 verifyFormat("@property(FIRST, readonly) int p;", Style);
258 verifyFormat("@property(FIRST, readwrite) int p;", Style);
259 verifyFormat("@property(FIRST, getter) int p;", Style);
260 verifyFormat("@property(FIRST, setter) int p;", Style);
261 verifyFormat("@property(FIRST, nullable) int p;", Style);
262 verifyFormat("@property(FIRST, nonnull) int p;", Style);
263 verifyFormat("@property(FIRST, null_resettable) int p;", Style);
264 verifyFormat("@property(FIRST, null_unspecified) int p;", Style);
265
266 verifyFormat("@property(FIRST, class, LAST) int p;", Style);
267 verifyFormat("@property(FIRST, direct, LAST) int p;", Style);
268 verifyFormat("@property(FIRST, atomic, LAST) int p;", Style);
269 verifyFormat("@property(FIRST, nonatomic, LAST) int p;", Style);
270 verifyFormat("@property(FIRST, assign, LAST) int p;", Style);
271 verifyFormat("@property(FIRST, retain, LAST) int p;", Style);
272 verifyFormat("@property(FIRST, strong, LAST) int p;", Style);
273 verifyFormat("@property(FIRST, copy, LAST) int p;", Style);
274 verifyFormat("@property(FIRST, weak, LAST) int p;", Style);
275 verifyFormat("@property(FIRST, unsafe_unretained, LAST) int p;", Style);
276 verifyFormat("@property(FIRST, readonly, LAST) int p;", Style);
277 verifyFormat("@property(FIRST, readwrite, LAST) int p;", Style);
278 verifyFormat("@property(FIRST, getter, LAST) int p;", Style);
279 verifyFormat("@property(FIRST, setter, LAST) int p;", Style);
280 verifyFormat("@property(FIRST, nullable, LAST) int p;", Style);
281 verifyFormat("@property(FIRST, nonnull, LAST) int p;", Style);
282 verifyFormat("@property(FIRST, null_resettable, LAST) int p;", Style);
283 verifyFormat("@property(FIRST, null_unspecified, LAST) int p;", Style);
284
285 // Reorder: put `FIRST` and/or `LAST` in the wrong spot.
286 verifyFormat("@property(class, LAST) int p;", "@property(LAST, class) int p;",
287 Style);
288 verifyFormat("@property(direct, LAST) int p;",
289 "@property(LAST, direct) int p;", Style);
290 verifyFormat("@property(atomic, LAST) int p;",
291 "@property(LAST, atomic) int p;", Style);
292 verifyFormat("@property(nonatomic, LAST) int p;",
293 "@property(LAST, nonatomic) int p;", Style);
294 verifyFormat("@property(assign, LAST) int p;",
295 "@property(LAST, assign) int p;", Style);
296 verifyFormat("@property(retain, LAST) int p;",
297 "@property(LAST, retain) int p;", Style);
298 verifyFormat("@property(strong, LAST) int p;",
299 "@property(LAST, strong) int p;", Style);
300 verifyFormat("@property(copy, LAST) int p;", "@property(LAST, copy) int p;",
301 Style);
302 verifyFormat("@property(weak, LAST) int p;", "@property(LAST, weak) int p;",
303 Style);
304 verifyFormat("@property(unsafe_unretained, LAST) int p;",
305 "@property(LAST, unsafe_unretained) int p;", Style);
306 verifyFormat("@property(readonly, LAST) int p;",
307 "@property(LAST, readonly) int p;", Style);
308 verifyFormat("@property(readwrite, LAST) int p;",
309 "@property(LAST, readwrite) int p;", Style);
310 verifyFormat("@property(getter, LAST) int p;",
311 "@property(LAST, getter) int p;", Style);
312 verifyFormat("@property(setter, LAST) int p;",
313 "@property(LAST, setter) int p;", Style);
314 verifyFormat("@property(nullable, LAST) int p;",
315 "@property(LAST, nullable) int p;", Style);
316 verifyFormat("@property(nonnull, LAST) int p;",
317 "@property(LAST, nonnull) int p;", Style);
318 verifyFormat("@property(null_resettable, LAST) int p;",
319 "@property(LAST, null_resettable) int p;", Style);
320 verifyFormat("@property(null_unspecified, LAST) int p;",
321 "@property(LAST, null_unspecified) int p;", Style);
322
323 verifyFormat("@property(FIRST, class) int p;",
324 "@property(class, FIRST) int p;", Style);
325 verifyFormat("@property(FIRST, direct) int p;",
326 "@property(direct, FIRST) int p;", Style);
327 verifyFormat("@property(FIRST, atomic) int p;",
328 "@property(atomic, FIRST) int p;", Style);
329 verifyFormat("@property(FIRST, nonatomic) int p;",
330 "@property(nonatomic, FIRST) int p;", Style);
331 verifyFormat("@property(FIRST, assign) int p;",
332 "@property(assign, FIRST) int p;", Style);
333 verifyFormat("@property(FIRST, retain) int p;",
334 "@property(retain, FIRST) int p;", Style);
335 verifyFormat("@property(FIRST, strong) int p;",
336 "@property(strong, FIRST) int p;", Style);
337 verifyFormat("@property(FIRST, copy) int p;", "@property(copy, FIRST) int p;",
338 Style);
339 verifyFormat("@property(FIRST, weak) int p;", "@property(weak, FIRST) int p;",
340 Style);
341 verifyFormat("@property(FIRST, unsafe_unretained) int p;",
342 "@property(unsafe_unretained, FIRST) int p;", Style);
343 verifyFormat("@property(FIRST, readonly) int p;",
344 "@property(readonly, FIRST) int p;", Style);
345 verifyFormat("@property(FIRST, readwrite) int p;",
346 "@property(readwrite, FIRST) int p;", Style);
347 verifyFormat("@property(FIRST, getter) int p;",
348 "@property(getter, FIRST) int p;", Style);
349 verifyFormat("@property(FIRST, setter) int p;",
350 "@property(setter, FIRST) int p;", Style);
351 verifyFormat("@property(FIRST, nullable) int p;",
352 "@property(nullable, FIRST) int p;", Style);
353 verifyFormat("@property(FIRST, nonnull) int p;",
354 "@property(nonnull, FIRST) int p;", Style);
355 verifyFormat("@property(FIRST, null_resettable) int p;",
356 "@property(null_resettable, FIRST) int p;", Style);
357 verifyFormat("@property(FIRST, null_unspecified) int p;",
358 "@property(null_unspecified, FIRST) int p;", Style);
359
360 verifyFormat("@property(FIRST, class, LAST) int p;",
361 "@property(LAST, class, FIRST) int p;", Style);
362 verifyFormat("@property(FIRST, direct, LAST) int p;",
363 "@property(LAST, direct, FIRST) int p;", Style);
364 verifyFormat("@property(FIRST, atomic, LAST) int p;",
365 "@property(LAST, atomic, FIRST) int p;", Style);
366 verifyFormat("@property(FIRST, nonatomic, LAST) int p;",
367 "@property(LAST, nonatomic, FIRST) int p;", Style);
368 verifyFormat("@property(FIRST, assign, LAST) int p;",
369 "@property(LAST, assign, FIRST) int p;", Style);
370 verifyFormat("@property(FIRST, retain, LAST) int p;",
371 "@property(LAST, retain, FIRST) int p;", Style);
372 verifyFormat("@property(FIRST, strong, LAST) int p;",
373 "@property(LAST, strong, FIRST) int p;", Style);
374 verifyFormat("@property(FIRST, copy, LAST) int p;",
375 "@property(LAST, copy, FIRST) int p;", Style);
376 verifyFormat("@property(FIRST, weak, LAST) int p;",
377 "@property(LAST, weak, FIRST) int p;", Style);
378 verifyFormat("@property(FIRST, unsafe_unretained, LAST) int p;",
379 "@property(LAST, unsafe_unretained, FIRST) int p;", Style);
380 verifyFormat("@property(FIRST, readonly, LAST) int p;",
381 "@property(LAST, readonly, FIRST) int p;", Style);
382 verifyFormat("@property(FIRST, readwrite, LAST) int p;",
383 "@property(LAST, readwrite, FIRST) int p;", Style);
384 verifyFormat("@property(FIRST, getter, LAST) int p;",
385 "@property(LAST, getter, FIRST) int p;", Style);
386 verifyFormat("@property(FIRST, setter, LAST) int p;",
387 "@property(LAST, setter, FIRST) int p;", Style);
388 verifyFormat("@property(FIRST, nullable, LAST) int p;",
389 "@property(LAST, nullable, FIRST) int p;", Style);
390 verifyFormat("@property(FIRST, nonnull, LAST) int p;",
391 "@property(LAST, nonnull, FIRST) int p;", Style);
392 verifyFormat("@property(FIRST, null_resettable, LAST) int p;",
393 "@property(LAST, null_resettable, FIRST) int p;", Style);
394 verifyFormat("@property(FIRST, null_unspecified, LAST) int p;",
395 "@property(LAST, null_unspecified, FIRST) int p;", Style);
396}
397
398TEST_F(ObjCPropertyAttributeOrderFixerTest, HandlesCommentsAroundAttributes) {
399 FormatStyle Style = getLLVMStyle();
400 Style.Language = FormatStyle::LK_ObjC;
401 Style.ObjCPropertyAttributeOrder = {"a", "b"};
402
403 // Zero attributes but comments.
404 verifyFormat("@property(/* 1 */) int p;", Style);
405 verifyFormat("@property(/* 1 */ /* 2 */) int p;", Style);
406
407 // One attribute with comments before or after.
408 verifyFormat("@property(/* 1 */ a) int p;", Style);
409 verifyFormat("@property(a /* 2 */) int p;", Style);
410 verifyFormat("@property(/* 1 */ a /* 2 */) int p;", Style);
411
412 // No reordering if comments are encountered anywhere.
413 // (Each case represents a reordering that would have happened
414 // without the comment.)
415 verifyFormat("@property(/* before */ b, a) int p;", Style);
416 verifyFormat("@property(b, /* between */ a) int p;", Style);
417 verifyFormat("@property(b, a /* after */) int p;", Style);
418}
419
420} // namespace
421} // namespace test
422} // namespace format
423} // namespace clang
424

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