Skip to content

Commit ec5dd95

Browse files
committed
[Macros] Fix column calculation in MacroExpansionContext for plugins
When retriving a location for a node at the first line, column calculation was incorrect. 'column' of 'PluginMessage.Syntax' is 1-based, so we need to '-1' when using it as a offset.
1 parent 8a4d12e commit ec5dd95

File tree

6 files changed

+104
-1
lines changed

6 files changed

+104
-1
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SwiftSyntax
14+
import SwiftSyntaxMacros
15+
16+
public struct NativeFileIDMacro: ExpressionMacro {
17+
public static func expansion(
18+
of node: some FreestandingMacroExpansionSyntax,
19+
in context: some MacroExpansionContext
20+
) -> ExprSyntax {
21+
return context.location(
22+
of: node, at: .afterLeadingTrivia, filePathMode: .fileID
23+
)!.file
24+
}
25+
}
26+
27+
public struct NativeFilePathMacro: ExpressionMacro {
28+
public static func expansion(
29+
of node: some FreestandingMacroExpansionSyntax,
30+
in context: some MacroExpansionContext
31+
) -> ExprSyntax {
32+
return context.location(
33+
of: node, at: .afterLeadingTrivia, filePathMode: .filePath
34+
)!.file
35+
}
36+
}
37+
38+
public struct NativeLineMacro: ExpressionMacro {
39+
public static func expansion(
40+
of node: some FreestandingMacroExpansionSyntax,
41+
in context: some MacroExpansionContext
42+
) -> ExprSyntax {
43+
return context.location(of: node)!.line
44+
}
45+
}
46+
47+
public struct NativeColumnMacro: ExpressionMacro {
48+
public static func expansion(
49+
of node: some FreestandingMacroExpansionSyntax,
50+
in context: some MacroExpansionContext
51+
) -> ExprSyntax {
52+
return context.location(of: node)!.column
53+
}
54+
}

Examples/Sources/MacroExamples/Implementation/Plugin.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ struct MyPlugin: CompilerPlugin {
3232
FuncUniqueMacro.self,
3333
MemberDeprecatedMacro.self,
3434
MetaEnumMacro.self,
35+
NativeColumnMacro.self,
36+
NativeFileIDMacro.self,
37+
NativeFilePathMacro.self,
38+
NativeLineMacro.self,
3539
NewTypeMacro.self,
3640
ObservableMacro.self,
3741
ObservablePropertyMacro.self,
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
@freestanding(expression)
14+
public macro FileID<T: ExpressibleByStringLiteral>() -> T = #externalMacro(
15+
module: "MacroExamplesImplementation", type: "NativeFileIDMacro"
16+
)
17+
18+
19+
@freestanding(expression)
20+
public macro FilePath<T: ExpressibleByStringLiteral>() -> T = #externalMacro(
21+
module: "MacroExamplesImplementation", type: "NativeFilePathMacro"
22+
)
23+
24+
@freestanding(expression)
25+
public macro Line<T : ExpressibleByIntegerLiteral>() -> T = #externalMacro(
26+
module: "MacroExamplesImplementation", type: "NativeLineMacro"
27+
)
28+
29+
@freestanding(expression)
30+
public macro Column<T : ExpressibleByIntegerLiteral>() -> T = #externalMacro(
31+
module: "MacroExamplesImplementation", type: "NativeColumnMacro"
32+
)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import MacroExamplesInterface
2+
3+
func runSourceLoctionMacrosPlayground() {
4+
print("FileID: \(#FileID as String)")
5+
print("FilePath: \(#FilePath as String)")
6+
print("Line: \(#Line as Int)")
7+
print("Column: \(#Column as Int)")
8+
}

Examples/Sources/MacroExamples/Playground/main.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,7 @@ runPeerMacrosPlayground()
5555
runEnvironmentValueAccessorMacroPlayground()
5656

5757
#endif
58+
59+
// MARK: - SourceLocationMacros
60+
61+
runSourceLoctionMacrosPlayground()

Sources/SwiftCompilerPluginMessageHandling/PluginMacroExpansionContext.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,9 @@ class SourceManager {
174174
let localLocation = base.locationConverter.location(for: localPosition)
175175

176176
let positionOffset = base.location.offset
177+
// NOTE '- 1' because base.location.{line|column} are 1-based.
177178
let lineOffset = base.location.line - 1
178-
let columnOffset = localLocation.line == 1 ? base.location.column : 0
179+
let columnOffset = localLocation.line == 1 ? (base.location.column - 1) : 0
179180

180181
return SourceLocation(
181182
// NOTE: IUO because 'localLocation' is created by a location converter

0 commit comments

Comments
 (0)