Skip to content

Commit 56214d1

Browse files
authored
Merge pull request #1475 from ahoppen/ahoppen/cherry-pick
Cherry-pick PRs from `main` to `release/5.9`
2 parents 548c9a9 + 3e650c8 commit 56214d1

File tree

86 files changed

+3841
-1987
lines changed

Some content is hidden

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

86 files changed

+3841
-1987
lines changed

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ message(STATUS "Module triple: ${SWIFT_MODULE_TRIPLE}")
6868
add_compile_definitions(
6969
$<$<COMPILE_LANGUAGE:Swift>:SWIFT_SYNTAX_ALWAYS_SINGLE_THREADED>
7070
)
71+
if (SWIFTSYNTAX_ENABLE_ASSERTIONS)
72+
add_compile_definitions(
73+
$<$<COMPILE_LANGUAGE:Swift>:SWIFTSYNTAX_ENABLE_ASSERTIONS>
74+
)
75+
endif()
7176

7277
add_subdirectory(Sources)
7378

CodeGeneration/Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ let package = Package(
1111
.executable(name: "generate-swiftsyntax", targets: ["generate-swiftsyntax"])
1212
],
1313
dependencies: [
14-
.package(url: "https://github.com/apple/swift-syntax.git", revision: "94b9021a2e461fc9a4b3bda6f4734119b52e8094"),
14+
.package(url: "https://github.com/apple/swift-syntax.git", revision: "39b3336c3f3bfcd4ddbcbf6a111d8814ffe542f3"),
1515
.package(url: "https://github.com/apple/swift-argument-parser.git", .upToNextMinor(from: "1.2.2")),
1616
],
1717
targets: [

CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ public let ATTRIBUTE_NODES: [Node] = [
301301
children: [
302302
Child(
303303
name: "DeclBaseName",
304-
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .token(tokenKind: "PrefixOperatorToken"), .keyword(text: "init")]),
304+
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .token(tokenKind: "BinaryOperatorToken"), .keyword(text: "init"), .keyword(text: "self"), .keyword(text: "Self")]),
305305
nameForDiagnostics: "base name",
306306
description: "The base name of the protocol's requirement."
307307
),
@@ -468,7 +468,7 @@ public let ATTRIBUTE_NODES: [Node] = [
468468
children: [
469469
Child(
470470
name: "DiffKind",
471-
kind: .token(choices: [.keyword(text: "forward"), .keyword(text: "reverse"), .keyword(text: "linear")]),
471+
kind: .token(choices: [.keyword(text: "_forward"), .keyword(text: "reverse"), .keyword(text: "_linear")]),
472472
isOptional: true
473473
),
474474
Child(
@@ -644,7 +644,7 @@ public let ATTRIBUTE_NODES: [Node] = [
644644
children: [
645645
Child(
646646
name: "Label",
647-
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .keyword(text: "available"), .keyword(text: "exported"), .keyword(text: "kind"), .keyword(text: "spi"), .keyword(text: "spiModule")]),
647+
kind: .node(kind: "Token"),
648648
nameForDiagnostics: "label",
649649
description: "The label of the argument"
650650
),
@@ -677,7 +677,7 @@ public let ATTRIBUTE_NODES: [Node] = [
677677
children: [
678678
Child(
679679
name: "Name",
680-
kind: .token(choices: [.token(tokenKind: "IdentifierToken")]),
680+
kind: .node(kind: "Token"),
681681
nameForDiagnostics: "name",
682682
isOptional: true
683683
),
@@ -779,7 +779,7 @@ public let ATTRIBUTE_NODES: [Node] = [
779779
),
780780
Child(
781781
name: "Name",
782-
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .token(tokenKind: "BinaryOperatorToken"), .token(tokenKind: "PrefixOperatorToken"), .token(tokenKind: "PostfixOperatorToken")]),
782+
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .keyword(text: "self"), .keyword(text: "Self"), .keyword(text: "init"), .token(tokenKind: "BinaryOperatorToken")]),
783783
nameForDiagnostics: "base name",
784784
description: "The base name of the referenced function."
785785
),

CodeGeneration/Sources/SyntaxSupport/AvailabilityNodes.swift

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,21 @@ public let AVAILABILITY_NODES: [Node] = [
128128
kind: "Syntax",
129129
children: [
130130
Child(
131-
name: "MajorMinor",
132-
kind: .token(choices: [.token(tokenKind: "IntegerLiteralToken"), .token(tokenKind: "FloatingLiteralToken")]),
133-
description: "In case the version consists only of the major version, an integer literal that specifies the major version. In case the version consists of major and minor version number, a floating literal in which the decimal part is interpreted as the minor version."
131+
name: "Major",
132+
kind: .token(choices: [.token(tokenKind: "IntegerLiteralToken")]),
133+
description: "The major version."
134+
),
135+
Child(
136+
name: "MinorPeriod",
137+
kind: .token(choices: [.token(tokenKind: "PeriodToken")]),
138+
description: "If the version contains a minor number, the period separating the major from the minor number.",
139+
isOptional: true
140+
),
141+
Child(
142+
name: "Minor",
143+
kind: .token(choices: [.token(tokenKind: "IntegerLiteralToken")]),
144+
description: "The minor version if specified.",
145+
isOptional: true
134146
),
135147
Child(
136148
name: "PatchPeriod",
@@ -139,7 +151,7 @@ public let AVAILABILITY_NODES: [Node] = [
139151
isOptional: true
140152
),
141153
Child(
142-
name: "PatchVersion",
154+
name: "Patch",
143155
kind: .token(choices: [.token(tokenKind: "IntegerLiteralToken")]),
144156
description: "The patch version if specified.",
145157
isOptional: true

CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public let DECL_NODES: [Node] = [
1919
children: [
2020
Child(
2121
name: "Name",
22-
kind: .token(choices: [.token(tokenKind: "IdentifierToken")]),
22+
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .token(tokenKind: "BinaryOperatorToken"), .token(tokenKind: "PrefixOperatorToken"), .token(tokenKind: "PostfixOperatorToken")]),
2323
nameForDiagnostics: "name"
2424
),
2525
Child(

CodeGeneration/Sources/SyntaxSupport/Node.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,6 @@ public class Node {
162162
self.elementsSeparatedByNewline = elementsSeparatedByNewline
163163

164164
// For SyntaxCollections make sure that the elementName is set.
165-
assert(!isSyntaxCollection || elementName != nil || element != "")
165+
precondition(!isSyntaxCollection || elementName != nil || element != "")
166166
}
167167
}

CodeGeneration/Sources/Utils/SyntaxBuildableChild.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public extension Child {
6363
}
6464

6565
/// If this node is a token that can't contain arbitrary text, generate a Swift
66-
/// `assert` statement that verifies the variable with name var_name and of type
66+
/// `precondition` statement that verifies the variable with name var_name and of type
6767
/// `TokenSyntax` contains one of the supported text options. Otherwise return `nil`.
6868
func generateAssertStmtTextChoices(varName: String) -> FunctionCallExprSyntax? {
6969
guard case .token(choices: let choices, requiresLeadingSpace: _, requiresTrailingSpace: _) = kind else {
@@ -79,7 +79,7 @@ public extension Child {
7979

8080
let choicesTexts: [String]
8181
if tokenCanContainArbitraryText {
82-
// Don't generate an assert statement if token can contain arbitrary text.
82+
// Don't generate an precondition statement if token can contain arbitrary text.
8383
return nil
8484
} else if !choices.isEmpty {
8585
choicesTexts = choices.compactMap {
@@ -92,9 +92,9 @@ public extension Child {
9292
return nil
9393
}
9494

95-
var assertChoices: [ExprSyntax] = []
95+
var preconditionChoices: [ExprSyntax] = []
9696
if type.isOptional {
97-
assertChoices.append(
97+
preconditionChoices.append(
9898
ExprSyntax(
9999
SequenceExprSyntax {
100100
IdentifierExprSyntax(identifier: .identifier(varName))
@@ -105,7 +105,7 @@ public extension Child {
105105
)
106106
}
107107
for textChoice in choicesTexts {
108-
assertChoices.append(
108+
preconditionChoices.append(
109109
ExprSyntax(
110110
SequenceExprSyntax {
111111
MemberAccessExprSyntax(base: type.forceUnwrappedIfNeeded(expr: IdentifierExprSyntax(identifier: .identifier(varName))), name: "text")
@@ -115,8 +115,8 @@ public extension Child {
115115
)
116116
)
117117
}
118-
let disjunction = ExprListSyntax(assertChoices.flatMap { [$0, ExprSyntax(BinaryOperatorExprSyntax(text: "||"))] }.dropLast())
119-
return FunctionCallExprSyntax(callee: ExprSyntax("assert")) {
118+
let disjunction = ExprListSyntax(preconditionChoices.flatMap { [$0, ExprSyntax(BinaryOperatorExprSyntax(text: "||"))] }.dropLast())
119+
return FunctionCallExprSyntax(callee: ExprSyntax("precondition")) {
120120
TupleExprElementSyntax(expression: SequenceExprSyntax(elements: disjunction))
121121
}
122122
}

CodeGeneration/Sources/Utils/SyntaxBuildableNode.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ public extension Node {
4444

4545
/// Assuming this node is a syntax collection, the type of its elements.
4646
var collectionElementType: SyntaxBuildableType {
47-
assert(isSyntaxCollection)
47+
precondition(isSyntaxCollection)
4848
return SyntaxBuildableType(syntaxKind: collectionElement)
4949
}
5050

5151
/// Assuming this node has a single child without a default value, that child.
5252
var singleNonDefaultedChild: Child {
5353
let nonDefaultedParams = children.filter { $0.type.defaultInitialization == nil }
54-
assert(nonDefaultedParams.count == 1)
54+
precondition(nonDefaultedParams.count == 1)
5555
return nonDefaultedParams[0]
5656
}
5757

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftparser/ParserEntryFile.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ let parserEntryFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
7878
"""
7979
mutating func parseRemainder<R: RawSyntaxNodeProtocol>(into: R) -> R {
8080
guard !into.raw.kind.isSyntaxCollection, let layout = into.raw.layoutView else {
81-
assertionFailure("Only support parsing of non-collection layout nodes")
82-
return into
81+
preconditionFailure("Only support parsing of non-collection layout nodes")
8382
}
8483
8584
let remainingTokens = self.consumeRemainingTokens()
@@ -89,7 +88,7 @@ let parserEntryFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
8988
9089
let existingUnexpected: [RawSyntax]
9190
if let unexpectedNode = layout.children[layout.children.count - 1] {
92-
assert(unexpectedNode.is(RawUnexpectedNodesSyntax.self))
91+
precondition(unexpectedNode.is(RawUnexpectedNodesSyntax.self))
9392
existingUnexpected = unexpectedNode.as(RawUnexpectedNodesSyntax.self).elements
9493
} else {
9594
existingUnexpected = []

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/RawSyntaxNodesFile.swift

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,15 @@ let rawSyntaxNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
129129
DeclSyntax(
130130
"""
131131
init(raw: RawSyntax) {
132-
assert(Self.isKindOf(raw))
132+
precondition(Self.isKindOf(raw))
133+
self.raw = raw
134+
}
135+
"""
136+
)
137+
138+
DeclSyntax(
139+
"""
140+
private init(unchecked raw: RawSyntax) {
133141
self.raw = raw
134142
}
135143
"""
@@ -139,7 +147,7 @@ let rawSyntaxNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
139147
"""
140148
public init?<Node: RawSyntaxNodeProtocol>(_ other: Node) {
141149
guard Self.isKindOf(other.raw) else { return nil }
142-
self.init(raw: other.raw)
150+
self.init(unchecked: other.raw)
143151
}
144152
"""
145153
)
@@ -148,7 +156,7 @@ let rawSyntaxNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
148156
DeclSyntax(
149157
"""
150158
public init<Node: Raw\(raw: node.name)NodeProtocol>(_ other: Node) {
151-
self.init(raw: other.raw)
159+
self.init(unchecked: other.raw)
152160
}
153161
"""
154162
)
@@ -167,7 +175,7 @@ let rawSyntaxNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
167175
ptr += 1
168176
}
169177
}
170-
self.init(raw: raw)
178+
self.init(unchecked: raw)
171179
}
172180
"""
173181
)
@@ -217,7 +225,7 @@ let rawSyntaxNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
217225
} else {
218226
DeclSyntax("let raw = RawSyntax.makeEmptyLayout(kind: .\(raw: node.swiftSyntaxKind), arena: arena)")
219227
}
220-
ExprSyntax("self.init(raw: raw)")
228+
ExprSyntax("self.init(unchecked: raw)")
221229
}
222230

223231
for (index, child) in node.children.enumerated() {

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/RawSyntaxValidationFile.swift

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,39 @@ let rawSyntaxValidationFile = try! SourceFileSyntax(leadingTrivia: copyrightHead
3232
condition: ExprSyntax("DEBUG"),
3333
elements: .statements(
3434
try CodeBlockItemListSyntax {
35+
DeclSyntax(
36+
#"""
37+
enum TokenChoice: CustomStringConvertible {
38+
case keyword(StaticString)
39+
case tokenKind(RawTokenKind)
40+
41+
var description: String {
42+
switch self {
43+
case .keyword(let keyword):
44+
return "keyword('\(keyword)')"
45+
case .tokenKind(let kind):
46+
return "\(kind)"
47+
}
48+
}
49+
}
50+
"""#
51+
)
52+
3553
DeclSyntax(
3654
#"""
3755
enum ValidationError: CustomStringConvertible {
3856
case expectedNonNil(expectedKind: RawSyntaxNodeProtocol.Type, file: StaticString, line: UInt)
3957
case kindMismatch(expectedKind: RawSyntaxNodeProtocol.Type, actualKind: SyntaxKind, file: StaticString, line: UInt)
58+
case tokenMismatch(expectedTokenChoices: [TokenChoice], actualKind: RawTokenKind, actualText: SyntaxText, file: StaticString, line: UInt)
4059
4160
var description: String {
4261
switch self {
4362
case .expectedNonNil(expectedKind: let expectedKind, file: _, line: _):
4463
return "Expected non-nil node of type \(expectedKind) but received nil"
4564
case .kindMismatch(expectedKind: let expectedKind, actualKind: let actualKind, file: _, line: _):
4665
return "Expected node of type \(expectedKind) but received \(actualKind)"
66+
case .tokenMismatch(expectedTokenChoices: let tokenChoices, actualKind: let actualKind, actualText: let actualText, file: _, line: _):
67+
return "Expected token with one of \(tokenChoices) but received \(actualKind) with text '\(actualText)'"
4768
}
4869
}
4970
@@ -53,6 +74,8 @@ let rawSyntaxValidationFile = try! SourceFileSyntax(leadingTrivia: copyrightHead
5374
return (file, line)
5475
case .kindMismatch(expectedKind: _, actualKind: _, file: let file, line: let line):
5576
return (file, line)
77+
case .tokenMismatch(expectedTokenChoices: _, actualKind: _, actualText: _, file: let file, line: let line):
78+
return (file, line)
5679
}
5780
}
5881
}
@@ -84,6 +107,61 @@ let rawSyntaxValidationFile = try! SourceFileSyntax(leadingTrivia: copyrightHead
84107
"""
85108
)
86109

110+
DeclSyntax(
111+
"""
112+
func verify(_ raw: RawSyntax?, as _: RawTokenSyntax?.Type, tokenChoices: [TokenChoice], file: StaticString = #file, line: UInt = #line) -> ValidationError? {
113+
// Validation of token choice is currently causing assertion failures where
114+
// the list of expected token choices in the syntax tree doesn't match those
115+
// the parser generates. Disable the verification for now until all issues
116+
// regarding it are fixed.
117+
#if VALIDATE_TOKEN_CHOICES
118+
if raw != nil {
119+
return verify(raw, as: RawTokenSyntax.self, tokenChoices: tokenChoices, file: file, line: line)
120+
}
121+
return nil
122+
#else
123+
return verify(raw, as: RawTokenSyntax?.self)
124+
#endif
125+
}
126+
"""
127+
)
128+
129+
DeclSyntax(
130+
"""
131+
func verify(_ raw: RawSyntax?, as _: RawTokenSyntax.Type, tokenChoices: [TokenChoice], file: StaticString = #file, line: UInt = #line) -> ValidationError? {
132+
// Validation of token choice is currently causing assertion failures where
133+
// the list of expected token choices in the syntax tree doesn't match those
134+
// the parser generates. Disable the verification for now until all issues
135+
// regarding it are fixed.
136+
#if VALIDATE_TOKEN_CHOICES
137+
guard let raw = raw else {
138+
return .expectedNonNil(expectedKind: RawTokenSyntax.self, file: file, line: line)
139+
}
140+
if let error = verify(raw, as: RawTokenSyntax?.self) {
141+
return error
142+
}
143+
let tokenView = raw.tokenView!
144+
for tokenChoice in tokenChoices {
145+
switch tokenChoice {
146+
case .tokenKind(let tokenKind):
147+
if raw.tokenView?.rawKind == tokenKind {
148+
return nil
149+
}
150+
case .keyword(let keyword):
151+
if tokenView.rawKind == .keyword && tokenView.rawText == SyntaxText(keyword) {
152+
return nil
153+
}
154+
}
155+
}
156+
return ValidationError.tokenMismatch(expectedTokenChoices: tokenChoices, actualKind: tokenView.rawKind, actualText: tokenView.rawText, file: file, line: line)
157+
#else
158+
return verify(raw, as: RawTokenSyntax.self)
159+
#endif
160+
}
161+
162+
"""
163+
)
164+
87165
DeclSyntax(
88166
#"""
89167
func assertNoError(_ nodeKind: SyntaxKind, _ index: Int, _ error: ValidationError?) {
@@ -139,6 +217,19 @@ let rawSyntaxValidationFile = try! SourceFileSyntax(leadingTrivia: copyrightHead
139217
}
140218

141219
ExprSyntax("assertAnyHasNoError(kind, \(raw: index), \(verifiedChoices))")
220+
case .token(choices: let choices, requiresLeadingSpace: _, requiresTrailingSpace: _):
221+
let choices = ArrayExprSyntax {
222+
for choice in choices {
223+
switch choice {
224+
case .keyword(text: let text):
225+
ArrayElementSyntax(expression: ExprSyntax(#".keyword("\#(raw: text)")"#))
226+
case .token(tokenKind: let tokenKind):
227+
ArrayElementSyntax(expression: ExprSyntax(".tokenKind(.\(raw: SYNTAX_TOKEN_MAP[tokenKind]!.swiftKind))"))
228+
}
229+
}
230+
}
231+
let verifyCall = ExprSyntax("verify(layout[\(raw: index)], as: Raw\(raw: child.type.buildable).self, tokenChoices: \(choices))")
232+
ExprSyntax("assertNoError(kind, \(raw: index), \(verifyCall))")
142233
default:
143234
ExprSyntax("assertNoError(kind, \(raw: index), verify(layout[\(raw: index)], as: Raw\(raw: child.type.buildable).self))")
144235
}

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/SyntaxCollectionsFile.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ let syntaxCollectionsFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
158158
/// that the `SyntaxData` is of the correct kind. If it is not, the behaviour
159159
/// is undefined.
160160
internal init(_ data: SyntaxData) {
161-
assert(data.raw.kind == .\(raw: node.swiftSyntaxKind))
161+
precondition(data.raw.kind == .\(raw: node.swiftSyntaxKind))
162162
self._syntaxNode = Syntax(data)
163163
}
164164
"""

0 commit comments

Comments
 (0)