diff --git a/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs b/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs index 3154d3e1e74..e75e9a27a36 100644 --- a/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs @@ -452,6 +452,40 @@ let TcSequenceExpressionEntry (cenv: TcFileState) env (overallTy: OverallTy) tpe | _ -> () if not hasBuilder && not cenv.g.compilingFSharpCore then - error (Error(FSComp.SR.tcInvalidSequenceExpressionSyntaxForm (), m)) - - TcSequenceExpression cenv env tpenv comp overallTy m + let (|MaybeRecordField|_|) = + function + | LongOrSingleIdent(false, (SynLongIdent _ as ident), None, _) as expr1 -> + let f = + ParseHelpers.mkRecdField (SynLongIdent([ List.last ident.LongIdent ], [], [])) + + ValueSome(SynExprRecordField(f, None, Some expr1, None)) + | SynExpr.App(ExprAtomicFlag.NonAtomic, + false, + SynExpr.App(ExprAtomicFlag.NonAtomic, + true, + SynExpr.LongIdent(longDotId = SynLongIdent(id = [ ident ])), + LongOrSingleIdent(false, (SynLongIdent _ as lid), None, _), + _), + rhs, + _) when ident.idText = "op_Equality" -> + let f = ParseHelpers.mkRecdField lid + ValueSome(SynExprRecordField(f, Some ident.idRange, Some rhs, None)) + | _ -> ValueNone + + let rec sequentialToRecordExpression fields (comp: SynExpr) = + match comp with + | SynExpr.Sequential(expr1 = MaybeRecordField field; expr2 = expr2) -> sequentialToRecordExpression (field :: fields) expr2 + | MaybeRecordField field -> ValueSome(SynExpr.Record(None, None, List.rev (field :: fields), comp.Range)) + | _ -> ValueNone + + match comp with + | MaybeRecordField field -> + SynExpr.Record(None, None, [ field ], comp.Range) + |> TcExpr cenv overallTy env tpenv + | SynExpr.Sequential _ -> + match sequentialToRecordExpression [] comp with + | ValueSome expr -> TcExpr cenv overallTy env tpenv expr + | ValueNone -> error (Error(FSComp.SR.tcInvalidSequenceExpressionSyntaxForm (), m)) + | _ -> error (Error(FSComp.SR.tcInvalidSequenceExpressionSyntaxForm (), m)) + else + TcSequenceExpression cenv env tpenv comp overallTy m diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 185bd1ed842..09e311ea742 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -5562,10 +5562,22 @@ recdExprCore: None, l | _ -> raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsFieldBinding ()) } + /* handles case like { x } */ + | appExpr recdExprBindings opt_seps_recd + { match $1 with + | LongOrSingleIdent(false, (SynLongIdent _ as ident), None, m) -> + let f = mkRecdField (SynLongIdent([List.last ident.LongIdent], [], [])) + let l = List.rev $2 + let l = rebindRanges (f, None, Some $1) l $3 + (None, l) + | _ -> raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsFieldBinding()) } + | appExpr - { let mExpr = rhs parseState 1 - reportParseErrorAt mExpr (FSComp.SR.parsFieldBinding ()) - Some($1, (mExpr.EndRange, None)), [] } + { match $1 with + | LongOrSingleIdent(false, (SynLongIdent _ as ident), None, m) -> + let f = mkRecdField (SynLongIdent([List.last ident.LongIdent], [], [])) + (None, [ SynExprRecordField(f, None, Some $1, None) ]) + | _ -> raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsFieldBinding()) } /* handles cases when identifier can start from the underscore @@ -5632,7 +5644,7 @@ seps_recd: /* identifier can start from the underscore */ -pathOrUnderscore : +pathOrUnderscore: | path { mkRecdField $1 } @@ -5664,12 +5676,10 @@ recdBinding: ($1, Some mEquals, None) } | pathOrUnderscore - { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsFieldBinding()) - ($1, None, None) } - - | pathOrUnderscore ends_coming_soon_or_recover - { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsFieldBinding()) - ($1, None, None) } + { let ident, b = $1 + let f = SynLongIdent([List.last ident.LongIdent], [], []), b + let expr = SynExpr.LongIdent(false, ident, None, rhs parseState 1) + (f, None, Some expr) } /* There is a minor conflict between seq { new ty() } // sequence expression with one very odd 'action' expression diff --git a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-01.fs.bsl b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-01.fs.bsl index f931eda4280..7714cb2a66e 100644 --- a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-01.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-01.fs.bsl @@ -24,14 +24,8 @@ ImplFile (AnonRecd (true, None, [], (4,0--4,12), { OpeningBraceRange = (4,7--4,9) }), (4,0--4,12)); - Expr - (AnonRecd - (false, Some (Null (5,3--5,7), ((5,7--5,7), None)), [], - (5,0--5,10), { OpeningBraceRange = (5,0--5,2) }), (5,0--5,10)); - Expr - (AnonRecd - (true, Some (Null (6,10--6,14), ((6,14--6,14), None)), [], - (6,0--6,17), { OpeningBraceRange = (6,7--6,9) }), (6,0--6,17))], + Expr (ArbitraryAfterError ("braceBarExpr", (5,0--5,10)), (5,0--5,10)); + Expr (ArbitraryAfterError ("braceBarExpr", (6,0--6,17)), (6,0--6,17))], PreXmlDocEmpty, [], None, (1,0--6,17), { LeadingKeyword = None })], (true, true), { ConditionalDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Record - Anon 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Anon 03.fs.bsl index dbb9b6e063f..9c44a2d8ae9 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Anon 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Anon 03.fs.bsl @@ -6,11 +6,9 @@ ImplFile ([Module], false, NamedModule, [Expr (AnonRecd - (false, Some (Ident F, ((3,4--3,4), None)), [], (3,0--3,7), - { OpeningBraceRange = (3,0--3,2) }), (3,0--3,7))], + (false, None, [(SynLongIdent ([F], [], []), None, Ident F)], + (3,0--3,7), { OpeningBraceRange = (3,0--3,2) }), (3,0--3,7))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,7), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] CodeComments = [] }, set [])) - -(3,3)-(3,4) parse error Field bindings must have the form 'id = expr;' diff --git a/tests/service/data/SyntaxTree/Expression/Record - Anon 04.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Anon 04.fs.bsl index 07303e1a146..e562c3452b8 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Anon 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Anon 04.fs.bsl @@ -4,14 +4,7 @@ ImplFile [], [], [SynModuleOrNamespace ([Module], false, NamedModule, - [Expr - (AnonRecd - (false, - Some - (App - (Atomic, false, Ident f, Const (Unit, (3,4--3,6)), - (3,3--3,6)), ((3,6--3,6), None)), [], (3,0--3,9), - { OpeningBraceRange = (3,0--3,2) }), (3,0--3,9))], + [Expr (ArbitraryAfterError ("braceBarExpr", (3,0--3,9)), (3,0--3,9))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,9), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Record - Anon 05.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Anon 05.fs.bsl index 6c2cefee45d..a3df207d6d7 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Anon 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Anon 05.fs.bsl @@ -4,16 +4,7 @@ ImplFile [], [], [SynModuleOrNamespace ([Module], false, NamedModule, - [Expr - (AnonRecd - (false, - Some - (DiscardAfterMissingQualificationAfterDot - (App - (Atomic, false, Ident f, Const (Unit, (3,4--3,6)), - (3,3--3,6)), (3,6--3,7), (3,3--3,7)), - ((3,10--3,10), None)), [], (3,0--3,10), - { OpeningBraceRange = (3,0--3,2) }), (3,0--3,10))], + [Expr (ArbitraryAfterError ("braceBarExpr", (3,0--3,10)), (3,0--3,10))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,10), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Record - Anon 06.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Anon 06.fs.bsl index edbeaa194e6..8ed8de16525 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Anon 06.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Anon 06.fs.bsl @@ -4,17 +4,7 @@ ImplFile [], [], [SynModuleOrNamespace ([Module], false, NamedModule, - [Expr - (AnonRecd - (false, - Some - (DotGet - (App - (Atomic, false, Ident f, Const (Unit, (3,4--3,6)), - (3,3--3,6)), (3,6--3,7), - SynLongIdent ([F], [], [None]), (3,3--3,8)), - ((3,8--3,8), None)), [], (3,0--3,11), - { OpeningBraceRange = (3,0--3,2) }), (3,0--3,11))], + [Expr (ArbitraryAfterError ("braceBarExpr", (3,0--3,11)), (3,0--3,11))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,11), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Record - Anon 08.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Anon 08.fs.bsl index 0cd4a997180..d8b95222172 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Anon 08.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Anon 08.fs.bsl @@ -9,12 +9,11 @@ ImplFile (false, None, [(SynLongIdent ([F1], [], [None]), Some (3,6--3,7), Const (Int32 1, (3,8--3,9))); - (SynLongIdent ([F2], [], [None]), None, - ArbitraryAfterError ("anonField", (4,3--4,5)))], (3,0--4,8), - { OpeningBraceRange = (3,0--3,2) }), (3,0--4,8))], + (SynLongIdent ([F2], [], []), None, + LongIdent + (false, SynLongIdent ([F2], [], [None]), None, (4,3--4,5)))], + (3,0--4,8), { OpeningBraceRange = (3,0--3,2) }), (3,0--4,8))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--4,8), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] CodeComments = [] }, set [])) - -(4,3)-(4,5) parse error Field bindings must have the form 'id = expr;' diff --git a/tests/service/data/SyntaxTree/Expression/Record - Anon 10.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Anon 10.fs.bsl index 2e01c7ef8c7..48a4a2bb91c 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Anon 10.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Anon 10.fs.bsl @@ -9,8 +9,9 @@ ImplFile (false, None, [(SynLongIdent ([F1], [], [None]), Some (3,6--3,7), Const (Int32 1, (3,8--3,9))); - (SynLongIdent ([F2], [], [None]), None, - ArbitraryAfterError ("anonField", (4,3--4,5))); + (SynLongIdent ([F2], [], []), None, + LongIdent + (false, SynLongIdent ([F2], [], [None]), None, (4,3--4,5))); (SynLongIdent ([F3], [], [None]), Some (5,6--5,7), Const (Int32 3, (5,8--5,9)))], (3,0--5,12), { OpeningBraceRange = (3,0--3,2) }), (3,0--5,12))], @@ -18,5 +19,3 @@ ImplFile (1,0--5,12), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] CodeComments = [] }, set [])) - -(4,3)-(4,5) parse error Field bindings must have the form 'id = expr;' diff --git a/tests/service/data/SyntaxTree/Expression/Record - Anon 12.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Anon 12.fs.bsl index 3371e7a75e6..456fd79fd07 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Anon 12.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Anon 12.fs.bsl @@ -6,25 +6,12 @@ ImplFile ([Module], false, NamedModule, [Expr (AnonRecd - (false, Some (Ident F1, ((3,5--3,5), None)), [], (3,0--3,5), - { OpeningBraceRange = (3,0--3,2) }), (3,0--3,5)); - Expr - (App - (NonAtomic, false, - App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Equality], [], [Some (OriginalNotation "=")]), - None, (4,6--4,7)), Ident F2, (4,3--4,7)), - Const (Int32 2, (4,8--4,9)), (4,3--4,9)), (4,3--4,9))], + (false, None, + [(SynLongIdent ([F1], [], []), None, Ident F1); + (SynLongIdent ([F2], [], [None]), Some (4,6--4,7), + Const (Int32 2, (4,8--4,9)))], (3,0--4,12), + { OpeningBraceRange = (3,0--3,2) }), (3,0--4,12))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, - (1,0--4,9), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + (1,0--4,12), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] CodeComments = [] }, set [])) - -(3,3)-(3,5) parse error Field bindings must have the form 'id = expr;' -(3,6)-(4,3) parse error Incomplete structured construct at or before this point in definition. Expected '|}' or other token. -(3,0)-(3,2) parse error Unmatched '{|' -(4,10)-(4,12) parse error Unexpected symbol '|}' in definition. Expected incomplete structured construct at or before this point or other token. diff --git a/tests/service/data/SyntaxTree/Expression/Record - Field 08.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Field 08.fs.bsl index a9a2cbc8047..10b2ab19744 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Field 08.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Field 08.fs.bsl @@ -11,12 +11,14 @@ ImplFile ((SynLongIdent ([A], [], [None]), true), Some (3,4--3,5), Some (Const (Int32 1, (3,6--3,7))), Some ((3,8--4,2), None)); SynExprRecordField - ((SynLongIdent ([B], [(4,3--4,4)], [None]), true), None, - None, None)], (3,0--4,6)), (3,0--4,6))], + ((SynLongIdent ([B], [], []), true), None, + Some + (LongIdent + (false, SynLongIdent ([B], [(4,3--4,4)], [None]), None, + (4,2--4,6))), None)], (3,0--4,6)), (3,0--4,6))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--4,6), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] CodeComments = [] }, set [])) (4,3)-(4,4) parse error Unexpected end of type. Expected a name after this point. -(4,2)-(4,6) parse error Field bindings must have the form 'id = expr;' diff --git a/tests/service/data/SyntaxTree/Expression/Record - Field 09.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Field 09.fs.bsl index 6132a89bd66..17c982cb27d 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Field 09.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Field 09.fs.bsl @@ -11,11 +11,12 @@ ImplFile ((SynLongIdent ([A], [], [None]), true), Some (3,4--3,5), Some (Const (Int32 1, (3,6--3,7))), Some ((3,8--4,2), None)); SynExprRecordField - ((SynLongIdent ([B], [], [None]), true), None, None, None)], - (3,0--4,5)), (3,0--4,5))], + ((SynLongIdent ([B], [], []), true), None, + Some + (LongIdent + (false, SynLongIdent ([B], [], [None]), None, + (4,2--4,3))), None)], (3,0--4,5)), (3,0--4,5))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--4,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] CodeComments = [] }, set [])) - -(4,2)-(4,3) parse error Field bindings must have the form 'id = expr;' diff --git a/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs b/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs index d8e92581f10..564c3792e33 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs @@ -94,7 +94,8 @@ module CompletionProviderTests = if actualNames <> expected then failwithf - "Expected:\n%s,\nbut was:\n%s\nactual with sort text:\n%s" + "After marker \"%s\" expected:\n%s,\nbut was:\n%s\nactual with sort text:\n%s" + marker (String.Join("; ", expected |> List.map (sprintf "\"%s\""))) (String.Join("; ", actualNames |> List.map (sprintf "\"%s\""))) (String.Join("\n", actual |> List.map (fun x -> sprintf "%s => %s" x.DisplayText x.SortText)))