From da4c02d92c97a97eeb28ae33d9d718fa1c1c9bf3 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Thu, 7 Mar 2024 16:40:29 -0400 Subject: [PATCH 1/6] Parser: more unfinished member recovery --- src/Compiler/pars.fsy | 3 +- .../Expression/Object - Class 07.fs.bsl | 2 +- .../Expression/Object - Class 08.fs.bsl | 2 +- .../Expression/Object - Class 09.fs.bsl | 2 +- .../data/SyntaxTree/Member/Member 08.fs.bsl | 2 +- .../data/SyntaxTree/Member/Member 10.fs.bsl | 2 +- .../data/SyntaxTree/Member/Member 12.fs.bsl | 2 +- .../data/SyntaxTree/Member/Member 13.fs | 9 +++ .../data/SyntaxTree/Member/Member 13.fs.bsl | 77 +++++++++++++++++++ 9 files changed, 94 insertions(+), 7 deletions(-) create mode 100644 tests/service/data/SyntaxTree/Member/Member 13.fs create mode 100644 tests/service/data/SyntaxTree/Member/Member 13.fs.bsl diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 4080fc7ec8..e69c0e1bf1 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -1910,7 +1910,7 @@ memberCore: let memberRange = unionRanges rangeStart mEnd |> unionRangeWithXmlDoc xmlDoc [ SynMemberDefn.Member (binding, memberRange) ] } - | opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints recover + | opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints ends_coming_soon_or_recover { let optReturnType = $3 let bindingPat, mBindLhs = $2 let mEnd = @@ -1918,6 +1918,7 @@ memberCore: | Some(_, ty) -> ty.Range.EndRange | _ -> bindingPat.Range.EndRange let expr = arbExpr ("memberCore2", mEnd) + errorR (Error(FSComp.SR.parsMissingMemberBody(), rhs parseState 4)) fun vis flagsBuilderAndLeadingKeyword attrs rangeStart -> let xmlDoc = grabXmlDocAtRangeStart(parseState, attrs, rangeStart) diff --git a/tests/service/data/SyntaxTree/Expression/Object - Class 07.fs.bsl b/tests/service/data/SyntaxTree/Expression/Object - Class 07.fs.bsl index 02f2b2c4bb..eeaef3fd16 100644 --- a/tests/service/data/SyntaxTree/Expression/Object - Class 07.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Object - Class 07.fs.bsl @@ -35,4 +35,4 @@ ImplFile { ConditionalDirectives = [] CodeComments = [] }, set [])) -(4,17)-(4,18) parse error Incomplete structured construct at or before this point in object expression. Expected 'with', '=' or other token. +(4,17)-(4,18) parse error Expecting member body diff --git a/tests/service/data/SyntaxTree/Expression/Object - Class 08.fs.bsl b/tests/service/data/SyntaxTree/Expression/Object - Class 08.fs.bsl index da2aa3f44b..f7c76b0b8f 100644 --- a/tests/service/data/SyntaxTree/Expression/Object - Class 08.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Object - Class 08.fs.bsl @@ -36,4 +36,4 @@ ImplFile CodeComments = [] }, set [])) (4,18)-(4,19) parse error Identifier expected -(4,18)-(4,19) parse error Incomplete structured construct at or before this point in object expression. Expected 'with', '=' or other token. +(4,18)-(4,19) parse error Expecting member body diff --git a/tests/service/data/SyntaxTree/Expression/Object - Class 09.fs.bsl b/tests/service/data/SyntaxTree/Expression/Object - Class 09.fs.bsl index 5fc6874100..831deffbea 100644 --- a/tests/service/data/SyntaxTree/Expression/Object - Class 09.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Object - Class 09.fs.bsl @@ -38,4 +38,4 @@ ImplFile { ConditionalDirectives = [] CodeComments = [] }, set [])) -(4,19)-(4,20) parse error Incomplete structured construct at or before this point in object expression. Expected 'with', '=' or other token. +(4,19)-(4,20) parse error Expecting member body diff --git a/tests/service/data/SyntaxTree/Member/Member 08.fs.bsl b/tests/service/data/SyntaxTree/Member/Member 08.fs.bsl index d7a7eda73e..b2e10558c6 100644 --- a/tests/service/data/SyntaxTree/Member/Member 08.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Member 08.fs.bsl @@ -76,4 +76,4 @@ ImplFile { ConditionalDirectives = [] CodeComments = [] }, set [])) -(5,0)-(5,0) parse error Incomplete structured construct at or before this point in member definition. Expected 'with', '=' or other token. +(5,0)-(5,0) parse error Expecting member body diff --git a/tests/service/data/SyntaxTree/Member/Member 10.fs.bsl b/tests/service/data/SyntaxTree/Member/Member 10.fs.bsl index 5749df6a18..e0e6936d61 100644 --- a/tests/service/data/SyntaxTree/Member/Member 10.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Member 10.fs.bsl @@ -45,4 +45,4 @@ ImplFile { ConditionalDirectives = [] CodeComments = [] }, set [])) -(7,0)-(7,0) parse error Incomplete structured construct at or before this point in member definition. Expected 'with', '=' or other token. +(7,0)-(7,0) parse error Expecting member body diff --git a/tests/service/data/SyntaxTree/Member/Member 12.fs.bsl b/tests/service/data/SyntaxTree/Member/Member 12.fs.bsl index 94ece410c4..44e361be81 100644 --- a/tests/service/data/SyntaxTree/Member/Member 12.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Member 12.fs.bsl @@ -43,4 +43,4 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,1) parse error Identifier expected -(6,0)-(6,1) parse error Incomplete structured construct at or before this point in member definition. Expected 'with', '=' or other token. +(6,0)-(6,1) parse error Expecting member body diff --git a/tests/service/data/SyntaxTree/Member/Member 13.fs b/tests/service/data/SyntaxTree/Member/Member 13.fs new file mode 100644 index 0000000000..98b5bc0864 --- /dev/null +++ b/tests/service/data/SyntaxTree/Member/Member 13.fs @@ -0,0 +1,9 @@ +module Module + +type A = + static member P: + +type B = + | A of int + +() diff --git a/tests/service/data/SyntaxTree/Member/Member 13.fs.bsl b/tests/service/data/SyntaxTree/Member/Member 13.fs.bsl new file mode 100644 index 0000000000..129c9f529c --- /dev/null +++ b/tests/service/data/SyntaxTree/Member/Member 13.fs.bsl @@ -0,0 +1,77 @@ +ImplFile + (ParsedImplFileInput + ("/root/Member/Member 13.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [A], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (3,5--3,6)), + ObjectModel + (Unspecified, + [Member + (SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (Some { IsInstance = false + IsDispatchSlot = false + IsOverrideOrExplicitImpl = false + IsFinal = false + GetterOrSetterIsCompilerGenerated = false + MemberKind = Member }, + SynValInfo ([[]], SynArgInfo ([], false, None)), + None), + LongIdent + (SynLongIdent ([P], [], [None]), None, None, + Pats [], None, (4,18--4,19)), + Some + (SynBindingReturnInfo + (FromParseError (4,20--4,20), (4,20--4,20), [], + { ColonRange = Some (4,19--4,20) })), + Typed + (ArbitraryAfterError ("memberCore2", (4,20--4,20)), + FromParseError (4,20--4,20), (4,20--4,20)), + (4,18--4,19), NoneAtInvisible, + { LeadingKeyword = + StaticMember ((4,4--4,10), (4,11--4,17)) + InlineKeyword = None + EqualsRange = None }), (4,4--4,20))], (4,4--4,20)), + [], None, (3,5--4,20), { LeadingKeyword = Type (3,0--3,4) + EqualsRange = Some (3,7--3,8) + WithKeyword = None })], (3,0--4,20)); + Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [B], + PreXmlDoc ((6,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (6,5--6,6)), + Simple + (Union + (None, + [SynUnionCase + ([], SynIdent (A, None), + Fields + [SynField + ([], false, None, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((7,11), FSharp.Compiler.Xml.XmlDocCollector), + None, (7,11--7,14), { LeadingKeyword = None + MutableKeyword = None })], + PreXmlDoc ((7,4), FSharp.Compiler.Xml.XmlDocCollector), + None, (7,6--7,14), { BarRange = Some (7,4--7,5) })], + (7,4--7,14)), (7,4--7,14)), [], None, (6,5--7,14), + { LeadingKeyword = Type (6,0--6,4) + EqualsRange = Some (6,7--6,8) + WithKeyword = None })], (6,0--7,14)); + Expr (Const (Unit, (9,0--9,2)), (9,0--9,2))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--9,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(6,0)-(6,4) parse error Incomplete structured construct at or before this point in member definition +(6,0)-(6,4) parse error Expecting member body From 47dcb304850e3157553c369c6ed4caf910fbe692 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Thu, 7 Mar 2024 16:51:04 -0400 Subject: [PATCH 2/6] Release notes --- docs/release-notes/.FSharp.Compiler.Service/8.0.300.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md index 148f373418..7839487a15 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md @@ -16,6 +16,7 @@ * Enforce AttributeTargets on let values and functions. ([PR #16692](https://github.com/dotnet/fsharp/pull/16692)) * Enforce AttributeTargets on union case declarations. ([PR #16764](https://github.com/dotnet/fsharp/pull/16764)) * Disallow using base to invoke an abstract base method. ([Issue #13926](https://github.com/dotnet/fsharp/issues/13926), [PR #16773](https://github.com/dotnet/fsharp/pull/16773)) +* Parser: more unfinished member recovery ([PR #16835](https://github.com/dotnet/fsharp/pull/16835)) ### Added From 62ea0f9246602e6cd55ac8ef3c8d351897d7ce41 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Fri, 8 Mar 2024 10:33:31 -0400 Subject: [PATCH 3/6] Update test baselines --- .../OnTypeMembers/OnTypeMembers.fs | 1 + .../ImportDeclarations/ImportDeclarations.fs | 1 + tests/service/SyntaxTreeTests.fs | 2 +- tests/service/data/SyntaxTree/Attribute/Test.fs | 7 +++++++ 4 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 tests/service/data/SyntaxTree/Attribute/Test.fs diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/AccessibilityAnnotations/OnTypeMembers/OnTypeMembers.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/AccessibilityAnnotations/OnTypeMembers/OnTypeMembers.fs index 0fbbe44a90..49c79c2600 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/AccessibilityAnnotations/OnTypeMembers/OnTypeMembers.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/AccessibilityAnnotations/OnTypeMembers/OnTypeMembers.fs @@ -90,6 +90,7 @@ module AccessibilityAnnotations_OnTypeMembers = (Error 10, Line 20, Col 49, Line 20, Col 50, "Unexpected identifier in pattern") (Error 1244, Line 20, Col 48, Line 20, Col 57, "Attempted to parse this as an operator name, but failed") (Error 10, Line 23, Col 36, Line 23, Col 42, "Unexpected keyword 'public' in member definition") + (Error 3567, Line 23, Col 36, Line 23, Col 42, "Expecting member body") ] // SOURCE=OnProperty01.fs # OnProperty01.fs diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/ImportDeclarations/ImportDeclarations.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/ImportDeclarations/ImportDeclarations.fs index 851746df35..449fb5bd9d 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/ImportDeclarations/ImportDeclarations.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/ImportDeclarations/ImportDeclarations.fs @@ -73,6 +73,7 @@ module ImportDeclarations = (Error 10, Line 9, Col 5, Line 9, Col 9, "Unexpected keyword 'open' in binding. Expected incomplete structured construct at or before this point or other token.") (Error 10, Line 17, Col 9, Line 17, Col 13, "Unexpected keyword 'open' in binding") (Error 10, Line 23, Col 9, Line 23, Col 13, "Unexpected keyword 'open' in expression") + (Error 3567, Line 23, Col 9, Line 23, Col 13, "Expecting member body") ] // SOURCE=OpenNestedModule01.fs # OpenNestedModule01.fs diff --git a/tests/service/SyntaxTreeTests.fs b/tests/service/SyntaxTreeTests.fs index a386e25e9e..2ef5a0b1e7 100644 --- a/tests/service/SyntaxTreeTests.fs +++ b/tests/service/SyntaxTreeTests.fs @@ -190,7 +190,7 @@ let ParseFile fileName = let equals = expected = actual let testUpdateBSLEnv = System.Environment.GetEnvironmentVariable("TEST_UPDATE_BSL") - if not (isNull testUpdateBSLEnv) && testUpdateBSLEnv.Trim() = "1" && not equals then + if true then File.WriteAllText(bslPath, actual) elif not equals then File.WriteAllText(actualPath, actual) diff --git a/tests/service/data/SyntaxTree/Attribute/Test.fs b/tests/service/data/SyntaxTree/Attribute/Test.fs new file mode 100644 index 0000000000..647abdbdd8 --- /dev/null +++ b/tests/service/data/SyntaxTree/Attribute/Test.fs @@ -0,0 +1,7 @@ + +open System + +match obj() with +| :? IDisposable as + +() From e52acbf2754d930a8384d451b52db1cf2687503d Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Fri, 8 Mar 2024 11:17:29 -0400 Subject: [PATCH 4/6] Undo commit --- tests/service/data/SyntaxTree/Attribute/Test.fs | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 tests/service/data/SyntaxTree/Attribute/Test.fs diff --git a/tests/service/data/SyntaxTree/Attribute/Test.fs b/tests/service/data/SyntaxTree/Attribute/Test.fs deleted file mode 100644 index 647abdbdd8..0000000000 --- a/tests/service/data/SyntaxTree/Attribute/Test.fs +++ /dev/null @@ -1,7 +0,0 @@ - -open System - -match obj() with -| :? IDisposable as - -() From 616624d5e5ccf471aff940fc659debca09281f50 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Fri, 8 Mar 2024 14:59:37 -0400 Subject: [PATCH 5/6] Update test baselines --- .../Source/Diagnostics/General/E_IncompleteConstruct01.fs | 2 +- .../Source/Diagnostics/General/E_IncompleteConstruct01b.fs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fsharpqa/Source/Diagnostics/General/E_IncompleteConstruct01.fs b/tests/fsharpqa/Source/Diagnostics/General/E_IncompleteConstruct01.fs index e6d2ee6c08..63bbad5d81 100644 --- a/tests/fsharpqa/Source/Diagnostics/General/E_IncompleteConstruct01.fs +++ b/tests/fsharpqa/Source/Diagnostics/General/E_IncompleteConstruct01.fs @@ -1,6 +1,6 @@ // #Regression #Diagnostics // Regression test for FSHARP1.0:1181 -//Incomplete structured construct at or before this point in member definition\. Expected 'with', '=' or other token\. +//Expecting member body type INumericNorm<'T,'Measure> = interface INumeric<'T> diff --git a/tests/fsharpqa/Source/Diagnostics/General/E_IncompleteConstruct01b.fs b/tests/fsharpqa/Source/Diagnostics/General/E_IncompleteConstruct01b.fs index e3fb451018..b029157e52 100644 --- a/tests/fsharpqa/Source/Diagnostics/General/E_IncompleteConstruct01b.fs +++ b/tests/fsharpqa/Source/Diagnostics/General/E_IncompleteConstruct01b.fs @@ -1,7 +1,7 @@ // #Regression #Diagnostics // Regression test for FSHARP1.0:1181 //syntax error -// +// From bedf340253532fdc5bf722a2732ab85b341549cf Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Tue, 19 Mar 2024 16:01:15 +0100 Subject: [PATCH 6/6] Revert --- tests/service/SyntaxTreeTests.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/service/SyntaxTreeTests.fs b/tests/service/SyntaxTreeTests.fs index 2ef5a0b1e7..a386e25e9e 100644 --- a/tests/service/SyntaxTreeTests.fs +++ b/tests/service/SyntaxTreeTests.fs @@ -190,7 +190,7 @@ let ParseFile fileName = let equals = expected = actual let testUpdateBSLEnv = System.Environment.GetEnvironmentVariable("TEST_UPDATE_BSL") - if true then + if not (isNull testUpdateBSLEnv) && testUpdateBSLEnv.Trim() = "1" && not equals then File.WriteAllText(bslPath, actual) elif not equals then File.WriteAllText(actualPath, actual)