1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
// REQUIRES: swift_swift_parser, OS=macosx
// RUN: %empty-directory(%t)
// RUN: mkdir -p %t/src
// RUN: mkdir -p %t/plugins
// RUN: split-file %s %t/src
//#-- Prepare the macro dylib plugin.
// RUN: %host-build-swift \
// RUN: -swift-version 5 \
// RUN: -emit-library -o %t/plugins/%target-library-name(MacroDefinition) \
// RUN: -module-name MacroDefinition \
// RUN: %t/src/MacroDefinition.swift \
// RUN: -g -no-toolchain-stdlib-rpath
// RUN: %target-swift-frontend \
// RUN: -typecheck -verify \
// RUN: -enable-experimental-feature FreestandingMacros \
// RUN: -parse-as-library \
// RUN: -dump-macro-expansions \
// RUN: -plugin-path %t/plugins \
// RUN: %t/src/test.swift
//--- MacroDefinition.swift
import SwiftDiagnostics
import SwiftOperators
import SwiftSyntax
import SwiftSyntaxBuilder
import SwiftSyntaxMacros
public struct GlobalFuncAndVarMacro: DeclarationMacro {
public static func expansion(
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {
return ["func globalFunc() {}", "var globalVar: Int { 1 }"]
}
}
public struct MemberFuncAndVarMacro: DeclarationMacro {
public static func expansion(
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {
return ["func memberFunc() {}", "var memberVar: Int { 1 }"]
}
}
public struct LocalFuncAndVarMacro: DeclarationMacro {
public static func expansion(
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {
return ["func LocalFunc() {}", "var LocalVar: Int { 1 }"]
}
}
public struct FuncFromClosureMacro: DeclarationMacro {
public static func expansion(
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {
guard
let closure = node.trailingClosure,
let arg1 = node.argumentList.first?.expression else {
return []
}
return ["""
func fromClosure() {
print(\(arg1))
\(closure.statements)
}
"""]
}
}
public struct FuncFooBarNoAttrsMacro: DeclarationMacro {
public static var propagateFreestandingMacroAttributes: Bool { false }
public static var propagateFreestandingMacroModifiers: Bool { false }
public static func expansion(
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {
return ["func foo() -> Int { 1 }", "func bar() -> String { \"bar\" }"]
}
}
//--- test.swift
@freestanding(declaration, names: named(globalFunc), named(globalVar)) macro globalDecls() = #externalMacro(module: "MacroDefinition", type: "GlobalFuncAndVarMacro")
@freestanding(declaration, names: named(memberFunc), named(memberVar)) macro memberDecls() = #externalMacro(module: "MacroDefinition", type: "MemberFuncAndVarMacro")
@freestanding(declaration, names: named(localFunc), named(localVar)) macro localDecls() = #externalMacro(module: "MacroDefinition", type: "LocalFuncAndVarMacro")
@freestanding(declaration, names: named(foo), named(bar)) macro funcFooBarNoAttrs() = #externalMacro(module: "MacroDefinition", type: "FuncFooBarNoAttrsMacro")
@available(SwiftStdlib 9999, *)
#globalDecls
func testGlobal() { // expected-note 2 {{add @available attribute to enclosing global function}}
globalFunc() // expected-error {{'globalFunc()' is only available in macOS 9999 or newer}} expected-note {{add 'if #available' version check}}
_ = globalVar // expected-error {{'globalVar' is only available in macOS 9999 or newer}} expected-note {{add 'if #available' version check}}
}
struct S {
@available(SwiftStdlib 9999, *)
#memberDecls
}
func testMember(value: S) { // expected-note 2 {{add @available attribute to enclosing global function}}
value.memberFunc() // expected-error {{'memberFunc()' is only available in macOS 9999 or newer}} expected-note {{add 'if #available' version check}}
_ = value.memberVar // expected-error {{'memberVar' is only available in macOS 9999 or newer}} expected-note {{add 'if #available' version check}}
}
struct T {
static #memberDecls
}
func testStatic() {
T.memberFunc() // OK
_ = T.memberVar // OK
}
func testLocal() {
// FIXME(109376102): Local vars with freestanding macro is not supported yet.
#if false
#localDecls
do {
}
#endif
}
@freestanding(declaration, names: named(fromClosure)) macro funcFromClosureMacro(_: String, _: () -> Void) = #externalMacro(module: "MacroDefinition", type: "FuncFromClosureMacro")
@available(macOS 99, *)
func APIFrom99() -> String { "" }
@available(macOS 999, *)
func APIFrom999() -> String { "" }
@available(macOS 99, *)
#funcFromClosureMacro(APIFrom99()) {
_ = APIFrom99()
if #available(macOS 999, *) {
_ = APIFrom99()
_ = APIFrom999()
}
}
struct S1 {
@available(macOS 99, *)
#funcFromClosureMacro(APIFrom99()) {
_ = APIFrom99()
if #available(macOS 999, *) {
_ = APIFrom99()
_ = APIFrom999()
}
}
}
// FIXME: Diagnostics could be better.
struct S2 { // expected-note 4 {{add @available attribute to enclosing struct}}
// expected-note@+3 6 {{in expansion of macro 'funcFromClosureMacro' here}}
// expected-error@+2 {{'APIFrom99()' is only available in macOS 99 or newer}}
// expected-error@+2 {{'APIFrom99()' is only available in macOS 99 or newer}} expected-note@+2 {{add 'if #available' version check}}
#funcFromClosureMacro(APIFrom99()) {
_ = APIFrom99()
if #available(macOS 999, *) {
_ = APIFrom99()
_ = APIFrom999()
}
}
}
struct S3 {
@discardableResult private #funcFooBarNoAttrs()
}
func testS3(value: S3) {
value.foo() // expected-warning {{result of call to 'foo()' is unused}}
value.bar() // expected-warning {{result of call to 'bar()' is unused}}
}
|