Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parser: recover on missing union case fields #17452

Merged
merged 5 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/9.0.100.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
### Added

* Support for nullable reference types ([PR #15181](https://github.com/dotnet/fsharp/pull/15181))
* Parser: recover on missing union case fields ([#17452](https://github.com/dotnet/fsharp/pull/17452))
* Sink: report function domain type ([PR #17470](https://github.com/dotnet/fsharp/pull/17470))

### Changed
Expand Down
3 changes: 2 additions & 1 deletion src/Compiler/FSComp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1762,7 +1762,7 @@ featureReuseSameFieldsInStructUnions,"Share underlying fields in a [<Struct>] di
3860,chkStaticMembersOnObjectExpressions,"Object expressions cannot implement interfaces with static abstract members or declare static members."
3861,chkTailCallAttrOnNonRec,"The TailCall attribute should only be applied to recursive functions."
3862,parsStaticMemberImcompleteSyntax,"Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration."
3863,parsExpectingField,"Expecting record field"
3863,parsExpectingRecordField,"Expecting record field"
3864,tooManyMethodsInDotNetTypeWritingAssembly,"The type '%s' has too many methods. Found: '%d', maximum: '%d'"
3865,parsOnlySimplePatternsAreAllowedInConstructors,"Only simple patterns are allowed in primary constructors"
3866,chkStaticAbstractInterfaceMembers,"A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.%s)."
Expand All @@ -1775,3 +1775,4 @@ featureParsedHashDirectiveArgumentNonString,"# directives with non-quoted string
3869,featureParsedHashDirectiveUnexpectedInteger,"Unexpected integer literal '%d'."
3869,featureParsedHashDirectiveUnexpectedIdentifier,"Unexpected identifier '%s'."
featureEmptyBodiedComputationExpressions,"Support for computation expressions with empty bodies: builder {{ }}"
3870,parsExpectingUnionCaseField,"Expecting union case field"
psfinaki marked this conversation as resolved.
Show resolved Hide resolved
80 changes: 59 additions & 21 deletions src/Compiler/pars.fsy
Original file line number Diff line number Diff line change
Expand Up @@ -2471,7 +2471,7 @@ braceFieldDeclList:
{ [] }

| LBRACE rbrace
{ errorR (Error(FSComp.SR.parsExpectingField(), rhs parseState 2))
{ errorR (Error(FSComp.SR.parsExpectingRecordField (), rhs parseState 2))
[] }

anonRecdType:
Expand Down Expand Up @@ -2711,17 +2711,26 @@ attrUnionCaseDecl:
{ fun (xmlDoc, mBar) -> mkSynUnionCase $1 $2 (SynIdent(mkSynId mBar.EndRange "", None)) (SynUnionCaseKind.Fields []) mBar (xmlDoc, mBar) |> Choice2Of2 }

| opt_attributes opt_access unionCaseName OF unionCaseRepr
{ mkSynUnionCase $1 $2 $3 (SynUnionCaseKind.Fields $5) (rhs2 parseState 1 5) >> Choice2Of2 }
{ let mId = rhs parseState 3
let fields, mFields = $5
let mWhole = unionRanges mId mFields
mkSynUnionCase $1 $2 $3 (SynUnionCaseKind.Fields fields) mWhole >> Choice2Of2 }

| opt_attributes opt_access unionCaseName unionCaseRepr
{ errorR (Error(FSComp.SR.parsMissingKeyword("of"), rhs2 parseState 3 4))
mkSynUnionCase $1 $2 $3 (SynUnionCaseKind.Fields $4) (rhs2 parseState 1 4) >> Choice2Of2 }
let mAttributes = rhs parseState 1
let fields, mFields = $4
let mWhole = unionRanges mAttributes mFields
mkSynUnionCase $1 $2 $3 (SynUnionCaseKind.Fields fields) mWhole >> Choice2Of2 }

| opt_attributes opt_access OF unionCaseRepr
{ let mOf = rhs parseState 3
{ let mAttributes = rhs parseState 1
let mOf = rhs parseState 3
let mId = mOf.StartRange
let fields, mFields = $4
let mWhole = unionRanges mAttributes mFields
errorR (Error(FSComp.SR.parsMissingUnionCaseName(), mOf))
mkSynUnionCase $1 $2 (SynIdent(mkSynId mId "", None)) (SynUnionCaseKind.Fields $4) (rhs2 parseState 1 4) >> Choice2Of2 }
mkSynUnionCase $1 $2 (SynIdent(mkSynId mId "", None)) (SynUnionCaseKind.Fields fields) mWhole >> Choice2Of2 }

| opt_attributes opt_access OF recover
{ let mOf = rhs parseState 3
Expand All @@ -2733,13 +2742,18 @@ attrUnionCaseDecl:
{ mkSynUnionCase $1 $2 $3 (SynUnionCaseKind.Fields []) (rhs2 parseState 1 4) >> Choice2Of2 }

| opt_attributes opt_access unionCaseName COLON topType
{ if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyWarning(lhs parseState)
mkSynUnionCase $1 $2 $3 (SynUnionCaseKind.FullType $5) (rhs2 parseState 1 5) >> Choice2Of2 }
{ let mAttributes = rhs parseState 1
let fullType, _ = $5
let mWhole = unionRanges mAttributes fullType.Range
if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyWarning(lhs parseState)
mkSynUnionCase $1 $2 $3 (SynUnionCaseKind.FullType $5) mWhole >> Choice2Of2 }

| opt_attributes opt_access unionCaseName EQUALS atomicExpr
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsEnumFieldsCannotHaveVisibilityDeclarations(), rhs parseState 2))
let mEquals = rhs parseState 4
let mDecl = rhs2 parseState 1 5
let mAttributes = rhs parseState 1
let expr, _ = $5
let mDecl = unionRanges mAttributes expr.Range
(fun (xmlDoc, mBar) ->
let trivia: SynEnumCaseTrivia = { BarRange = Some mBar; EqualsRange = mEquals }
let mDecl = unionRangeWithXmlDoc xmlDoc mDecl
Expand Down Expand Up @@ -2797,16 +2811,20 @@ firstUnionCaseDeclOfMany:

firstUnionCaseDecl:
| ident OF unionCaseRepr
{ let trivia: SynUnionCaseTrivia = { BarRange = None }
{ let fields, mFields = $3
let trivia: SynUnionCaseTrivia = { BarRange = None }
let xmlDoc = grabXmlDoc (parseState, [], 1)
let mDecl = rhs2 parseState 1 3 |> unionRangeWithXmlDoc xmlDoc
Choice2Of2(SynUnionCase([], SynIdent($1, None), SynUnionCaseKind.Fields $3, xmlDoc, None, mDecl, trivia)) }
let mId = rhs parseState 1
let mDecl = unionRanges mId mFields |> unionRangeWithXmlDoc xmlDoc
Choice2Of2(SynUnionCase([], SynIdent($1, None), SynUnionCaseKind.Fields fields, xmlDoc, None, mDecl, trivia)) }

| unionCaseName COLON topType
| unionCaseName COLON topType
{ if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyWarning(lhs parseState)
let trivia: SynUnionCaseTrivia = { BarRange = None }
let xmlDoc = grabXmlDoc (parseState, [], 1)
let mDecl = rhs2 parseState 1 3 |> unionRangeWithXmlDoc xmlDoc
let mId = rhs parseState 1
let fullType, _ = $3
let mDecl = unionRanges mId fullType.Range |> unionRangeWithXmlDoc xmlDoc
Choice2Of2(SynUnionCase([], $1, SynUnionCaseKind.FullType $3, xmlDoc, None, mDecl, trivia)) }

| ident OF recover
Expand All @@ -2818,18 +2836,21 @@ firstUnionCaseDecl:
| OF unionCaseRepr
{ let mOf = rhs parseState 1
let mId = mOf.StartRange
let fields, mFields = $2
errorR (Error(FSComp.SR.parsMissingUnionCaseName(), mOf))
let id = SynIdent(mkSynId mId "", None)
let trivia: SynUnionCaseTrivia = { BarRange = None }
let xmlDoc = grabXmlDoc (parseState, [], 1)
let mDecl = rhs2 parseState 1 2 |> unionRangeWithXmlDoc xmlDoc
Choice2Of2(SynUnionCase([], id, SynUnionCaseKind.Fields $2, xmlDoc, None, mDecl, trivia)) }
let mDecl = unionRanges mOf mFields |> unionRangeWithXmlDoc xmlDoc
Choice2Of2(SynUnionCase([], id, SynUnionCaseKind.Fields fields, xmlDoc, None, mDecl, trivia)) }

| ident EQUALS atomicExpr opt_OBLOCKSEP
{ let mEquals = rhs parseState 2
{ let mId = rhs parseState 1
let mEquals = rhs parseState 2
let trivia: SynEnumCaseTrivia = { BarRange = None; EqualsRange = mEquals }
let xmlDoc = grabXmlDoc (parseState, [], 1)
let mDecl = rhs2 parseState 1 3 |> unionRangeWithXmlDoc xmlDoc
let expr, _ = $3
let mDecl = unionRanges mId expr.Range |> unionRangeWithXmlDoc xmlDoc
Choice1Of2(SynEnumCase([], SynIdent($1, None), fst $3, xmlDoc, mDecl, trivia)) }

| ident EQUALS recover opt_OBLOCKSEP
Expand All @@ -2843,10 +2864,26 @@ firstUnionCaseDecl:

unionCaseReprElements:
| unionCaseReprElement STAR unionCaseReprElements
{ $1 :: $3 }
{ let mField = rhs parseState 1
let fields, mFields = $3
$1 :: fields, unionRanges mField mFields }

| unionCaseReprElement STAR recover
{ let mStar = rhs parseState 2
let ty = SynType.FromParseError mStar.EndRange
let field = mkSynAnonField (ty, PreXmlDoc.Empty)
[$1; field], rhs2 parseState 1 2 }

| STAR unionCaseReprElements
{ let mStar = rhs parseState 1
errorR (Error(FSComp.SR.parsExpectingUnionCaseField (), rhs parseState 1))
let fields, mFields = $2
let ty = SynType.FromParseError mStar.StartRange
let field = mkSynAnonField (ty, PreXmlDoc.Empty)
field :: fields, unionRanges mStar mFields }

| unionCaseReprElement %prec prec_toptuptyptail_prefix
{ [$1] }
{ [$1], rhs parseState 1 }

unionCaseReprElement:
| ident COLON appTypeNullableInParens
Expand All @@ -2872,7 +2909,7 @@ unionCaseReprElement:
unionCaseRepr:
| braceFieldDeclList
{ errorR(Deprecated(FSComp.SR.parsConsiderUsingSeparateRecordType(), lhs parseState))
$1 }
$1, rhs parseState 1 }

| unionCaseReprElements
{ $1 }
Expand Down Expand Up @@ -2948,7 +2985,8 @@ exconIntro:
{ SynUnionCase([], SynIdent($1, None), SynUnionCaseKind.Fields [], PreXmlDoc.Empty, None, lhs parseState, { BarRange = None }) }

| ident OF unionCaseRepr
{ SynUnionCase([], SynIdent($1, None), SynUnionCaseKind.Fields $3, PreXmlDoc.Empty, None, lhs parseState, { BarRange = None }) }
{ let fields, _ = $3
SynUnionCase([], SynIdent($1, None), SynUnionCaseKind.Fields fields, PreXmlDoc.Empty, None, lhs parseState, { BarRange = None }) }

| ident OF recover
{ SynUnionCase([], SynIdent($1, None), SynUnionCaseKind.Fields [], PreXmlDoc.Empty, None, lhs parseState, { BarRange = None }) }
Expand Down
15 changes: 10 additions & 5 deletions src/Compiler/xlf/FSComp.txt.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 10 additions & 5 deletions src/Compiler/xlf/FSComp.txt.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 10 additions & 5 deletions src/Compiler/xlf/FSComp.txt.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 10 additions & 5 deletions src/Compiler/xlf/FSComp.txt.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 10 additions & 5 deletions src/Compiler/xlf/FSComp.txt.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 10 additions & 5 deletions src/Compiler/xlf/FSComp.txt.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading