Skip to content

Commit 134c0a1

Browse files
committed
[ASTGen] Move macros related code to a new dedicated module
Introduce 'swiftMacros' module.
1 parent 3442fba commit 134c0a1

File tree

9 files changed

+246
-224
lines changed

9 files changed

+246
-224
lines changed

lib/ASTGen/CMakeLists.txt

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,10 @@ add_pure_swift_host_library(swiftASTGen STATIC
3131
Sources/ASTGen/Generics.swift
3232
Sources/ASTGen/LegacyParse.swift
3333
Sources/ASTGen/Literals.swift
34-
Sources/ASTGen/Macros.swift
3534
Sources/ASTGen/ParameterClause.swift
3635
Sources/ASTGen/Patterns.swift
37-
Sources/ASTGen/PluginHost.swift
3836
Sources/ASTGen/Regex.swift
3937
Sources/ASTGen/SourceFile.swift
40-
Sources/ASTGen/SourceManager.swift
4138
Sources/ASTGen/Stmts.swift
4239
Sources/ASTGen/TypeAttrs.swift
4340
Sources/ASTGen/Types.swift
@@ -51,19 +48,34 @@ add_pure_swift_host_library(swiftASTGen STATIC
5148
_CompilerSwiftSyntaxBuilder
5249
_CompilerSwiftParser
5350
_CompilerSwiftParserDiagnostics
54-
_CompilerSwiftCompilerPluginMessageHandling
55-
_CompilerSwiftSyntaxMacroExpansion
5651
_CompilerSwiftDiagnostics
57-
_CompilerSwiftIDEUtils
5852
${ASTGen_Swift_dependencies}
5953
)
6054

55+
add_pure_swift_host_library(swiftMacros STATIC
56+
Sources/Macros/Macros.swift
57+
Sources/Macros/PluginHost.swift
58+
Sources/Macros/SourceManager.swift
59+
60+
DEPENDENCIES
61+
swiftAST
62+
SWIFT_DEPENDENCIES
63+
_CompilerSwiftCompilerPluginMessageHandling
64+
_CompilerSwiftDiagnostics
65+
_CompilerSwiftOperators
66+
_CompilerSwiftParser
67+
_CompilerSwiftSyntax
68+
_CompilerSwiftSyntaxMacroExpansion
69+
swiftASTGen
70+
)
71+
6172
add_pure_swift_host_library(swiftIDEUtilsBridging
6273
Sources/SwiftIDEUtilsBridging/NameMatcherBridging.swift
6374

6475
DEPENDENCIES
6576
swiftAST
6677
SWIFT_DEPENDENCIES
78+
_CompilerSwiftIDEUtils
6779
_CompilerSwiftSyntax
6880
swiftASTGen
6981
)
@@ -111,7 +123,7 @@ else()
111123
endif()
112124

113125
if(SWIFT_BUILD_SWIFT_SYNTAX)
114-
foreach(target swiftASTGen swiftIDEUtilsBridging)
126+
foreach(target swiftASTGen swiftIDEUtilsBridging swiftMacros)
115127
target_compile_options(${target} PRIVATE ${compile_options})
116128
endforeach()
117129
endif()

lib/ASTGen/Package.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ let package = Package(
5454
.target(
5555
name: "swiftASTGen",
5656
dependencies: [
57-
.product(name: "_SwiftCompilerPluginMessageHandling", package: "swift-syntax"),
5857
.product(name: "SwiftDiagnostics", package: "swift-syntax"),
5958
.product(name: "SwiftIfConfig", package: "swift-syntax"),
6059
.product(name: "SwiftOperators", package: "swift-syntax"),
@@ -68,6 +67,20 @@ let package = Package(
6867
path: "Sources/ASTGen",
6968
swiftSettings: swiftSetttings
7069
),
70+
.target(
71+
name: "swiftMacros",
72+
dependencies: [
73+
"swiftASTGen",
74+
.product(name: "_SwiftCompilerPluginMessageHandling", package: "swift-syntax"),
75+
.product(name: "SwiftSyntax", package: "swift-syntax"),
76+
.product(name: "SwiftDiagnostics", package: "swift-syntax"),
77+
.product(name: "SwiftParser", package: "swift-syntax"),
78+
.product(name: "SwiftOperators", package: "swift-syntax"),
79+
.product(name: "SwiftSyntaxMacroExpansion", package: "swift-syntax"),
80+
],
81+
path: "Sources/Macros",
82+
swiftSettings: swiftSetttings
83+
),
7184
.target(
7285
name: "swiftIDEUtilsBridging",
7386
dependencies: [

lib/ASTGen/Sources/ASTGen/Bridge.swift

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import ASTBridging
1414
import BasicBridging
1515
@_spi(RawSyntax) import SwiftSyntax
1616

17-
protocol BridgedNullable: ExpressibleByNilLiteral {
17+
public protocol BridgedNullable: ExpressibleByNilLiteral {
1818
associatedtype RawPtr
1919
init(raw: RawPtr?)
2020
}
@@ -105,7 +105,7 @@ extension String {
105105
)
106106
}
107107

108-
mutating func withBridgedString<R>(_ body: (BridgedStringRef) throws -> R) rethrows -> R {
108+
public mutating func withBridgedString<R>(_ body: (BridgedStringRef) throws -> R) rethrows -> R {
109109
try withUTF8 { buffer in
110110
try body(BridgedStringRef(data: buffer.baseAddress, count: buffer.count))
111111
}
@@ -119,7 +119,7 @@ extension SyntaxText {
119119
}
120120

121121
/// Allocate a copy of the given string as a null-terminated UTF-8 string.
122-
func allocateBridgedString(
122+
public func allocateBridgedString(
123123
_ string: String
124124
) -> BridgedStringRef {
125125
var string = string
@@ -143,12 +143,6 @@ public func freeBridgedString(bridged: BridgedStringRef) {
143143
bridged.data?.deallocate()
144144
}
145145

146-
extension BridgedStringRef {
147-
var isEmptyInitialized: Bool {
148-
return self.data == nil && self.count == 0
149-
}
150-
}
151-
152146
extension BridgedStringRef: /*@retroactive*/ Swift.ExpressibleByStringLiteral {
153147
public init(stringLiteral str: StaticString) {
154148
self.init(data: str.utf8Start, count: str.utf8CodeUnitCount)

lib/ASTGen/Sources/ASTGen/DiagnosticsBridge.swift

Lines changed: 2 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ fileprivate func emitDiagnosticParts(
100100
}
101101

102102
/// Emit the given diagnostic via the diagnostic engine.
103-
func emitDiagnostic(
103+
public func emitDiagnostic(
104104
diagnosticEngine: BridgedDiagnosticEngine,
105105
sourceFileBuffer: UnsafeBufferPointer<UInt8>,
106106
sourceFileBufferOffset: Int = 0,
@@ -146,7 +146,7 @@ func emitDiagnostic(
146146
}
147147

148148
extension DiagnosticSeverity {
149-
var bridged: BridgedDiagnosticSeverity {
149+
public var bridged: BridgedDiagnosticSeverity {
150150
switch self {
151151
case .error: return .error
152152
case .note: return .note
@@ -159,141 +159,6 @@ extension DiagnosticSeverity {
159159
}
160160
}
161161

162-
extension SourceManager {
163-
private func diagnoseSingle<Node: SyntaxProtocol>(
164-
message: String,
165-
severity: DiagnosticSeverity,
166-
node: Node,
167-
position: AbsolutePosition,
168-
highlights: [Syntax] = [],
169-
fixItChanges: [FixIt.Change] = []
170-
) {
171-
// Map severity
172-
let bridgedSeverity = severity.bridged
173-
174-
// Emit the diagnostic
175-
var mutableMessage = message
176-
let diag = mutableMessage.withBridgedString { bridgedMessage in
177-
BridgedDiagnostic(
178-
at: bridgedSourceLoc(for: node, at: position),
179-
message: bridgedMessage,
180-
severity: bridgedSeverity,
181-
engine: bridgedDiagEngine
182-
)
183-
}
184-
185-
// Emit highlights
186-
for highlight in highlights {
187-
diag.highlight(
188-
start: bridgedSourceLoc(for: highlight, at: highlight.positionAfterSkippingLeadingTrivia),
189-
end: bridgedSourceLoc(for: highlight, at: highlight.endPositionBeforeTrailingTrivia)
190-
)
191-
}
192-
193-
// Emit changes for a Fix-It.
194-
for change in fixItChanges {
195-
let replaceStartLoc: BridgedSourceLoc
196-
let replaceEndLoc: BridgedSourceLoc
197-
var newText: String
198-
199-
switch change {
200-
case .replace(let oldNode, let newNode):
201-
replaceStartLoc = bridgedSourceLoc(
202-
for: oldNode,
203-
at: oldNode.positionAfterSkippingLeadingTrivia
204-
)
205-
replaceEndLoc = bridgedSourceLoc(
206-
for: oldNode,
207-
at: oldNode.endPositionBeforeTrailingTrivia
208-
)
209-
newText = newNode.description
210-
211-
case .replaceLeadingTrivia(let oldToken, let newTrivia):
212-
replaceStartLoc = bridgedSourceLoc(for: oldToken)
213-
replaceEndLoc = bridgedSourceLoc(
214-
for: oldToken,
215-
at: oldToken.positionAfterSkippingLeadingTrivia
216-
)
217-
newText = newTrivia.description
218-
219-
case .replaceTrailingTrivia(let oldToken, let newTrivia):
220-
replaceStartLoc = bridgedSourceLoc(
221-
for: oldToken,
222-
at: oldToken.endPositionBeforeTrailingTrivia
223-
)
224-
replaceEndLoc = bridgedSourceLoc(
225-
for: oldToken,
226-
at: oldToken.endPosition
227-
)
228-
newText = newTrivia.description
229-
230-
case .replaceChild(let replacingChildData):
231-
let replacementRange = replacingChildData.replacementRange
232-
replaceStartLoc = bridgedSourceLoc(
233-
for: replacingChildData.parent,
234-
at: replacementRange.lowerBound
235-
)
236-
replaceEndLoc = bridgedSourceLoc(
237-
for: replacingChildData.parent,
238-
at: replacementRange.upperBound
239-
)
240-
newText = replacingChildData.newChild.description
241-
242-
#if RESILIENT_SWIFT_SYNTAX
243-
@unknown default:
244-
fatalError()
245-
#endif
246-
}
247-
248-
newText.withBridgedString { bridgedMessage in
249-
diag.fixItReplace(
250-
start: replaceStartLoc,
251-
end: replaceEndLoc,
252-
replacement: bridgedMessage
253-
)
254-
}
255-
}
256-
257-
diag.finish();
258-
}
259-
260-
/// Emit a diagnostic via the C++ diagnostic engine.
261-
func diagnose(
262-
diagnostic: Diagnostic,
263-
messageSuffix: String? = nil
264-
) {
265-
// Emit the main diagnostic.
266-
diagnoseSingle(
267-
message: diagnostic.diagMessage.message + (messageSuffix ?? ""),
268-
severity: diagnostic.diagMessage.severity,
269-
node: diagnostic.node,
270-
position: diagnostic.position,
271-
highlights: diagnostic.highlights
272-
)
273-
274-
// Emit Fix-Its.
275-
for fixIt in diagnostic.fixIts {
276-
diagnoseSingle(
277-
message: fixIt.message.message,
278-
severity: .note,
279-
node: diagnostic.node,
280-
position: diagnostic.position,
281-
fixItChanges: fixIt.changes
282-
)
283-
}
284-
285-
// Emit any notes as follow-ons.
286-
for note in diagnostic.notes {
287-
diagnoseSingle(
288-
message: note.message,
289-
severity: .note,
290-
node: note.node,
291-
position: note.position
292-
)
293-
}
294-
}
295-
}
296-
297162
struct QueuedDiagnostics {
298163
var grouped: GroupedDiagnostics = GroupedDiagnostics()
299164

lib/ASTGen/Sources/ASTGen/SourceFile.swift

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,18 @@ public struct ExportedSourceFile {
2525
public let buffer: UnsafeBufferPointer<UInt8>
2626

2727
/// The name of the enclosing module.
28-
let moduleName: String
28+
public let moduleName: String
2929

3030
/// The name of the source file being parsed.
31-
let fileName: String
31+
public let fileName: String
3232

3333
/// The syntax tree for the complete source file.
3434
public let syntax: SourceFileSyntax
3535

3636
/// A source location converter to convert `AbsolutePosition`s in `syntax` to line/column locations.
3737
///
3838
/// Cached so we don't need to re-build the line table every time we need to convert a position.
39-
let sourceLocationConverter: SourceLocationConverter
39+
public let sourceLocationConverter: SourceLocationConverter
4040

4141
/// Configured regions for this source file.
4242
///
@@ -200,3 +200,64 @@ public func emitParserDiagnostics(
200200
return anyDiags ? 1 : 0
201201
}
202202
}
203+
204+
/// Retrieve a syntax node in the given source file, with the given type.
205+
public func findSyntaxNodeInSourceFile<Node: SyntaxProtocol>(
206+
sourceFilePtr: UnsafeRawPointer,
207+
sourceLocationPtr: UnsafePointer<UInt8>?,
208+
type: Node.Type,
209+
wantOutermost: Bool = false
210+
) -> Node? {
211+
guard let sourceLocationPtr = sourceLocationPtr else {
212+
return nil
213+
}
214+
215+
let sourceFilePtr = sourceFilePtr.assumingMemoryBound(to: ExportedSourceFile.self)
216+
217+
// Find the offset.
218+
let buffer = sourceFilePtr.pointee.buffer
219+
let offset = sourceLocationPtr - buffer.baseAddress!
220+
if offset < 0 || offset >= buffer.count {
221+
print("source location isn't inside this buffer")
222+
return nil
223+
}
224+
225+
// Find the token at that offset.
226+
let sf = sourceFilePtr.pointee.syntax
227+
guard let token = sf.token(at: AbsolutePosition(utf8Offset: offset)) else {
228+
print("couldn't find token at offset \(offset)")
229+
return nil
230+
}
231+
232+
var currentSyntax = Syntax(token)
233+
var resultSyntax: Node? = nil
234+
while let parentSyntax = currentSyntax.parent {
235+
currentSyntax = parentSyntax
236+
if let typedParent = currentSyntax.as(type) {
237+
resultSyntax = typedParent
238+
break
239+
}
240+
}
241+
242+
// If we didn't find anything, complain and fail.
243+
guard var resultSyntax else {
244+
print("unable to find node: \(token.debugDescription)")
245+
return nil
246+
}
247+
248+
// If we want the outermost node, keep looking.
249+
// E.g. for 'foo.bar' we want the member ref expression instead of the
250+
// identifier expression.
251+
if wantOutermost {
252+
while let parentSyntax = currentSyntax.parent,
253+
parentSyntax.position == resultSyntax.position
254+
{
255+
currentSyntax = parentSyntax
256+
if let typedParent = currentSyntax.as(type) {
257+
resultSyntax = typedParent
258+
}
259+
}
260+
}
261+
262+
return resultSyntax
263+
}

0 commit comments

Comments
 (0)