Skip to content

Commit b5c9937

Browse files
committed
Handle generic parameter on enum case
1 parent 02a1330 commit b5c9937

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
@@ -1074,6 +1074,24 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
10741074
return .visitChildren
10751075
}
10761076

1077+
public override func visit(_ node: EnumCaseElementSyntax) -> SyntaxVisitorContinueKind {
1078+
if shouldSkip(node) {
1079+
return .skipChildren
1080+
}
1081+
1082+
if let unexpectedBetweenNameAndParameterClause = node.unexpectedBetweenNameAndParameterClause,
1083+
let genericParameter = unexpectedBetweenNameAndParameterClause.compactMap({ $0.as(GenericParameterClauseSyntax.self) }).only
1084+
{
1085+
addDiagnostic(
1086+
genericParameter,
1087+
.genericParamCantBeUsedInEnumCaseDecl,
1088+
handledNodes: [unexpectedBetweenNameAndParameterClause.id]
1089+
)
1090+
}
1091+
1092+
return .visitChildren
1093+
}
1094+
10771095
public override func visit(_ node: IfConfigClauseSyntax) -> SyntaxVisitorContinueKind {
10781096
if shouldSkip(node) {
10791097
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
@@ -2946,4 +2946,117 @@ final class DeclarationTests: ParserTestCase {
29462946
]
29472947
)
29482948
}
2949+
2950+
// https://github.com/apple/swift-syntax/issues/2273
2951+
func testEnumCaseWithGenericParameter() {
2952+
assertParse(
2953+
"""
2954+
enum Foo {
2955+
case foo1️⃣<T>(T)
2956+
}
2957+
""",
2958+
diagnostics: [
2959+
DiagnosticSpec(
2960+
locationMarker: "1️⃣",
2961+
message: "generic signature cannot be declared in enum 'case'"
2962+
)
2963+
]
2964+
)
2965+
2966+
assertParse(
2967+
"""
2968+
enum Foo {
2969+
case bar1️⃣<T>(param: T)
2970+
}
2971+
""",
2972+
diagnostics: [
2973+
DiagnosticSpec(
2974+
locationMarker: "1️⃣",
2975+
message: "generic signature cannot be declared in enum 'case'"
2976+
)
2977+
]
2978+
)
2979+
2980+
assertParse(
2981+
"""
2982+
enum Foo {
2983+
case baz1️⃣<T>
2984+
}
2985+
""",
2986+
diagnostics: [
2987+
DiagnosticSpec(
2988+
locationMarker: "1️⃣",
2989+
message: "generic signature cannot be declared in enum 'case'"
2990+
)
2991+
]
2992+
)
2993+
2994+
assertParse(
2995+
"""
2996+
enum Foo {
2997+
case one, two1️⃣<T>
2998+
}
2999+
""",
3000+
diagnostics: [
3001+
DiagnosticSpec(
3002+
locationMarker: "1️⃣",
3003+
message: "generic signature cannot be declared in enum 'case'"
3004+
)
3005+
]
3006+
)
3007+
3008+
assertParse(
3009+
"""
3010+
enum Foo {
3011+
case three1️⃣<T>, four
3012+
}
3013+
""",
3014+
diagnostics: [
3015+
DiagnosticSpec(
3016+
locationMarker: "1️⃣",
3017+
message: "generic signature cannot be declared in enum 'case'"
3018+
)
3019+
]
3020+
)
3021+
3022+
assertParse(
3023+
"""
3024+
enum Foo {
3025+
case five1️⃣<T>(param: T), six
3026+
}
3027+
""",
3028+
diagnostics: [
3029+
DiagnosticSpec(
3030+
locationMarker: "1️⃣",
3031+
message: "generic signature cannot be declared in enum 'case'"
3032+
)
3033+
]
3034+
)
3035+
3036+
assertParse(
3037+
"""
3038+
enum Foo {
3039+
case seven1️⃣<T>, eight2️⃣<U>
3040+
}
3041+
""",
3042+
diagnostics: [
3043+
DiagnosticSpec(
3044+
locationMarker: "1️⃣",
3045+
message: "generic signature cannot be declared in enum 'case'"
3046+
),
3047+
DiagnosticSpec(
3048+
locationMarker: "2️⃣",
3049+
message: "generic signature cannot be declared in enum 'case'"
3050+
),
3051+
]
3052+
)
3053+
3054+
assertParse(
3055+
"""
3056+
enum Foo<T> {
3057+
case five(param: T), six
3058+
}
3059+
"""
3060+
)
3061+
}
29493062
}

0 commit comments

Comments
 (0)