Skip to content

Commit 9867998

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 9867998

File tree

6 files changed

+127
-1
lines changed

6 files changed

+127
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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,
23+
at: .afterLeadingTrivia,
24+
filePathMode: .fileID
25+
)!.file
26+
}
27+
}
28+
29+
public struct NativeFilePathMacro: ExpressionMacro {
30+
public static func expansion(
31+
of node: some FreestandingMacroExpansionSyntax,
32+
in context: some MacroExpansionContext
33+
) -> ExprSyntax {
34+
return context.location(
35+
of: node,
36+
at: .afterLeadingTrivia,
37+
filePathMode: .filePath
38+
)!.file
39+
}
40+
}
41+
42+
public struct NativeLineMacro: ExpressionMacro {
43+
public static func expansion(
44+
of node: some FreestandingMacroExpansionSyntax,
45+
in context: some MacroExpansionContext
46+
) -> ExprSyntax {
47+
return context.location(of: node)!.line
48+
}
49+
}
50+
51+
public struct NativeColumnMacro: ExpressionMacro {
52+
public static func expansion(
53+
of node: some FreestandingMacroExpansionSyntax,
54+
in context: some MacroExpansionContext
55+
) -> ExprSyntax {
56+
return context.location(of: node)!.column
57+
}
58+
}

Examples/Sources/MacroExamples/Implementation/Plugin.swift

+4
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,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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 =
15+
#externalMacro(
16+
module: "MacroExamplesImplementation",
17+
type: "NativeFileIDMacro"
18+
)
19+
20+
@freestanding(expression)
21+
public macro FilePath<T: ExpressibleByStringLiteral>() -> T =
22+
#externalMacro(
23+
module: "MacroExamplesImplementation",
24+
type: "NativeFilePathMacro"
25+
)
26+
27+
@freestanding(expression)
28+
public macro Line<T: ExpressibleByIntegerLiteral>() -> T =
29+
#externalMacro(
30+
module: "MacroExamplesImplementation",
31+
type: "NativeLineMacro"
32+
)
33+
34+
@freestanding(expression)
35+
public macro Column<T: ExpressibleByIntegerLiteral>() -> T =
36+
#externalMacro(
37+
module: "MacroExamplesImplementation",
38+
type: "NativeColumnMacro"
39+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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 MacroExamplesInterface
14+
15+
func runSourceLoctionMacrosPlayground() {
16+
print("FileID: \(#FileID as String)")
17+
print("FilePath: \(#FilePath as String)")
18+
print("Line: \(#Line as Int)")
19+
print("Column: \(#Column as Int)")
20+
}

Examples/Sources/MacroExamples/Playground/main.swift

+4
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

+2-1
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)