Skip to content

Commit d8cb895

Browse files
committed
Merge remote-tracking branch 'upstream/main' into generic-parameter-list-function-scope
2 parents bbc9b6a + f8b6353 commit d8cb895

File tree

74 files changed

+2562
-786
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+2562
-786
lines changed

CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -341,19 +341,13 @@ public let EXPR_NODES: [Node] = [
341341
),
342342
Child(
343343
name: "name",
344-
kind: .token(choices: [.token(.identifier)]),
345-
isOptional: true
344+
kind: .token(choices: [.token(.identifier), .keyword(.self)])
346345
),
347346
Child(
348-
name: "equal",
349-
deprecatedName: "assignToken",
350-
kind: .token(choices: [.token(.equal)]),
347+
name: "initializer",
348+
kind: .node(kind: .initializerClause),
351349
isOptional: true
352350
),
353-
Child(
354-
name: "expression",
355-
kind: .node(kind: .expr)
356-
),
357351
Child(
358352
name: "trailingComma",
359353
kind: .token(choices: [.token(.comma)]),

CodeGeneration/Tests/ValidateSyntaxNodes/ValidateSyntaxNodes.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -482,22 +482,22 @@ class ValidateSyntaxNodes: XCTestCase {
482482
ValidationFailure(
483483
node: .enumCaseElement,
484484
message:
485-
"child 'rawValue' is named inconsistently with 'MatchingPatternConditionSyntax.initializer', which has the same type ('InitializerClauseSyntax')"
485+
"child 'rawValue' is named inconsistently with 'ClosureCaptureSyntax.initializer', which has the same type ('InitializerClauseSyntax')"
486486
),
487487
ValidationFailure(
488488
node: .enumCaseParameter,
489489
message:
490-
"child 'defaultValue' is named inconsistently with 'MatchingPatternConditionSyntax.initializer', which has the same type ('InitializerClauseSyntax')"
490+
"child 'defaultValue' is named inconsistently with 'ClosureCaptureSyntax.initializer', which has the same type ('InitializerClauseSyntax')"
491491
),
492492
ValidationFailure(
493493
node: .functionParameter,
494494
message:
495-
"child 'defaultValue' is named inconsistently with 'MatchingPatternConditionSyntax.initializer', which has the same type ('InitializerClauseSyntax')"
495+
"child 'defaultValue' is named inconsistently with 'ClosureCaptureSyntax.initializer', which has the same type ('InitializerClauseSyntax')"
496496
),
497497
ValidationFailure(
498498
node: .macroDecl,
499499
message:
500-
"child 'definition' is named inconsistently with 'MatchingPatternConditionSyntax.initializer', which has the same type ('InitializerClauseSyntax')"
500+
"child 'definition' is named inconsistently with 'ClosureCaptureSyntax.initializer', which has the same type ('InitializerClauseSyntax')"
501501
),
502502
// MARK: Miscellaneous
503503
ValidationFailure(

Package.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version:5.7
1+
// swift-tools-version:5.8
22

33
import Foundation
44
import PackageDescription
@@ -143,7 +143,7 @@ let package = Package(
143143

144144
.target(
145145
name: "SwiftIfConfig",
146-
dependencies: ["SwiftSyntax", "SwiftDiagnostics", "SwiftOperators"],
146+
dependencies: ["SwiftSyntax", "SwiftSyntaxBuilder", "SwiftDiagnostics", "SwiftOperators"],
147147
exclude: ["CMakeLists.txt"]
148148
),
149149

Release Notes/600.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
- Description: The `throwsSpecifier` for the effects nodes (`AccessorEffectSpecifiers`, `FunctionEffectSpecifiers`, `TypeEffectSpecifiers`, `EffectSpecifiers`) has been replaced with `throwsClause`, which captures both the throws specifier and the (optional) thrown error type, as introduced by SE-0413.
3333
- Pull Request: https://github.com/swiftlang/swift-syntax/pull/2379
3434

35-
- `String.isValidIdentifier(for:)`
35+
- `String.isValidSwiftIdentifier(for:)`
3636
- Description: `SwiftParser` adds an extension on `String` to check if it can be used as an identifier in a given context.
3737
- Pull Request: https://github.com/swiftlang/swift-syntax/pull/2434
3838

Release Notes/601.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
- Description: `IncrementalEdit` is being dropped for `SourceEdit`. `SourceEdit` has deprecated compatibility layers to make it API-compatible with `IncrementalEdit`
3232
- Issue: https://github.com/apple/swift-syntax/issues/2532
3333
- Pull request: https://github.com/apple/swift-syntax/pull/2604
34+
35+
- `ClosureCaptureSyntax.init(leadingTrivia:specifier:name:equal:expression:trailingComma:trailingTrivia:)` deprecated in favor of a new `ClosureCaptureSyntax.init(leadingTrivia:_:specifier:_:name:_:initializer:_:trailingComma:_:trailingTrivia:)` initializer.
36+
- Description: `ClosureCaptureSyntax` now has an `initializer` property instead of `equal` and `expression`. Additionally, the `name` property is no longer optional.
37+
- Pull request: https://github.com/swiftlang/swift-syntax/pull/2763
3438

3539
## API-Incompatible Changes
3640

@@ -39,6 +43,16 @@
3943
- Issue: https://github.com/apple/swift-syntax/issues/405
4044
- Pull Request: https://github.com/apple/swift-syntax/pull/2605
4145

46+
- `FixIt.Change` gained a new case `replaceChild(data:)`.
47+
- Description: The new case covers the replacement of a child node with another node.
48+
- Issue: https://github.com/swiftlang/swift-syntax/issues/2205
49+
- Pull Request: https://github.com/swiftlang/swift-syntax/pull/2758
50+
- Migration steps: In exhaustive switches over `FixIt.Change`, cover the new case.
51+
52+
- `ClosureCaptureSyntax.name` is no longer optional.
53+
- Description: Due to the new `ClosureCaptureSyntax` node structure, `name` property is non-optional.
54+
- Pull request: https://github.com/swiftlang/swift-syntax/pull/2763
55+
4256
## Template
4357

4458
- *Affected API or two word description*

Sources/SwiftCompilerPluginMessageHandling/Diagnostics.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,15 @@ extension PluginMessage.Diagnostic {
130130
to: .afterTrailingTrivia
131131
)
132132
text = newTrivia.description
133+
case .replaceChild(let replaceChildData):
134+
range = sourceManager.range(replaceChildData.replacementRange, in: replaceChildData.parent)
135+
text = replaceChildData.newChild.description
133136
#if RESILIENT_LIBRARIES
134137
@unknown default:
135138
fatalError()
136139
#endif
137140
}
138-
guard let range = range else {
141+
guard let range else {
139142
return nil
140143
}
141144
return .init(

Sources/SwiftCompilerPluginMessageHandling/PluginMacroExpansionContext.swift

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -169,20 +169,25 @@ class SourceManager {
169169
of node: Syntax,
170170
from startKind: PositionInSyntaxNode = .afterLeadingTrivia,
171171
to endKind: PositionInSyntaxNode = .beforeTrailingTrivia
172+
) -> SourceRange? {
173+
range(node.position(at: startKind)..<node.position(at: endKind), in: node)
174+
}
175+
176+
/// Get ``SourceRange`` (file name + UTF-8 offset range) of `localRange` in `node`'s root node, which must be one
177+
/// of the returned values from `add(_:)`.
178+
func range(
179+
_ localRange: @autoclosure () -> Range<AbsolutePosition>,
180+
in node: some SyntaxProtocol
172181
) -> SourceRange? {
173182
guard let base = self.knownSourceSyntax[node.root.id] else {
174183
return nil
175184
}
176-
let localStartPosition = node.position(at: startKind)
177-
let localEndPosition = node.position(at: endKind)
178-
precondition(localStartPosition <= localEndPosition)
179-
180185
let positionOffset = base.location.offset
181-
186+
let localRange = localRange()
182187
return SourceRange(
183188
fileName: base.location.fileName,
184-
startUTF8Offset: localStartPosition.advanced(by: positionOffset).utf8Offset,
185-
endUTF8Offset: localEndPosition.advanced(by: positionOffset).utf8Offset
189+
startUTF8Offset: localRange.lowerBound.advanced(by: positionOffset).utf8Offset,
190+
endUTF8Offset: localRange.upperBound.advanced(by: positionOffset).utf8Offset
186191
)
187192
}
188193

Sources/SwiftDiagnostics/Convenience.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,20 @@ extension FixIt {
5151
]
5252
)
5353
}
54+
55+
public static func replaceChild<Parent: SyntaxProtocol, Child: SyntaxProtocol>(
56+
message: FixItMessage,
57+
parent: Parent,
58+
replacingChildAt keyPath: WritableKeyPath<Parent, Child?> & Sendable,
59+
with newChild: Child
60+
) -> Self {
61+
FixIt(
62+
message: message,
63+
changes: [
64+
.replaceChild(
65+
data: FixIt.Change.ReplacingOptionalChildData(parent: parent, newChild: newChild, keyPath: keyPath)
66+
)
67+
]
68+
)
69+
}
5470
}

Sources/SwiftDiagnostics/FixIt.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,56 @@ public protocol FixItMessage: Sendable {
2727
var fixItID: MessageID { get }
2828
}
2929

30+
/// Types conforming to this protocol provide the data required for replacing a child node of a parent node.
31+
///
32+
/// Conforming types should ensure the child of ``parent`` to be replaced at ``replacementRange`` is type-compatible
33+
/// with ``newChild``. Conforming types are stored as type-erased existentials (i.e. `any ReplacingChildData`) in
34+
/// ``FixIt/Change/replaceChild(data:)`` to keep ``FixIt`` type-erased.
35+
public protocol ReplacingChildData: Sendable {
36+
associatedtype Parent: SyntaxProtocol
37+
associatedtype Child: SyntaxProtocol
38+
39+
/// The node whose child node at ``replacementRange`` to be replaced by ``newChild``.
40+
var parent: Parent { get }
41+
42+
/// The node to replace the child node of ``parent`` at ``replacementRange``.
43+
var newChild: Child { get }
44+
45+
/// The absolute position range of the child node to be replaced.
46+
///
47+
/// If a nil child node is to be replaced, conforming types should provide a zero-length range with both bounds
48+
/// denoting the start position of ``newChild`` in ``parent`` after replacement.
49+
var replacementRange: Range<AbsolutePosition> { get }
50+
}
51+
3052
/// A Fix-It that can be applied to resolve a diagnostic.
3153
public struct FixIt: Sendable {
3254
public enum Change: Sendable {
55+
struct ReplacingOptionalChildData<Parent: SyntaxProtocol, Child: SyntaxProtocol>: ReplacingChildData {
56+
let parent: Parent
57+
let newChild: Child
58+
let keyPath: WritableKeyPath<Parent, Child?> & Sendable
59+
60+
var replacementRange: Range<AbsolutePosition> {
61+
// need to upcast keyPath to strip Sendable for older Swift versions
62+
let keyPath: WritableKeyPath<Parent, Child?> = keyPath
63+
if let oldChild = parent[keyPath: keyPath] {
64+
return oldChild.range
65+
} else {
66+
let newChild = parent.with(keyPath, newChild)[keyPath: keyPath]!
67+
return newChild.position..<newChild.position
68+
}
69+
}
70+
}
71+
3372
/// Replace `oldNode` by `newNode`.
3473
case replace(oldNode: Syntax, newNode: Syntax)
3574
/// Replace the leading trivia on the given token
3675
case replaceLeadingTrivia(token: TokenSyntax, newTrivia: Trivia)
3776
/// Replace the trailing trivia on the given token
3877
case replaceTrailingTrivia(token: TokenSyntax, newTrivia: Trivia)
78+
/// Replace the child node of the given parent node at the given replacement range with the given new child node
79+
case replaceChild(data: any ReplacingChildData)
3980
}
4081

4182
/// A description of what this Fix-It performs.
@@ -89,6 +130,12 @@ private extension FixIt.Change {
89130
range: token.endPositionBeforeTrailingTrivia..<token.endPosition,
90131
replacement: newTrivia.description
91132
)
133+
134+
case .replaceChild(let replacingChildData):
135+
return SourceEdit(
136+
range: replacingChildData.replacementRange,
137+
replacement: replacingChildData.newChild.description
138+
)
92139
}
93140
}
94141
}

Sources/SwiftIfConfig/BuildConfiguration.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ public enum CanImportVersion {
4444
/// be imported is a complicated task only implemented in the Swift compiler.
4545
/// Therefore, queries are permitted to throw an error to report when they
4646
/// cannot answer a query, in which case this error will be reported to
47-
/// the caller.
47+
/// the caller and the condition will be treated as being "false", so the
48+
/// code covered by the condition will be inactive.
4849
public protocol BuildConfiguration {
4950
/// Determine whether a given custom build condition has been set.
5051
///

0 commit comments

Comments
 (0)