Files
swift-mirror/test/Macros/accessor_macros.swift
Henrik G. Olsson cbc0ec3b88 Add -verify-ignore-unrelated where necessary (NFC)
These are tests that fail in the next commit without this flag. This
does not add -verify-ignore-unrelated to all tests with -verify, only
the ones that would fail without it. This is NFC since this flag is
currently a no-op.
2025-10-04 14:19:52 -07:00

221 lines
6.8 KiB
Swift

// REQUIRES: swift_swift_parser, executable_test
// RUN: %empty-directory(%t)
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath
// Check for expected errors.
// RUN: %target-typecheck-verify-swift -verify-ignore-unrelated -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -DTEST_DIAGNOSTICS -verify-ignore-unknown
// RUN: not %target-swift-frontend -typecheck -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -DTEST_DIAGNOSTICS %s > %t/diags.txt 2>&1
// RUN: %FileCheck -check-prefix=CHECK-DIAGS %s < %t/diags.txt
// Check that the expansion buffer are as expected.
// RUN: %target-swift-frontend -swift-version 5 -typecheck -load-plugin-library %t/%target-library-name(MacroDefinition) %s -dump-macro-expansions > %t/expansions-dump.txt 2>&1
// RUN: %FileCheck -check-prefix=CHECK-DUMP %s < %t/expansions-dump.txt
// Execution testing
// RUN: %target-build-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) %s -o %t/main -module-name MacroUser
// RUN: %target-codesign %t/main
// RUN: %target-run %t/main | %FileCheck %s
@attached(accessor)
macro myPropertyWrapper() =
#externalMacro(module: "MacroDefinition", type: "PropertyWrapperMacro")
@attached(accessor)
macro myPropertyWrapperSkipsComputed() =
#externalMacro(module: "MacroDefinition", type: "PropertyWrapperSkipsComputedMacro")
struct Date { }
struct MyWrapperThingy<T> {
var storage: T
var wrappedValue: T {
get {
print("Getting value \(storage)")
return storage
}
set {
print("Setting value \(newValue)")
storage = newValue
}
}
}
struct MyStruct {
var _name: MyWrapperThingy<String> = .init(storage: "Hello")
var _birthDate: MyWrapperThingy<Date?> = .init(storage: nil)
var _favoriteColor: MyWrapperThingy<String> = .init(storage: "Blue")
@myPropertyWrapper
var name: String
// CHECK-DUMP: @__swiftmacro_15accessor_macros8MyStructV4name17myPropertyWrapperfMa_.swift
// CHECK-DUMP: get {
// CHECK-DUMP: _name.wrappedValue
// CHECK-DUMP: }
// CHECK-DUMP: set {
// CHECK-DUMP: _name.wrappedValue = newValue
// CHECK-DUMP: }
@myPropertyWrapper
var birthDate: Date?
// CHECK-DUMP: @__swiftmacro_15accessor_macros8MyStructV9birthDate17myPropertyWrapperfMa_.swift
// CHECK-DUMP: get {
// CHECK-DUMP: _birthDate.wrappedValue
// CHECK-DUMP: }
// CHECK-DUMP: set {
// CHECK-DUMP: _birthDate.wrappedValue = newValue
// CHECK-DUMP: }
@myPropertyWrapperSkipsComputed
var age: Int? {
get { nil }
}
@myPropertyWrapper
var favoriteColor: String {
didSet { fatalError("Boom") }
}
}
// Test that the fake-property-wrapper-introduced accessors execute properly at
// runtime.
var ms = MyStruct()
// CHECK: Getting value Hello
_ = ms.name
// CHECK-NEXT: Setting value World
ms.name = "World"
// CHECK-NEXT: Setting value Yellow
ms.favoriteColor = "Yellow"
#if TEST_DIAGNOSTICS
struct MyBrokenStruct {
var _birthDate: MyWrapperThingy<Date?> = .init(storage: nil)
// expected-note@+1 2{{in expansion of macro 'myPropertyWrapper' on property 'birthDate' here}}
@myPropertyWrapper
var birthDate: Date? {
/*
expected-expansion@-2:25{{
expected-error@1:1{{variable already has a getter}}
}}
*/
// CHECK-DIAGS: variable already has a getter
// CHECK-DIAGS: in expansion of macro
// CHECK-DIAGS: previous definition of getter here
get { fatalError("Boom") }
// expected-note @-1{{previous definition of getter here}}
// CHECK-DIAGS: variable already has a setter
// CHECK-DIAGS: in expansion of macro
// CHECK-DIAGS: previous definition of setter here
set { fatalError("Boom") }
// expected-note @-1{{previous definition of setter here}}
}
}
// expected-error@+1{{'accessor' macro cannot be attached to struct ('CannotHaveAccessors')}}
@myPropertyWrapper
struct CannotHaveAccessors {}
// CHECK-DIAGS: 'accessor' macro cannot be attached to struct ('CannotHaveAccessors')
#endif
@attached(accessor, names: named(willSet))
macro SkipsComputed() =
#externalMacro(module: "MacroDefinition", type: "PropertyWrapperSkipsComputedMacro")
struct HasComputed {
@SkipsComputed
var value: Int { 17 }
}
@attached(accessor, names: named(willSet))
macro AddWillSet() =
#externalMacro(module: "MacroDefinition", type: "WillSetMacro")
@attached(accessor)
macro AddWillSetSneakily() =
#externalMacro(module: "MacroDefinition", type: "WillSetMacro")
@attached(accessor, names: named(willSet))
macro MakeComputedSneakily() =
#externalMacro(module: "MacroDefinition", type: "PropertyWrapperMacro")
struct HasStoredTests {
@AddWillSet var x: Int = 0
#if TEST_DIAGNOSTICS
@AddWillSetSneakily var y: Int = 0
// expected-error@-1{{expansion of macro 'AddWillSetSneakily()' did not produce a non-observing accessor (such as 'get') as expected}}
@MakeComputedSneakily var z: Int = 0
// expected-error@-1{{expansion of macro 'MakeComputedSneakily()' produced an unexpected getter}}
// expected-note@-2 2{{in expansion of macro}}
// expected-note@-3 2{{'z' declared here}}
/*
expected-expansion@-5:36{{
expected-error@3:9{{cannot find '_z' in scope; did you mean 'z'?}}
expected-error@6:9{{cannot find '_z' in scope; did you mean 'z'?}}
}}
*/
#endif
}
#if TEST_DIAGNOSTICS
struct MultipleVars {
@AddWillSet var (x, y): (Int, Int) = (0, 0)
// expected-error@-1 2{{accessor macro 'AddWillSet()' can only apply to a single variable}}
}
#endif
@attached(accessor)
macro addGetterMacro() =
#externalMacro(module: "MacroDefinition", type: "AddGetterMacro")
#if TEST_DIAGNOSTICS
struct S {
@addGetterMacro let x: Int
// expected-warning@-1 {{cannot expand accessor macro on variable declared with 'let'; this is an error in the Swift 6 language mode}}
}
#endif
func acceptAutoclosure(_ success: @autoclosure () -> Bool, message: @autoclosure () -> String) {
}
@attached(accessor)
macro BigEndianAccessorMacro() = #externalMacro(module: "MacroDefinition", type: "BigEndianAccessorMacro")
func testLocalWithAutoclosure(x: Int, y: Int) {
struct Local {
var __value: Int = 0
// CHECK-DUMP: @__swiftmacro_15accessor_macros9value_$l022BigEndianAccessorMacrofMa_.swift
@BigEndianAccessorMacro
var value: Int
}
acceptAutoclosure(x == y, message: "they better be the same")
let local = Local(__value: 5)
acceptAutoclosure(x + 1 == local.__value, message: "they better be the same")
if x == y {
struct Nested {
struct Local {
var __value: Int = 0
// CHECK-DUMP: @__swiftmacro_15accessor_macros9value_$l122BigEndianAccessorMacrofMa_.swift
@BigEndianAccessorMacro
var value: Int
}
}
}
}