Skip to content

Commit 5b17976

Browse files
authored
Merge pull request #70416 from ahoppen/ahoppen/5.10/cache-source-loc-converter
[5.10][Macros] Cache `SourceLocationConverter` in `ExportedSourceFile`
2 parents e8ca436 + 3e3b714 commit 5b17976

File tree

3 files changed

+45
-16
lines changed

3 files changed

+45
-16
lines changed

lib/ASTGen/Sources/ASTGen/PluginHost.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -379,11 +379,9 @@ extension PluginMessage.Syntax {
379379
}
380380

381381
let source = syntax.description
382-
let sourceStr = String(decoding: sourceFilePtr.pointee.buffer, as: UTF8.self)
383382
let fileName = sourceFilePtr.pointee.fileName
384383
let fileID = "\(sourceFilePtr.pointee.moduleName)/\(sourceFilePtr.pointee.fileName.basename)"
385-
let converter = SourceLocationConverter(file: fileName, source: sourceStr)
386-
let loc = converter.location(for: syntax.position)
384+
let loc = sourceFilePtr.pointee.sourceLocationConverter.location(for: syntax.position)
387385

388386
self.init(
389387
kind: kind,

lib/ASTGen/Sources/ASTGen/SourceFile.swift

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ struct ExportedSourceFile {
2323

2424
/// The syntax tree for the complete source file.
2525
let syntax: SourceFileSyntax
26+
27+
/// A source location converter to convert `AbsolutePosition`s in `syntax` to line/column locations.
28+
///
29+
/// Cached so we don't need to re-build the line table every time we need to convert a position.
30+
let sourceLocationConverter: SourceLocationConverter
2631
}
2732

2833
extension Parser.ExperimentalFeatures {
@@ -53,10 +58,16 @@ public func parseSourceFile(
5358
let sourceFile = Parser.parse(source: buffer, experimentalFeatures: .init(from: ctx))
5459

5560
let exportedPtr = UnsafeMutablePointer<ExportedSourceFile>.allocate(capacity: 1)
61+
let moduleName = String(cString: moduleName)
62+
let fileName = String(cString: filename)
5663
exportedPtr.initialize(
5764
to: .init(
58-
buffer: buffer, moduleName: String(cString: moduleName),
59-
fileName: String(cString: filename), syntax: sourceFile)
65+
buffer: buffer,
66+
moduleName: moduleName,
67+
fileName: fileName,
68+
syntax: sourceFile,
69+
sourceLocationConverter: SourceLocationConverter(fileName: fileName, tree: sourceFile)
70+
)
6071
)
6172

6273
return UnsafeRawPointer(exportedPtr)

lib/ASTGen/Sources/ASTGen/SourceManager+MacroExpansionContext.swift

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,6 @@ extension SourceManager.MacroExpansionContext: MacroExpansionContext {
102102
return nil
103103
}
104104

105-
// Determine the filename to use in the resulting location.
106-
let fileName: String
107-
switch filePathMode {
108-
case .fileID:
109-
fileName = "\(exportedSourceFile.moduleName)/\(exportedSourceFile.fileName.basename)"
110-
111-
case .filePath:
112-
fileName = exportedSourceFile.fileName
113-
}
114105

115106
// Find the node's offset relative to its root.
116107
let rawPosition: AbsolutePosition
@@ -131,8 +122,37 @@ extension SourceManager.MacroExpansionContext: MacroExpansionContext {
131122
let offsetWithinSyntaxNode =
132123
rawPosition.utf8Offset - node.position.utf8Offset
133124

125+
var location = exportedSourceFile.sourceLocationConverter.location(
126+
for: rootPosition.advanced(by: offsetWithinSyntaxNode)
127+
)
128+
129+
switch filePathMode {
130+
case .fileID:
131+
// The `SourceLocationConverter` in `exportedSourceFile` uses `filePath` as the file mode. When the `fileID` mode
132+
// is requested, we need to adjust the file and presumed file to the `fileID`.
133+
let fileID = "\(exportedSourceFile.moduleName)/\(exportedSourceFile.fileName.basename)"
134+
var adjustedFile = location.file
135+
if adjustedFile == exportedSourceFile.fileName {
136+
adjustedFile = fileID
137+
}
138+
var adjustePresumedFile = location.presumedFile
139+
if adjustePresumedFile == exportedSourceFile.fileName {
140+
adjustePresumedFile = fileID
141+
}
142+
location = SourceLocation(
143+
line: location.line,
144+
column: location.column,
145+
offset: location.offset,
146+
file: adjustedFile,
147+
presumedLine: location.presumedLine,
148+
presumedFile: adjustePresumedFile
149+
)
150+
151+
case .filePath:
152+
break
153+
}
154+
134155
// Do the location lookup.
135-
let converter = SourceLocationConverter(file: fileName, tree: sourceFile)
136-
return AbstractSourceLocation(converter.location(for: rootPosition.advanced(by: offsetWithinSyntaxNode)))
156+
return AbstractSourceLocation(location)
137157
}
138158
}

0 commit comments

Comments
 (0)