Skip to content

Commit ff6e13d

Browse files
authored
Parser: recover on missing union case names or representations (#15058)
1 parent 630be62 commit ff6e13d

39 files changed

+544
-15
lines changed

src/Compiler/Checking/CheckDeclarations.fs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,10 @@ module TcRecdUnionAndEnumDeclarations =
558558
Construct.NewUnionCase id rfields recordTy attrs xmlDoc vis
559559

560560
let TcUnionCaseDecls (cenv: cenv) env (parent: ParentRef) (thisTy: TType) (thisTyInst: TypeInst) hasRQAAttribute tpenv unionCases =
561-
let unionCasesR = unionCases |> List.map (TcUnionCaseDecl cenv env parent thisTy thisTyInst tpenv hasRQAAttribute)
561+
let unionCasesR =
562+
unionCases
563+
|> List.filter (fun (SynUnionCase(_, SynIdent(id, _), _, _, _, _, _)) -> id.idText <> "")
564+
|> List.map (TcUnionCaseDecl cenv env parent thisTy thisTyInst tpenv hasRQAAttribute)
562565
unionCasesR |> CheckDuplicates (fun uc -> uc.Id) "union case"
563566

564567
let MakeEnumCaseSpec cenv env parent attrs thisTy caseRange (caseIdent: Ident) (xmldoc: PreXmlDoc) value =

src/Compiler/FSComp.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,4 +1685,5 @@ featureEscapeBracesInFormattableString,"Escapes curly braces before calling Form
16851685
3561,chkAutoOpenAttributeInTypeAbbrev,"FSharp.Core.AutoOpenAttribute should not be aliased."
16861686
3562,parsUnexpectedEndOfFileElif,"Unexpected end of input in 'else if' or 'elif' branch of conditional expression. Expected 'elif <expr> then <expr>' or 'else if <expr> then <expr>'."
16871687
3563,lexInvalidIdentifier,"This is not a valid identifier"
1688+
3564,parsMissingUnionCaseName,"Missing union case name"
16881689
3565,parsExpectingType,"Expecting type"

src/Compiler/pars.fsy

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2387,6 +2387,14 @@ attrUnionCaseDecl:
23872387
let mDecl = unionRangeWithXmlDoc xmlDoc mDecl
23882388
Choice2Of2 (SynUnionCase ( $1, $3, SynUnionCaseKind.Fields [], xmlDoc, None, mDecl, trivia))) }
23892389

2390+
| opt_attributes opt_access recover
2391+
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2))
2392+
(fun (xmlDoc, mBar) ->
2393+
let id = SynIdent(mkSynId mBar.EndRange "", None)
2394+
let trivia: SynUnionCaseTrivia = { BarRange = Some mBar }
2395+
let mDecl = unionRangeWithXmlDoc xmlDoc mBar
2396+
Choice2Of2 (SynUnionCase ( $1, id, SynUnionCaseKind.Fields [], xmlDoc, None, mDecl, trivia))) }
2397+
23902398
| opt_attributes opt_access unionCaseName OF unionCaseRepr
23912399
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2))
23922400
let mDecl = rhs2 parseState 1 5
@@ -2395,6 +2403,30 @@ attrUnionCaseDecl:
23952403
let mDecl = unionRangeWithXmlDoc xmlDoc mDecl
23962404
Choice2Of2 (SynUnionCase ( $1, $3, SynUnionCaseKind.Fields $5, xmlDoc, None, mDecl, trivia))) }
23972405

2406+
| opt_attributes opt_access OF unionCaseRepr
2407+
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2))
2408+
let mOf = rhs parseState 3
2409+
let mId = mOf.StartRange
2410+
errorR (Error(FSComp.SR.parsMissingUnionCaseName(), mOf))
2411+
let mDecl = rhs2 parseState 1 4
2412+
(fun (xmlDoc, mBar) ->
2413+
let id = SynIdent(mkSynId mId "", None)
2414+
let trivia: SynUnionCaseTrivia = { BarRange = Some mBar }
2415+
let mDecl = unionRangeWithXmlDoc xmlDoc mDecl
2416+
Choice2Of2(SynUnionCase($1, id, SynUnionCaseKind.Fields $4, xmlDoc, None, mDecl, trivia))) }
2417+
2418+
| opt_attributes opt_access OF recover
2419+
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2))
2420+
let mOf = rhs parseState 3
2421+
let mId = mOf.StartRange
2422+
errorR (Error(FSComp.SR.parsMissingUnionCaseName(), mOf))
2423+
let mDecl = rhs2 parseState 1 3
2424+
(fun (xmlDoc, mBar) ->
2425+
let id = SynIdent(mkSynId mId "", None)
2426+
let trivia: SynUnionCaseTrivia = { BarRange = Some mBar }
2427+
let mDecl = unionRangeWithXmlDoc xmlDoc mDecl
2428+
Choice2Of2(SynUnionCase($1, id, SynUnionCaseKind.Fields [], xmlDoc, None, mDecl, trivia))) }
2429+
23982430
| opt_attributes opt_access unionCaseName OF recover
23992431
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2))
24002432
let mDecl = rhs2 parseState 1 4
@@ -2453,19 +2485,35 @@ firstUnionCaseDeclOfMany:
24532485
| firstUnionCaseDecl opt_OBLOCKSEP
24542486
{ $1 }
24552487

2456-
firstUnionCaseDecl:
2457-
| ident OF unionCaseRepr
2458-
{ let trivia: SynUnionCaseTrivia = { BarRange = None }
2459-
let xmlDoc = grabXmlDoc(parseState, [], 1)
2460-
let mDecl = rhs2 parseState 1 3 |> unionRangeWithXmlDoc xmlDoc
2461-
Choice2Of2 (SynUnionCase ( [], SynIdent($1, None), SynUnionCaseKind.Fields $3, xmlDoc, None, mDecl, trivia)) }
2488+
firstUnionCaseDecl:
2489+
| ident OF unionCaseRepr
2490+
{ let trivia: SynUnionCaseTrivia = { BarRange = None }
2491+
let xmlDoc = grabXmlDoc (parseState, [], 1)
2492+
let mDecl = rhs2 parseState 1 3 |> unionRangeWithXmlDoc xmlDoc
2493+
Choice2Of2(SynUnionCase([], SynIdent($1, None), SynUnionCaseKind.Fields $3, xmlDoc, None, mDecl, trivia)) }
2494+
2495+
| ident OF recover
2496+
{ let trivia: SynUnionCaseTrivia = { BarRange = None }
2497+
let xmlDoc = grabXmlDoc (parseState, [], 1)
2498+
let mDecl = rhs2 parseState 1 2 |> unionRangeWithXmlDoc xmlDoc
2499+
Choice2Of2(SynUnionCase([], SynIdent($1, None), SynUnionCaseKind.Fields [], xmlDoc, None, mDecl, trivia)) }
2500+
2501+
| OF unionCaseRepr
2502+
{ let mOf = rhs parseState 1
2503+
let mId = mOf.StartRange
2504+
errorR (Error(FSComp.SR.parsMissingUnionCaseName(), mOf))
2505+
let id = SynIdent(mkSynId mId "", None)
2506+
let trivia: SynUnionCaseTrivia = { BarRange = None }
2507+
let xmlDoc = grabXmlDoc (parseState, [], 1)
2508+
let mDecl = rhs2 parseState 1 2 |> unionRangeWithXmlDoc xmlDoc
2509+
Choice2Of2(SynUnionCase([], id, SynUnionCaseKind.Fields $2, xmlDoc, None, mDecl, trivia)) }
24622510

24632511
| ident EQUALS atomicExpr opt_OBLOCKSEP
24642512
{ let mEquals = rhs parseState 2
24652513
let trivia: SynEnumCaseTrivia = { BarRange = None; EqualsRange = mEquals }
2466-
let xmlDoc = grabXmlDoc(parseState, [], 1)
2514+
let xmlDoc = grabXmlDoc (parseState, [], 1)
24672515
let mDecl = rhs2 parseState 1 3 |> unionRangeWithXmlDoc xmlDoc
2468-
Choice1Of2 (SynEnumCase ([], SynIdent($1, None), fst $3, xmlDoc, mDecl, trivia)) }
2516+
Choice1Of2(SynEnumCase([], SynIdent($1, None), fst $3, xmlDoc, mDecl, trivia)) }
24692517

24702518
unionCaseReprElements:
24712519
| unionCaseReprElement STAR unionCaseReprElements

src/Compiler/xlf/FSComp.txt.cs.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,11 @@
777777
<target state="translated">Neúplný výraz operátoru (například^b) nebo volání kvalifikovaného typu (příklad: ^T.Name)</target>
778778
<note />
779779
</trans-unit>
780+
<trans-unit id="parsMissingUnionCaseName">
781+
<source>Missing union case name</source>
782+
<target state="new">Missing union case name</target>
783+
<note />
784+
</trans-unit>
780785
<trans-unit id="parsNewExprMemberAccess">
781786
<source>This member access is ambiguous. Please use parentheses around the object creation, e.g. '(new SomeType(args)).MemberName'</source>
782787
<target state="translated">Tento přístup člena je nejednoznačný. Při vytváření objektu použijte závorky, např. (new SomeType(args)).MemberName'</target>

src/Compiler/xlf/FSComp.txt.de.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,11 @@
777777
<target state="translated">Unvollständiger Operatorausdruck (Beispiel: a^b) oder qualifizierter Typaufruf (Beispiel: ^T.Name)</target>
778778
<note />
779779
</trans-unit>
780+
<trans-unit id="parsMissingUnionCaseName">
781+
<source>Missing union case name</source>
782+
<target state="new">Missing union case name</target>
783+
<note />
784+
</trans-unit>
780785
<trans-unit id="parsNewExprMemberAccess">
781786
<source>This member access is ambiguous. Please use parentheses around the object creation, e.g. '(new SomeType(args)).MemberName'</source>
782787
<target state="translated">Dieser Memberzugriff ist mehrdeutig. Setzen Sie Klammern um die Objekterstellung, z. B. "(new SomeType(args)). MemberName“</target>

src/Compiler/xlf/FSComp.txt.es.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,11 @@
777777
<target state="translated">Expresión de operador incompleta (ejemplo, a^b) o invocación de tipo calificada (ejemplo: ^T.Name)</target>
778778
<note />
779779
</trans-unit>
780+
<trans-unit id="parsMissingUnionCaseName">
781+
<source>Missing union case name</source>
782+
<target state="new">Missing union case name</target>
783+
<note />
784+
</trans-unit>
780785
<trans-unit id="parsNewExprMemberAccess">
781786
<source>This member access is ambiguous. Please use parentheses around the object creation, e.g. '(new SomeType(args)).MemberName'</source>
782787
<target state="translated">Este acceso de miembro es ambiguo. Use paréntesis alrededor de la creación del objeto, por ejemplo, '(nuevo AlgúnTipo(args)).NombreMiembro'</target>

src/Compiler/xlf/FSComp.txt.fr.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,11 @@
777777
<target state="translated">Expression d’opérateur incomplète (exemple a^b) ou appel de type qualifié (exemple : ^T.Name)</target>
778778
<note />
779779
</trans-unit>
780+
<trans-unit id="parsMissingUnionCaseName">
781+
<source>Missing union case name</source>
782+
<target state="new">Missing union case name</target>
783+
<note />
784+
</trans-unit>
780785
<trans-unit id="parsNewExprMemberAccess">
781786
<source>This member access is ambiguous. Please use parentheses around the object creation, e.g. '(new SomeType(args)).MemberName'</source>
782787
<target state="translated">L’accès à ce membre est ambigu. Utilisez des parenthèses autour de la création de l’objet, par exemple' (New SomeType (args)). MemberName</target>

src/Compiler/xlf/FSComp.txt.it.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,11 @@
777777
<target state="translated">Espressione operatore incompleta (ad esempio a^b) o chiamata di tipo qualificato (ad esempio: ^T.Name)</target>
778778
<note />
779779
</trans-unit>
780+
<trans-unit id="parsMissingUnionCaseName">
781+
<source>Missing union case name</source>
782+
<target state="new">Missing union case name</target>
783+
<note />
784+
</trans-unit>
780785
<trans-unit id="parsNewExprMemberAccess">
781786
<source>This member access is ambiguous. Please use parentheses around the object creation, e.g. '(new SomeType(args)).MemberName'</source>
782787
<target state="translated">L'accesso ai membri è ambiguo. Utilizzare le parentesi intorno alla creazione oggetto, ad esempio “(New SomeType (args)). MemberName”</target>

src/Compiler/xlf/FSComp.txt.ja.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,11 @@
777777
<target state="translated">不完全な演算子式 (例 a^b) または修飾型の呼び出し (例: ^T.Name)</target>
778778
<note />
779779
</trans-unit>
780+
<trans-unit id="parsMissingUnionCaseName">
781+
<source>Missing union case name</source>
782+
<target state="new">Missing union case name</target>
783+
<note />
784+
</trans-unit>
780785
<trans-unit id="parsNewExprMemberAccess">
781786
<source>This member access is ambiguous. Please use parentheses around the object creation, e.g. '(new SomeType(args)).MemberName'</source>
782787
<target state="translated">このメンバーへのアクセスはあいまいです。オブジェクト作成の前後にはかっこを使用してください。例: '(new SomeType(args)).MemberName'</target>

src/Compiler/xlf/FSComp.txt.ko.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,11 @@
777777
<target state="translated">불완전한 연산자 식(예: a^b) 또는 정규화된 형식 호출(예: ^T.Name)</target>
778778
<note />
779779
</trans-unit>
780+
<trans-unit id="parsMissingUnionCaseName">
781+
<source>Missing union case name</source>
782+
<target state="new">Missing union case name</target>
783+
<note />
784+
</trans-unit>
780785
<trans-unit id="parsNewExprMemberAccess">
781786
<source>This member access is ambiguous. Please use parentheses around the object creation, e.g. '(new SomeType(args)).MemberName'</source>
782787
<target state="translated">이 구성원 액세스가 모호합니다. 개체 생성 주위에 괄호를 사용하세요. 예: '(새로운 SomeType(인수)).MemberName'</target>

0 commit comments

Comments
 (0)