Skip to content

Commit 624fe5b

Browse files
committed
Handle generic parameter on enum case
1 parent e8659bb commit 624fe5b

File tree

4 files changed

+143
-0
lines changed

4 files changed

+143
-0
lines changed

Sources/SwiftParser/Declarations.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,14 @@ extension Parser {
808808
let unexpectedPeriod = self.consume(if: .period)
809809
let (unexpectedBeforeName, name) = self.expectIdentifier(keywordRecovery: true)
810810

811+
let unexpectedGenericParameters: RawUnexpectedNodesSyntax?
812+
if self.at(prefix: "<") {
813+
let genericParameters = self.parseGenericParameters()
814+
unexpectedGenericParameters = RawUnexpectedNodesSyntax([genericParameters], arena: self.arena)
815+
} else {
816+
unexpectedGenericParameters = nil
817+
}
818+
811819
let parameterClause: RawEnumCaseParameterClauseSyntax?
812820
if self.at(TokenSpec(.leftParen)) {
813821
parameterClause = self.parseParameterClause(RawEnumCaseParameterClauseSyntax.self) { parser in
@@ -836,6 +844,7 @@ extension Parser {
836844
RawEnumCaseElementSyntax(
837845
RawUnexpectedNodesSyntax(combining: unexpectedPeriod, unexpectedBeforeName, arena: self.arena),
838846
name: name,
847+
unexpectedGenericParameters,
839848
parameterClause: parameterClause,
840849
rawValue: rawValue,
841850
trailingComma: keepGoing,

Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,24 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
10771077
return .visitChildren
10781078
}
10791079

1080+
public override func visit(_ node: EnumCaseElementSyntax) -> SyntaxVisitorContinueKind {
1081+
if shouldSkip(node) {
1082+
return .skipChildren
1083+
}
1084+
1085+
if let unexpectedBetweenNameAndParameterClause = node.unexpectedBetweenNameAndParameterClause,
1086+
let genericParameter = unexpectedBetweenNameAndParameterClause.compactMap({ $0.as(GenericParameterClauseSyntax.self) }).only
1087+
{
1088+
addDiagnostic(
1089+
genericParameter,
1090+
.genericParamCantBeUsedInEnumCaseDecl,
1091+
handledNodes: [unexpectedBetweenNameAndParameterClause.id]
1092+
)
1093+
}
1094+
1095+
return .visitChildren
1096+
}
1097+
10801098
public override func visit(_ node: IfConfigClauseSyntax) -> SyntaxVisitorContinueKind {
10811099
if shouldSkip(node) {
10821100
return .skipChildren

Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@ extension DiagnosticMessage where Self == StaticParserError {
167167
public static var forbiddenInterpolatedString: Self {
168168
return .init("argument cannot be an interpolated string literal")
169169
}
170+
public static var genericParamCantBeUsedInEnumCaseDecl: Self {
171+
return .init("generic signature cannot be declared in enum 'case'")
172+
}
170173
public static var initializerInPattern: Self {
171174
.init("unexpected initializer in pattern; did you mean to use '='?")
172175
}

Tests/SwiftParserTest/DeclarationTests.swift

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2934,4 +2934,117 @@ final class DeclarationTests: ParserTestCase {
29342934
]
29352935
)
29362936
}
2937+
2938+
// https://github.com/apple/swift-syntax/issues/2273
2939+
func testEnumCaseWithGenericParameter() {
2940+
assertParse(
2941+
"""
2942+
enum Foo {
2943+
case foo1️⃣<T>(T)
2944+
}
2945+
""",
2946+
diagnostics: [
2947+
DiagnosticSpec(
2948+
locationMarker: "1️⃣",
2949+
message: "generic signature cannot be declared in enum 'case'"
2950+
)
2951+
]
2952+
)
2953+
2954+
assertParse(
2955+
"""
2956+
enum Foo {
2957+
case bar1️⃣<T>(param: T)
2958+
}
2959+
""",
2960+
diagnostics: [
2961+
DiagnosticSpec(
2962+
locationMarker: "1️⃣",
2963+
message: "generic signature cannot be declared in enum 'case'"
2964+
)
2965+
]
2966+
)
2967+
2968+
assertParse(
2969+
"""
2970+
enum Foo {
2971+
case baz1️⃣<T>
2972+
}
2973+
""",
2974+
diagnostics: [
2975+
DiagnosticSpec(
2976+
locationMarker: "1️⃣",
2977+
message: "generic signature cannot be declared in enum 'case'"
2978+
)
2979+
]
2980+
)
2981+
2982+
assertParse(
2983+
"""
2984+
enum Foo {
2985+
case one, two1️⃣<T>
2986+
}
2987+
""",
2988+
diagnostics: [
2989+
DiagnosticSpec(
2990+
locationMarker: "1️⃣",
2991+
message: "generic signature cannot be declared in enum 'case'"
2992+
)
2993+
]
2994+
)
2995+
2996+
assertParse(
2997+
"""
2998+
enum Foo {
2999+
case three1️⃣<T>, four
3000+
}
3001+
""",
3002+
diagnostics: [
3003+
DiagnosticSpec(
3004+
locationMarker: "1️⃣",
3005+
message: "generic signature cannot be declared in enum 'case'"
3006+
)
3007+
]
3008+
)
3009+
3010+
assertParse(
3011+
"""
3012+
enum Foo {
3013+
case five1️⃣<T>(param: T), six
3014+
}
3015+
""",
3016+
diagnostics: [
3017+
DiagnosticSpec(
3018+
locationMarker: "1️⃣",
3019+
message: "generic signature cannot be declared in enum 'case'"
3020+
)
3021+
]
3022+
)
3023+
3024+
assertParse(
3025+
"""
3026+
enum Foo {
3027+
case seven1️⃣<T>, eight2️⃣<U>
3028+
}
3029+
""",
3030+
diagnostics: [
3031+
DiagnosticSpec(
3032+
locationMarker: "1️⃣",
3033+
message: "generic signature cannot be declared in enum 'case'"
3034+
),
3035+
DiagnosticSpec(
3036+
locationMarker: "2️⃣",
3037+
message: "generic signature cannot be declared in enum 'case'"
3038+
),
3039+
]
3040+
)
3041+
3042+
assertParse(
3043+
"""
3044+
enum Foo<T> {
3045+
case five(param: T), six
3046+
}
3047+
"""
3048+
)
3049+
}
29373050
}

0 commit comments

Comments
 (0)