Skip to content

Commit 74a60dd

Browse files
committed
[Parser] Always enable abiAttribute feature
`ABIAttributeArgumentsSyntax` is still under `@_spi(ExperimentalLanguageFeatures)`. Not parsing the interior of `@abi` attribute causes catastrophic breakage to the tree. Having "unknown" syntax kind in the tree is better than dealing with structually broken trees.
1 parent d9fabf7 commit 74a60dd

File tree

5 files changed

+57
-55
lines changed

5 files changed

+57
-55
lines changed

CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift

+11
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,17 @@ public enum ExperimentalFeature: String, CaseIterable {
7676
}
7777
}
7878

79+
public var isAlwaysEnabledInParser: Bool {
80+
switch self {
81+
case .abiAttribute:
82+
// `@abi` attributes should be always parsed because not parsing its interior
83+
// breaks the tree catastrophically.
84+
return true
85+
default:
86+
return false
87+
}
88+
}
89+
7990
/// The token that represents the experimental feature case name.
8091
public var token: TokenSyntax {
8192
.identifier(rawValue)

CodeGeneration/Sources/generate-swift-syntax/templates/swiftparser/ExperimentalFeaturesFile.swift

+13
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,19 @@ let experimentalFeaturesFile = SourceFileSyntax(leadingTrivia: copyrightHeader)
4040
)
4141
}
4242

43+
try! VariableDeclSyntax(
44+
"""
45+
/// Set of features always enabled.
46+
static var alwaysEnabledFeatures: Self
47+
"""
48+
) {
49+
ArrayExprSyntax {
50+
for feature in ExperimentalFeature.allCases where feature.isAlwaysEnabledInParser {
51+
ArrayElementSyntax(expression: ExprSyntax(".\(feature.token)"))
52+
}
53+
}
54+
}
55+
4356
try! InitializerDeclSyntax(
4457
"""
4558
/// Creates a new value representing the experimental feature with the

Sources/SwiftParser/Parser.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ public struct Parser {
237237

238238
self.maximumNestingLevel = maximumNestingLevel ?? Self.defaultMaximumNestingLevel
239239
self.swiftVersion = swiftVersion ?? Self.defaultSwiftVersion
240-
self.experimentalFeatures = experimentalFeatures
240+
self.experimentalFeatures = experimentalFeatures.union(.alwaysEnabledFeatures)
241241
self.lookaheadTrackerOwner = LookaheadTrackerOwner()
242242

243243
self.lexemes = Lexer.tokenize(input, lookaheadTracker: lookaheadTrackerOwner.lookaheadTracker)

Sources/SwiftParser/generated/ExperimentalFeatures.swift

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tests/SwiftParserTest/AttributeTests.swift

+27-54
Original file line numberDiff line numberDiff line change
@@ -1007,74 +1007,64 @@ final class AttributeTests: ParserTestCase {
10071007
parameterClause: FunctionParameterClauseSyntax {},
10081008
returnClause: ReturnClauseSyntax(type: TypeSyntax("Int"))
10091009
)
1010-
) {},
1011-
experimentalFeatures: [.abiAttribute]
1010+
) {}
10121011
)
10131012

10141013
assertParse(
10151014
"""
10161015
@abi(associatedtype AssocTy)
10171016
associatedtype AssocTy
1018-
""",
1019-
experimentalFeatures: [.abiAttribute]
1017+
"""
10201018
)
10211019
assertParse(
10221020
"""
10231021
@abi(deinit)
10241022
deinit {}
1025-
""",
1026-
experimentalFeatures: [.abiAttribute]
1023+
"""
10271024
)
10281025
assertParse(
10291026
"""
10301027
enum EnumCaseDeclNotParsedAtTopLevel {
10311028
@abi(case someCase)
10321029
case someCase
10331030
}
1034-
""",
1035-
experimentalFeatures: [.abiAttribute]
1031+
"""
10361032
)
10371033
assertParse(
10381034
"""
10391035
@abi(func fn())
10401036
func fn()
1041-
""",
1042-
experimentalFeatures: [.abiAttribute]
1037+
"""
10431038
)
10441039
assertParse(
10451040
"""
10461041
@abi(init())
10471042
init() {}
1048-
""",
1049-
experimentalFeatures: [.abiAttribute]
1043+
"""
10501044
)
10511045
assertParse(
10521046
"""
10531047
@abi(subscript(i: Int) -> Element)
10541048
subscript(i: Int) -> Element {}
1055-
""",
1056-
experimentalFeatures: [.abiAttribute]
1049+
"""
10571050
)
10581051
assertParse(
10591052
"""
10601053
@abi(typealias Typealias = @escaping () -> Void)
10611054
typealias Typealias = () -> Void
1062-
""",
1063-
experimentalFeatures: [.abiAttribute]
1055+
"""
10641056
)
10651057
assertParse(
10661058
"""
10671059
@abi(let c1, c2)
10681060
let c1, c2
1069-
""",
1070-
experimentalFeatures: [.abiAttribute]
1061+
"""
10711062
)
10721063
assertParse(
10731064
"""
10741065
@abi(var v1, v2)
10751066
var v1, v2
1076-
""",
1077-
experimentalFeatures: [.abiAttribute]
1067+
"""
10781068
)
10791069

10801070
assertParse(
@@ -1089,8 +1079,7 @@ final class AttributeTests: ParserTestCase {
10891079
),
10901080
diagnostics: [
10911081
DiagnosticSpec(locationMarker: "1️⃣", message: "editor placeholder in source file")
1092-
],
1093-
experimentalFeatures: [.abiAttribute]
1082+
]
10941083
)
10951084

10961085
assertParse(
@@ -1114,8 +1103,7 @@ final class AttributeTests: ParserTestCase {
11141103
),
11151104
diagnostics: [
11161105
DiagnosticSpec(locationMarker: "1️⃣", message: "import is not permitted as ABI-providing declaration")
1117-
],
1118-
experimentalFeatures: [.abiAttribute]
1106+
]
11191107
)
11201108

11211109
//
@@ -1126,66 +1114,57 @@ final class AttributeTests: ParserTestCase {
11261114
"""
11271115
@abi(associatedtype AssocTy = T)
11281116
associatedtype AssocTy
1129-
""",
1130-
experimentalFeatures: [.abiAttribute]
1117+
"""
11311118
)
11321119
assertParse(
11331120
"""
11341121
@abi(deinit {})
11351122
deinit {}
1136-
""",
1137-
experimentalFeatures: [.abiAttribute]
1123+
"""
11381124
)
11391125
assertParse(
11401126
"""
11411127
enum EnumCaseDeclNotParsedAtTopLevel {
11421128
@abi(case someCase = 42)
11431129
case someCase
11441130
}
1145-
""",
1146-
experimentalFeatures: [.abiAttribute]
1131+
"""
11471132
)
11481133
assertParse(
11491134
"""
11501135
@abi(func fn() {})
11511136
func fn()
1152-
""",
1153-
experimentalFeatures: [.abiAttribute]
1137+
"""
11541138
)
11551139
assertParse(
11561140
"""
11571141
@abi(init() {})
11581142
init() {}
1159-
""",
1160-
experimentalFeatures: [.abiAttribute]
1143+
"""
11611144
)
11621145
assertParse(
11631146
"""
11641147
@abi(subscript(i: Int) -> Element { get {} set {} })
11651148
subscript(i: Int) -> Element {}
1166-
""",
1167-
experimentalFeatures: [.abiAttribute]
1149+
"""
11681150
)
11691151
assertParse(
11701152
"""
11711153
@abi(let c1 = 1, c2 = 2)
11721154
let c1, c2
1173-
""",
1174-
experimentalFeatures: [.abiAttribute]
1155+
"""
11751156
)
11761157
assertParse(
11771158
"""
11781159
@abi(var v1 = 1, v2 = 2)
11791160
var v1, v2
1180-
""",
1181-
experimentalFeatures: [.abiAttribute]
1161+
"""
11821162
)
11831163
assertParse(
11841164
"""
11851165
@abi(var v3 { get {} set {} })
11861166
var v3
1187-
""",
1188-
experimentalFeatures: [.abiAttribute]
1167+
"""
11891168
)
11901169

11911170
//
@@ -1207,8 +1186,7 @@ final class AttributeTests: ParserTestCase {
12071186
fixedSource: """
12081187
@abi(var <#pattern#>)
12091188
var v1
1210-
""",
1211-
experimentalFeatures: [.abiAttribute]
1189+
"""
12121190
)
12131191
assertParse(
12141192
"""
@@ -1231,8 +1209,7 @@ final class AttributeTests: ParserTestCase {
12311209
fixedSource: """
12321210
@abi(var v2)
12331211
var v2
1234-
""",
1235-
experimentalFeatures: [.abiAttribute]
1212+
"""
12361213
)
12371214
assertParse(
12381215
"""
@@ -1250,8 +1227,7 @@ final class AttributeTests: ParserTestCase {
12501227
fixedSource: """
12511228
@abi(<#declaration#>)
12521229
func fn2() {}
1253-
""",
1254-
experimentalFeatures: [.abiAttribute]
1230+
"""
12551231
)
12561232
assertParse(
12571233
"""
@@ -1268,8 +1244,7 @@ final class AttributeTests: ParserTestCase {
12681244
fixedSource: """
12691245
@abi(<#declaration#>)
12701246
func fn3() {}
1271-
""",
1272-
experimentalFeatures: [.abiAttribute]
1247+
"""
12731248
)
12741249
assertParse(
12751250
"""
@@ -1291,8 +1266,7 @@ final class AttributeTests: ParserTestCase {
12911266
fixedSource: """
12921267
@abi(<#declaration#>) func fn4_abi())
12931268
func fn4() {}
1294-
""",
1295-
experimentalFeatures: [.abiAttribute]
1269+
"""
12961270
)
12971271

12981272
// `#if` is banned inside an `@abi` attribute.
@@ -1325,8 +1299,7 @@ final class AttributeTests: ParserTestCase {
13251299
func _fn<E: Error>() throws(E)
13261300
)
13271301
func fn<E: Error>() throws(E) {}
1328-
""",
1329-
experimentalFeatures: [.abiAttribute]
1302+
"""
13301303
)
13311304
}
13321305

0 commit comments

Comments
 (0)