Skip to content

Commit aecd449

Browse files
authored
Merge pull request #62381 from DougGregor/swift-syntax-macros-api-changes
2 parents e057172 + b6df411 commit aecd449

File tree

8 files changed

+96
-161
lines changed

8 files changed

+96
-161
lines changed

lib/ASTGen/Sources/ASTGen/Macros.swift

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,18 @@ private func allocateUTF8String(
8282
}
8383
}
8484

85+
extension String {
86+
/// Drop everything up to and including the last '/' from the string.
87+
fileprivate func withoutPath() -> String {
88+
// Only keep everything after the last slash.
89+
if let lastSlash = lastIndex(of: "/") {
90+
return String(self[index(after: lastSlash)...])
91+
}
92+
93+
return self
94+
}
95+
}
96+
8597
@_cdecl("swift_ASTGen_evaluateMacro")
8698
@usableFromInline
8799
func evaluateMacro(
@@ -124,12 +136,9 @@ func evaluateMacro(
124136
return -1
125137
}
126138

127-
let converter = SourceLocationConverter(
128-
file: sourceFile.pointee.fileName, tree: sf
129-
)
130-
let context = MacroEvaluationContext(
139+
var context = MacroExpansionContext(
131140
moduleName: sourceFile.pointee.moduleName,
132-
sourceLocationConverter: converter
141+
fileName: sourceFile.pointee.fileName.withoutPath()
133142
)
134143

135144
let evaluatedSyntax: ExprSyntax = macroPtr.withMemoryRebound(to: ExportedMacro.self, capacity: 1) { macro in
@@ -138,11 +147,11 @@ func evaluateMacro(
138147
return ExprSyntax(parentExpansion)
139148
}
140149

141-
let expansion = exprMacro.apply(parentExpansion, in: context)
142-
// FIXME: Produce diagnostics.
143-
return expansion.rewritten
150+
return exprMacro.expand(parentExpansion, in: &context)
144151
}
145152

153+
// FIXME: Emit diagnostics accumulated in the
154+
146155
var evaluatedSyntaxStr = evaluatedSyntax.withoutTrivia().description
147156
evaluatedSyntaxStr.withUTF8 { utf8 in
148157
let evaluatedResultPtr = UnsafeMutablePointer<UInt8>.allocate(capacity: utf8.count + 1)
@@ -158,16 +167,3 @@ func evaluateMacro(
158167
return 0
159168
}
160169
}
161-
162-
// Makes sure that the type metadata for these macros can be found.
163-
public var allBuiltinMacros: [Any.Type] = [
164-
ColorLiteralMacro.self,
165-
ColumnMacro.self,
166-
FileIDMacro.self,
167-
FileLiteralMacro.self,
168-
FilePathMacro.self,
169-
FunctionMacro.self,
170-
ImageLiteralMacro.self,
171-
LineMacro.self,
172-
StringifyMacro.self
173-
]

lib/Sema/TypeCheckMacros.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,21 +101,19 @@ MacroDefinition MacroDefinitionRequest::evaluate(
101101
ASTContext &ctx = macro->getASTContext();
102102

103103
#if SWIFT_SWIFT_PARSER
104-
105104
/// Look for the type metadata given the external module and type names.
106105
auto macroMetatype = lookupMacroTypeMetadataByExternalName(
107106
ctx, macro->externalModuleName.str(),
108107
macro->externalMacroTypeName.str());
109108
if (macroMetatype) {
110109
// Check whether the macro metatype can be handled as a compiler plugin.
111-
// We look here first, because compiler plugins are meant to be resilient.
112110
if (auto plugin = CompilerPlugin::fromMetatype(macroMetatype, ctx)) {
113111
// FIXME: Handle other kinds of macros.
114112
return MacroDefinition::forCompilerPlugin(
115113
MacroDefinition::Expression, plugin);
116114
}
117115

118-
// Otherwise, check whether the macro metatype can be handled as a builtin.
116+
// Check whether the macro metatype can be handled as a builtin.
119117
if (auto builtin = swift_ASTGen_resolveMacroType(macroMetatype)) {
120118
// Make sure we clean up after the macro.
121119
ctx.addCleanup([builtin]() {

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,55 @@ import SwiftSyntax
22
import SwiftSyntaxBuilder
33
import _SwiftSyntaxMacros
44

5-
public struct FileIDMacro: ExpressionMacro {
6-
public static func apply(
7-
_ macro: MacroExpansionExprSyntax, in context: MacroEvaluationContext
8-
) -> MacroResult<ExprSyntax> {
9-
var fileName = context.sourceLocationConverter.location(
10-
for: .init(utf8Offset: 0)
11-
).file ?? "<unknown file>"
5+
/// Replace the label of the first element in the tuple with the given
6+
/// new label.
7+
private func replaceFirstLabel(
8+
of tuple: TupleExprElementListSyntax, with newLabel: String
9+
) -> TupleExprElementListSyntax{
10+
guard let firstElement = tuple.first else {
11+
return tuple
12+
}
13+
14+
return tuple.replacing(
15+
childAt: 0, with: firstElement.withLabel(.identifier(newLabel)))
16+
}
1217

13-
// Only keep everything after the last slash.
14-
if let lastSlash = fileName.lastIndex(of: "/") {
15-
fileName = String(fileName[fileName.index(after: lastSlash)...])
18+
public struct ColorLiteralMacro: ExpressionMacro {
19+
public static func expand(
20+
_ macro: MacroExpansionExprSyntax, in context: inout MacroExpansionContext
21+
) -> ExprSyntax {
22+
let argList = replaceFirstLabel(
23+
of: macro.argumentList, with: "_colorLiteralRed"
24+
)
25+
let initSyntax: ExprSyntax = ".init(\(argList))"
26+
if let leadingTrivia = macro.leadingTrivia {
27+
return initSyntax.withLeadingTrivia(leadingTrivia)
1628
}
29+
return initSyntax
30+
}
31+
}
1732

18-
let fileLiteral: ExprSyntax = #""\#(context.moduleName)/\#(fileName)""#
33+
public struct FileIDMacro: ExpressionMacro {
34+
public static func expand(
35+
_ macro: MacroExpansionExprSyntax, in context: inout MacroExpansionContext
36+
) -> ExprSyntax {
37+
let fileLiteral: ExprSyntax = #""\#(context.moduleName)/\#(context.fileName)""#
1938
if let leadingTrivia = macro.leadingTrivia {
20-
return MacroResult(fileLiteral.withLeadingTrivia(leadingTrivia))
39+
return fileLiteral.withLeadingTrivia(leadingTrivia)
40+
}
41+
return fileLiteral
42+
}
43+
}
44+
45+
public struct StringifyMacro: ExpressionMacro {
46+
public static func expand(
47+
_ macro: MacroExpansionExprSyntax, in context: inout MacroExpansionContext
48+
) -> ExprSyntax {
49+
guard let argument = macro.argumentList.first?.expression else {
50+
// FIXME: Create a diagnostic for the missing argument?
51+
return ExprSyntax(macro)
2152
}
22-
return MacroResult(fileLiteral)
53+
54+
return "(\(argument), \(StringLiteralExprSyntax(content: argument.description)))"
2355
}
2456
}

test/Macros/builtin_macros.swift

Lines changed: 0 additions & 22 deletions
This file was deleted.

test/Macros/macro_external_exec.swift

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,46 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-build-swift -Xfrontend -disable-availability-checking -I %swift-host-lib-dir -L %swift-host-lib-dir -emit-library -emit-library-path=%t/%target-library-name(MacroDefinition) -working-directory=%t -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift
3-
// RUN: %target-build-swift -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -L %swift-host-lib-dir %s -o %t/main -module-name MacroUser
2+
// RUN: %target-build-swift -I %swift-host-lib-dir -L %swift-host-lib-dir -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath
3+
// RUNx: %target-swift-frontend -dump-ast -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir %s -module-name MacroUser 2>&1 | %FileCheck --check-prefix CHECK-AST %s
4+
// RUN: %target-build-swift -enable-experimental-feature Macros -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -L %swift-host-lib-dir %s -o %t/main -module-name MacroUser
45
// RUN: %target-run %t/main | %FileCheck %s
56
// REQUIRES: executable_test
67

78
// FIXME: Swift parser is not enabled on Linux CI yet.
89
// REQUIRES: OS=macosx
910

1011
macro customFileID: String = MacroDefinition.FileIDMacro
12+
macro stringify<T>(_ value: T) -> (T, String) = MacroDefinition.StringifyMacro
13+
macro fileID<T: _ExpressibleByStringLitera>: T = MacroDefinition.FileIDMacro
1114

12-
func testFunc(a: Int, b: Int) {
15+
func testFileID(a: Int, b: Int) {
1316
// CHECK: MacroUser/macro_external_exec.swift
1417
print("Result is \(#customFileID)")
18+
19+
// CHECK: Builtin result is MacroUser/macro_external_exec.swift
20+
// CHECK-AST: macro_expansion_expr type='String'{{.*}}name=line
21+
print("Builtin result is \(#fileID)")
22+
}
23+
24+
testFileID(a: 1, b: 2)
25+
26+
func testStringify(a: Int, b: Int) {
27+
let s = #stringify(a + b)
28+
print(s)
29+
30+
// CHECK-AST: macro_expansion_expr type='(Int, String)'{{.*}}name=stringify
31+
// CHECK-AST-NEXT: argument_list
32+
// CHECK-AST: tuple_expr type='(Int, String)' location=Macro expansion of #stringify
33+
34+
let (b, s2) = #stringify({ () -> Bool in return true })
35+
// CHECK-AST: macro_expansion_expr type='(() -> Bool, String)'{{.*}}name=stringify
36+
// CHECK-AST-NEXT: argument_list
37+
// CHECK-AST: tuple_expr type='(() -> Bool, String)' location=Macro expansion of #stringify
38+
39+
let (b2, s3) = #stringify<Double>(1 + 2)
40+
// CHECK-AST: macro_expansion_expr type='(Double, String)'{{.*}}name=stringify
41+
// CHECK-AST-NEXT: argument_list
42+
// CHECK-AST: tuple_expr type='(Double, String)' location=Macro expansion of #stringify
1543
}
1644

17-
testFunc(a: 1, b: 2)
45+
// CHECK: (2, "a + b")
46+
testStringify(a: 1, b: 1)

test/Macros/macro_plugin.swift

Lines changed: 0 additions & 57 deletions
This file was deleted.

test/Macros/macro_plugin_exec.swift

Lines changed: 0 additions & 19 deletions
This file was deleted.

test/Macros/macros.swift

Lines changed: 0 additions & 22 deletions
This file was deleted.

0 commit comments

Comments
 (0)