424 lines · cpp
1//===- unittest/Format/ObjCPropertyAttributeOrderFixerTest.cpp - unit tests2//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-exception6//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(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 change127 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 // Reorder132 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 recognized140 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 order160 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 silly168 // 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 happened414 // 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} // namespace421} // namespace test422} // namespace format423} // namespace clang424