Skip to content

Commit 6f711e5

Browse files
committed
Implement macros for #file/#fileID/#filePath
1 parent 5ed277e commit 6f711e5

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

Sources/SwiftSyntaxMacros/MacroSystem+Examples.swift

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,66 @@ struct ImageLiteralMacro: ExpressionMacro {
202202
}
203203
}
204204

205+
struct FilePathMacro: ExpressionMacro {
206+
static var name: String { "filePath" }
207+
208+
static func apply(
209+
_ macro: MacroExpansionExprSyntax, in context: MacroEvaluationContext
210+
) -> MacroResult<ExprSyntax> {
211+
let fileName = context.sourceLocationConverter.location(
212+
for: .init(utf8Offset: 0)
213+
).file ?? "<unknown file>"
214+
let fileLiteral: ExprSyntax = #""\#(fileName)""#
215+
if let leadingTrivia = macro.leadingTrivia {
216+
return MacroResult(fileLiteral.withLeadingTrivia(leadingTrivia))
217+
}
218+
return MacroResult(fileLiteral)
219+
}
220+
}
221+
222+
struct FileIDMacro: ExpressionMacro {
223+
static var name: String { "fileID" }
224+
225+
static func apply(
226+
_ macro: MacroExpansionExprSyntax, in context: MacroEvaluationContext
227+
) -> MacroResult<ExprSyntax> {
228+
var fileName = context.sourceLocationConverter.location(
229+
for: .init(utf8Offset: 0)
230+
).file ?? "<unknown file>"
231+
232+
// Only keep everything after the last slash.
233+
if let lastSlash = fileName.lastIndex(of: "/") {
234+
fileName = String(fileName[fileName.index(after: lastSlash)...])
235+
}
236+
237+
let fileLiteral: ExprSyntax = #""\#(context.moduleName)/\#(fileName)""#
238+
if let leadingTrivia = macro.leadingTrivia {
239+
return MacroResult(fileLiteral.withLeadingTrivia(leadingTrivia))
240+
}
241+
return MacroResult(fileLiteral)
242+
}
243+
}
244+
245+
struct FileMacro: ExpressionMacro {
246+
static var name: String { "file" }
247+
248+
static func apply(
249+
_ macro: MacroExpansionExprSyntax, in context: MacroEvaluationContext
250+
) -> MacroResult<ExprSyntax> {
251+
// FIXME: Macro evaluation context needs to know the semantics of #file,
252+
// which is a feature check.
253+
return FilePathMacro.apply(macro, in: context)
254+
}
255+
}
256+
205257
extension MacroSystem {
206258
public static var exampleSystem: MacroSystem {
207259
var macroSystem = MacroSystem()
208260
try! macroSystem.add(ColorLiteralMacro.self)
209261
try! macroSystem.add(ColumnMacro.self)
262+
try! macroSystem.add(FileIDMacro.self)
210263
try! macroSystem.add(FileLiteralMacro.self)
264+
try! macroSystem.add(FilePathMacro.self)
211265
try! macroSystem.add(FunctionMacro.self)
212266
try! macroSystem.add(ImageLiteralMacro.self)
213267
try! macroSystem.add(LineMacro.self)

Tests/SwiftSyntaxMacrosTest/MacroSystemTests.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,28 @@ final class MacroSystemTests: XCTestCase {
104104
"""
105105
)
106106
}
107+
108+
func testFileExpansions() {
109+
let sf: SourceFileSyntax =
110+
"""
111+
let a = #filePath
112+
let b = #fileID
113+
"""
114+
let converter = SourceLocationConverter(
115+
file: "/tmp/src/taylor.swift", tree: sf
116+
)
117+
let context = MacroEvaluationContext(
118+
moduleName: "MyModule", sourceLocationConverter: converter
119+
)
120+
let transformedSF = MacroSystem.exampleSystem.evaluateMacros(
121+
node: sf, in: context, errorHandler: { error in }
122+
)
123+
AssertStringsEqualWithDiff(
124+
transformedSF.description,
125+
"""
126+
let a = "/tmp/src/taylor.swift"
127+
let b = "MyModule/taylor.swift"
128+
"""
129+
)
130+
}
107131
}

0 commit comments

Comments
 (0)