From ba6647ebf5b94823c4d6fafd1e7d5f806d915ee0 Mon Sep 17 00:00:00 2001 From: Florian Verdonck Date: Mon, 3 Apr 2023 14:06:56 +0200 Subject: [PATCH] Add parser recovery for incomplete named pat pair. (#14985) * Add parser recovery for incomplete named pat pair. * Remove newly added parser error. * Update baseline --- src/Compiler/SyntaxTree/SyntaxTree.fs | 2 +- src/Compiler/SyntaxTree/SyntaxTree.fsi | 2 +- src/Compiler/pars.fsy | 7 ++++- ...ervice.SurfaceArea.netstandard20.debug.bsl | 6 ++-- ...vice.SurfaceArea.netstandard20.release.bsl | 6 ++-- .../Pattern/NamedPatPairRecoverAfterEquals.fs | 2 ++ .../NamedPatPairRecoverAfterEquals.fs.bsl | 26 +++++++++++++++++ .../NamedPatPairRecoverAfterIdentifier.fs | 2 ++ .../NamedPatPairRecoverAfterIdentifier.fs.bsl | 28 +++++++++++++++++++ ...ParenthesesOfSynArgPatsNamePatPairs.fs.bsl | 2 +- ...airsContainsTheRangeOfTheEqualsSign.fs.bsl | 2 +- 11 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 tests/service/data/SyntaxTree/Pattern/NamedPatPairRecoverAfterEquals.fs create mode 100644 tests/service/data/SyntaxTree/Pattern/NamedPatPairRecoverAfterEquals.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Pattern/NamedPatPairRecoverAfterIdentifier.fs create mode 100644 tests/service/data/SyntaxTree/Pattern/NamedPatPairRecoverAfterIdentifier.fs.bsl diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs index e02559815..452d174c7 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fs +++ b/src/Compiler/SyntaxTree/SyntaxTree.fs @@ -881,7 +881,7 @@ type SynSimplePats = type SynArgPats = | Pats of pats: SynPat list - | NamePatPairs of pats: (Ident * range * SynPat) list * range: range * trivia: SynArgPatsNamePatPairsTrivia + | NamePatPairs of pats: (Ident * range option * SynPat) list * range: range * trivia: SynArgPatsNamePatPairsTrivia member x.Patterns = match x with diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi index c9619454d..575673804 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi @@ -1025,7 +1025,7 @@ type SynSimplePats = type SynArgPats = | Pats of pats: SynPat list - | NamePatPairs of pats: (Ident * range * SynPat) list * range: range * trivia: SynArgPatsNamePatPairsTrivia + | NamePatPairs of pats: (Ident * range option * SynPat) list * range: range * trivia: SynArgPatsNamePatPairsTrivia member Patterns: SynPat list diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 64223ea75..496d70bae 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -3133,7 +3133,12 @@ namePatPairs: namePatPair: | ident EQUALS parenPattern { let mEquals = rhs parseState 2 - ($1, mEquals, $3) } + ($1, Some mEquals, $3) } + | ident EQUALS recover + { let mEquals = rhs parseState 2 + ($1, Some mEquals, patFromParseError (SynPat.Wild mEquals.EndRange)) } + | ident recover + { ($1, None, patFromParseError (SynPat.Wild $1.idRange.EndRange)) } constrPattern: | atomicPatternLongIdent explicitValTyparDecls diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl index 5cf10db46..a55725f24 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl @@ -5770,8 +5770,8 @@ FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: FSharp.Compiler.SyntaxTrivia.Syn FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia trivia FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: FSharp.Compiler.Text.Range range -FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,FSharp.Compiler.Text.Range,FSharp.Compiler.Syntax.SynPat]] get_pats() -FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,FSharp.Compiler.Text.Range,FSharp.Compiler.Syntax.SynPat]] pats +FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range],FSharp.Compiler.Syntax.SynPat]] get_pats() +FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range],FSharp.Compiler.Syntax.SynPat]] pats FSharp.Compiler.Syntax.SynArgPats+Pats: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynPat] get_pats() FSharp.Compiler.Syntax.SynArgPats+Pats: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynPat] pats FSharp.Compiler.Syntax.SynArgPats+Tags: Int32 NamePatPairs @@ -5780,7 +5780,7 @@ FSharp.Compiler.Syntax.SynArgPats: Boolean IsNamePatPairs FSharp.Compiler.Syntax.SynArgPats: Boolean IsPats FSharp.Compiler.Syntax.SynArgPats: Boolean get_IsNamePatPairs() FSharp.Compiler.Syntax.SynArgPats: Boolean get_IsPats() -FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats NewNamePatPairs(Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,FSharp.Compiler.Text.Range,FSharp.Compiler.Syntax.SynPat]], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia) +FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats NewNamePatPairs(Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range],FSharp.Compiler.Syntax.SynPat]], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia) FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats NewPats(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynPat]) FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats+NamePatPairs FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats+Pats diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl index 5cf10db46..a55725f24 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl @@ -5770,8 +5770,8 @@ FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: FSharp.Compiler.SyntaxTrivia.Syn FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia trivia FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: FSharp.Compiler.Text.Range range -FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,FSharp.Compiler.Text.Range,FSharp.Compiler.Syntax.SynPat]] get_pats() -FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,FSharp.Compiler.Text.Range,FSharp.Compiler.Syntax.SynPat]] pats +FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range],FSharp.Compiler.Syntax.SynPat]] get_pats() +FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range],FSharp.Compiler.Syntax.SynPat]] pats FSharp.Compiler.Syntax.SynArgPats+Pats: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynPat] get_pats() FSharp.Compiler.Syntax.SynArgPats+Pats: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynPat] pats FSharp.Compiler.Syntax.SynArgPats+Tags: Int32 NamePatPairs @@ -5780,7 +5780,7 @@ FSharp.Compiler.Syntax.SynArgPats: Boolean IsNamePatPairs FSharp.Compiler.Syntax.SynArgPats: Boolean IsPats FSharp.Compiler.Syntax.SynArgPats: Boolean get_IsNamePatPairs() FSharp.Compiler.Syntax.SynArgPats: Boolean get_IsPats() -FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats NewNamePatPairs(Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,FSharp.Compiler.Text.Range,FSharp.Compiler.Syntax.SynPat]], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia) +FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats NewNamePatPairs(Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range],FSharp.Compiler.Syntax.SynPat]], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia) FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats NewPats(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynPat]) FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats+NamePatPairs FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats+Pats diff --git a/tests/service/data/SyntaxTree/Pattern/NamedPatPairRecoverAfterEquals.fs b/tests/service/data/SyntaxTree/Pattern/NamedPatPairRecoverAfterEquals.fs new file mode 100644 index 000000000..ad0c46afc --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/NamedPatPairRecoverAfterEquals.fs @@ -0,0 +1,2 @@ +match x with +| Y(z = ) -> () diff --git a/tests/service/data/SyntaxTree/Pattern/NamedPatPairRecoverAfterEquals.fs.bsl b/tests/service/data/SyntaxTree/Pattern/NamedPatPairRecoverAfterEquals.fs.bsl new file mode 100644 index 000000000..4549710df --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/NamedPatPairRecoverAfterEquals.fs.bsl @@ -0,0 +1,26 @@ +ImplFile + (ParsedImplFileInput + ("/root/Pattern/NamedPatPairRecoverAfterEquals.fs", false, + QualifiedNameOfFile NamedPatPairRecoverAfterEquals, [], [], + [SynModuleOrNamespace + ([NamedPatPairRecoverAfterEquals], false, AnonModule, + [Expr + (Match + (Yes (1,0--1,12), Ident x, + [SynMatchClause + (LongIdent + (SynLongIdent ([Y], [], [None]), None, None, + NamePatPairs + ([(z, Some (2,6--2,7), + FromParseError (Wild (2,7--2,7), (2,7--2,7)))], + (2,4--2,9), { ParenRange = (2,3--2,9) }), None, + (2,2--2,9)), None, Const (Unit, (2,13--2,15)), + (2,2--2,15), Yes, { ArrowRange = Some (2,10--2,12) + BarRange = Some (2,0--2,1) })], + (1,0--2,15), { MatchKeyword = (1,0--1,5) + WithKeyword = (1,8--1,12) }), (1,0--2,15))], + PreXmlDocEmpty, [], None, (1,0--3,0), { LeadingKeyword = None })], + (true, true), { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(2,8)-(2,9) parse error Unexpected symbol ')' in pattern diff --git a/tests/service/data/SyntaxTree/Pattern/NamedPatPairRecoverAfterIdentifier.fs b/tests/service/data/SyntaxTree/Pattern/NamedPatPairRecoverAfterIdentifier.fs new file mode 100644 index 000000000..9c207d700 --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/NamedPatPairRecoverAfterIdentifier.fs @@ -0,0 +1,2 @@ +match x with +| Y(a = 1; b = 2; c) -> () diff --git a/tests/service/data/SyntaxTree/Pattern/NamedPatPairRecoverAfterIdentifier.fs.bsl b/tests/service/data/SyntaxTree/Pattern/NamedPatPairRecoverAfterIdentifier.fs.bsl new file mode 100644 index 000000000..c288ee9ea --- /dev/null +++ b/tests/service/data/SyntaxTree/Pattern/NamedPatPairRecoverAfterIdentifier.fs.bsl @@ -0,0 +1,28 @@ +ImplFile + (ParsedImplFileInput + ("/root/Pattern/NamedPatPairRecoverAfterIdentifier.fs", false, + QualifiedNameOfFile NamedPatPairRecoverAfterIdentifier, [], [], + [SynModuleOrNamespace + ([NamedPatPairRecoverAfterIdentifier], false, AnonModule, + [Expr + (Match + (Yes (1,0--1,12), Ident x, + [SynMatchClause + (LongIdent + (SynLongIdent ([Y], [], [None]), None, None, + NamePatPairs + ([(a, Some (2,6--2,7), Const (Int32 1, (2,8--2,9))); + (b, Some (2,13--2,14), Const (Int32 2, (2,15--2,16))); + (c, None, + FromParseError (Wild (2,19--2,19), (2,19--2,19)))], + (2,4--2,20), { ParenRange = (2,3--2,20) }), None, + (2,2--2,20)), None, Const (Unit, (2,24--2,26)), + (2,2--2,26), Yes, { ArrowRange = Some (2,21--2,23) + BarRange = Some (2,0--2,1) })], + (1,0--2,26), { MatchKeyword = (1,0--1,5) + WithKeyword = (1,8--1,12) }), (1,0--2,26))], + PreXmlDocEmpty, [], None, (1,0--3,0), { LeadingKeyword = None })], + (true, true), { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(2,19)-(2,20) parse error Unexpected symbol ')' in pattern. Expected '=' or other token. diff --git a/tests/service/data/SyntaxTree/Pattern/ParenthesesOfSynArgPatsNamePatPairs.fs.bsl b/tests/service/data/SyntaxTree/Pattern/ParenthesesOfSynArgPatsNamePatPairs.fs.bsl index a875ebd4c..e260f077c 100644 --- a/tests/service/data/SyntaxTree/Pattern/ParenthesesOfSynArgPatsNamePatPairs.fs.bsl +++ b/tests/service/data/SyntaxTree/Pattern/ParenthesesOfSynArgPatsNamePatPairs.fs.bsl @@ -11,7 +11,7 @@ ImplFile (LongIdent (SynLongIdent ([OnePartData], [], [None]), None, None, NamePatPairs - ([(part1, (4,10--4,11), + ([(part1, Some (4,10--4,11), Named (SynIdent (p1, None), false, None, (4,12--4,14)))], (4,4--5,13), { ParenRange = (3,13--5,13) }), None, diff --git a/tests/service/data/SyntaxTree/Pattern/SynArgPatsNamePatPairsContainsTheRangeOfTheEqualsSign.fs.bsl b/tests/service/data/SyntaxTree/Pattern/SynArgPatsNamePatPairsContainsTheRangeOfTheEqualsSign.fs.bsl index b82db10dc..61afba6c7 100644 --- a/tests/service/data/SyntaxTree/Pattern/SynArgPatsNamePatPairsContainsTheRangeOfTheEqualsSign.fs.bsl +++ b/tests/service/data/SyntaxTree/Pattern/SynArgPatsNamePatPairsContainsTheRangeOfTheEqualsSign.fs.bsl @@ -14,7 +14,7 @@ ImplFile (LongIdent (SynLongIdent ([X], [], [None]), None, None, NamePatPairs - ([(Y, (3,7--3,8), + ([(Y, Some (3,7--3,8), Named (SynIdent (y, None), false, None, (3,9--3,10)))], (3,4--3,11), { ParenRange = (3,3--3,11) }), None, -- GitLab