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