Skip to content

Commit a159604

Browse files
authored
Merge pull request #70415 from ahoppen/ahoppen/cache-source-loc-converter
[Macros] Cache `SourceLocationConverter` in `ExportedSourceFile`
2 parents d61eac2 + 8da0754 commit a159604

File tree

3 files changed

+43
-17
lines changed

3 files changed

+43
-17
lines changed

lib/ASTGen/Sources/ASTGen/PluginHost.swift

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

388388
let source = syntax.description
389-
let sourceStr = String(decoding: sourceFilePtr.pointee.buffer, as: UTF8.self)
390389
let fileName = sourceFilePtr.pointee.fileName
391390
let fileID = "\(sourceFilePtr.pointee.moduleName)/\(sourceFilePtr.pointee.fileName.basename)"
392-
let converter = SourceLocationConverter(file: fileName, source: sourceStr)
393-
let loc = converter.location(for: syntax.position)
391+
let loc = sourceFilePtr.pointee.sourceLocationConverter.location(for: syntax.position)
394392

395393
self.init(
396394
kind: kind,

lib/ASTGen/Sources/ASTGen/SourceFile.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ public struct ExportedSourceFile {
3232
/// The syntax tree for the complete source file.
3333
public let syntax: SourceFileSyntax
3434

35+
/// A source location converter to convert `AbsolutePosition`s in `syntax` to line/column locations.
36+
///
37+
/// Cached so we don't need to re-build the line table every time we need to convert a position.
38+
let sourceLocationConverter: SourceLocationConverter
39+
3540
public func position(of location: BridgedSourceLoc) -> AbsolutePosition? {
3641
let sourceFileBaseAddress = UnsafeRawPointer(buffer.baseAddress!)
3742
guard let opaqueValue = location.getOpaquePointerValue() else {
@@ -74,12 +79,15 @@ public func parseSourceFile(
7479
let sourceFile = Parser.parse(source: buffer, experimentalFeatures: .init(from: ctx))
7580

7681
let exportedPtr = UnsafeMutablePointer<ExportedSourceFile>.allocate(capacity: 1)
82+
let moduleName = String(cString: moduleName)
83+
let fileName = String(cString: filename)
7784
exportedPtr.initialize(
7885
to: .init(
7986
buffer: buffer,
80-
moduleName: String(cString: moduleName),
81-
fileName: String(cString: filename),
82-
syntax: sourceFile
87+
moduleName: moduleName,
88+
fileName: fileName,
89+
syntax: sourceFile,
90+
sourceLocationConverter: SourceLocationConverter(fileName: fileName, tree: sourceFile)
8391
)
8492
)
8593

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

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,6 @@ extension SourceManager.MacroExpansionContext: MacroExpansionContext {
117117
return nil
118118
}
119119

120-
// Determine the filename to use in the resulting location.
121-
let fileName: String
122-
switch filePathMode {
123-
case .fileID:
124-
fileName = "\(exportedSourceFile.moduleName)/\(exportedSourceFile.fileName.basename)"
125-
126-
case .filePath:
127-
fileName = exportedSourceFile.fileName
128-
}
129120

130121
// Find the node's offset relative to its root.
131122
let rawPosition: AbsolutePosition
@@ -146,8 +137,37 @@ extension SourceManager.MacroExpansionContext: MacroExpansionContext {
146137
let offsetWithinSyntaxNode =
147138
rawPosition.utf8Offset - node.position.utf8Offset
148139

140+
var location = exportedSourceFile.sourceLocationConverter.location(
141+
for: rootPosition.advanced(by: offsetWithinSyntaxNode)
142+
)
143+
144+
switch filePathMode {
145+
case .fileID:
146+
// The `SourceLocationConverter` in `exportedSourceFile` uses `filePath` as the file mode. When the `fileID` mode
147+
// is requested, we need to adjust the file and presumed file to the `fileID`.
148+
let fileID = "\(exportedSourceFile.moduleName)/\(exportedSourceFile.fileName.basename)"
149+
var adjustedFile = location.file
150+
if adjustedFile == exportedSourceFile.fileName {
151+
adjustedFile = fileID
152+
}
153+
var adjustedPresumedFile = location.presumedFile
154+
if adjustedPresumedFile == exportedSourceFile.fileName {
155+
adjustedPresumedFile = fileID
156+
}
157+
location = SourceLocation(
158+
line: location.line,
159+
column: location.column,
160+
offset: location.offset,
161+
file: adjustedFile,
162+
presumedLine: location.presumedLine,
163+
presumedFile: adjustedPresumedFile
164+
)
165+
166+
case .filePath:
167+
break
168+
}
169+
149170
// Do the location lookup.
150-
let converter = SourceLocationConverter(file: fileName, tree: sourceFile)
151-
return AbstractSourceLocation(converter.location(for: rootPosition.advanced(by: offsetWithinSyntaxNode)))
171+
return AbstractSourceLocation(location)
152172
}
153173
}

0 commit comments

Comments
 (0)