diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md index e58c882938b..28f20ca2be2 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md +++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md @@ -16,6 +16,7 @@ * Remove non-functional useSyntaxTreeCache option. ([PR #17768](https://github.com/dotnet/fsharp/pull/17768)) * Better ranges for CE `let!` and `use!` error reporting. ([PR #17712](https://github.com/dotnet/fsharp/pull/17712)) * Better ranges for CE `do!` error reporting. ([PR #17779](https://github.com/dotnet/fsharp/pull/17779)) +* Better ranges for CE `return, yield, return! and yield!` error reporting. ([PR #17792](https://github.com/dotnet/fsharp/pull/17792)) * Better ranges for CE `match!`. ([PR #17789](https://github.com/dotnet/fsharp/pull/17789)) ### Breaking Changes diff --git a/docs/release-notes/.VisualStudio/17.12.md b/docs/release-notes/.VisualStudio/17.12.md index 83df7173b2e..690ec481a20 100644 --- a/docs/release-notes/.VisualStudio/17.12.md +++ b/docs/release-notes/.VisualStudio/17.12.md @@ -5,9 +5,10 @@ ### Added ### Changed +* Fix unwanted navigation on hover [PR #17592](https://github.com/dotnet/fsharp/pull/17592) +* Update `RemoveReturnOrYield` code fix range calculation [PR #17792](https://github.com/dotnet/fsharp/pull/17792) * Fix unwanted navigation on hover [PR #17592](https://github.com/dotnet/fsharp/pull/17592)) * Remove non-functional useSyntaxTreeCache option. ([PR #17768](https://github.com/dotnet/fsharp/pull/17768)) - ### Breaking Changes * Enable FSharp 9.0 Language Version ([Issue #17497](https://github.com/dotnet/fsharp/issues/17438)), [PR](https://github.com/dotnet/fsharp/pull/17500))) diff --git a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs index d328f6a310a..c1aa4dafc5d 100644 --- a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs @@ -1545,7 +1545,9 @@ let rec TryTranslateComputationExpression let dataCompPrior = translatedCtxt ( - TranslateComputationExpressionNoQueryOps ceenv (SynExpr.YieldOrReturn((true, false), varSpaceExpr, mClause)) + TranslateComputationExpressionNoQueryOps + ceenv + (SynExpr.YieldOrReturn((true, false), varSpaceExpr, mClause, SynExprYieldOrReturnTrivia.Zero)) ) // Rebind using for ... @@ -1576,7 +1578,9 @@ let rec TryTranslateComputationExpression let isYield = not (customOperationMaintainsVarSpaceUsingBind ceenv nm) translatedCtxt ( - TranslateComputationExpressionNoQueryOps ceenv (SynExpr.YieldOrReturn((isYield, false), varSpaceExpr, mClause)) + TranslateComputationExpressionNoQueryOps + ceenv + (SynExpr.YieldOrReturn((isYield, false), varSpaceExpr, mClause, SynExprYieldOrReturnTrivia.Zero)) ) // Now run the consumeCustomOpClauses @@ -2374,7 +2378,7 @@ let rec TryTranslateComputationExpression Some(translatedCtxt callExpr) - | SynExpr.YieldOrReturnFrom((true, _), synYieldExpr, m) -> + | SynExpr.YieldOrReturnFrom((true, _), synYieldExpr, _, { YieldOrReturnFromKeyword = m }) -> let yieldFromExpr = mkSourceExpr synYieldExpr ceenv.sourceMethInfo ceenv.builderValName @@ -2392,7 +2396,8 @@ let rec TryTranslateComputationExpression then error (Error(FSComp.SR.tcRequireBuilderMethod ("YieldFrom"), m)) - let yieldFromCall = mkSynCall "YieldFrom" m [ yieldFromExpr ] ceenv.builderValName + let yieldFromCall = + mkSynCall "YieldFrom" synYieldExpr.Range [ yieldFromExpr ] ceenv.builderValName let yieldFromCall = if IsControlFlowExpression synYieldExpr then @@ -2402,7 +2407,7 @@ let rec TryTranslateComputationExpression Some(translatedCtxt yieldFromCall) - | SynExpr.YieldOrReturnFrom((false, _), synReturnExpr, m) -> + | SynExpr.YieldOrReturnFrom((false, _), synReturnExpr, _, { YieldOrReturnFromKeyword = m }) -> let returnFromExpr = mkSourceExpr synReturnExpr ceenv.sourceMethInfo ceenv.builderValName @@ -2424,7 +2429,7 @@ let rec TryTranslateComputationExpression error (Error(FSComp.SR.tcRequireBuilderMethod ("ReturnFrom"), m)) let returnFromCall = - mkSynCall "ReturnFrom" m [ returnFromExpr ] ceenv.builderValName + mkSynCall "ReturnFrom" synReturnExpr.Range [ returnFromExpr ] ceenv.builderValName let returnFromCall = if IsControlFlowExpression synReturnExpr then @@ -2434,7 +2439,7 @@ let rec TryTranslateComputationExpression Some(translatedCtxt returnFromCall) - | SynExpr.YieldOrReturn((isYield, _), synYieldOrReturnExpr, m) -> + | SynExpr.YieldOrReturn((isYield, _), synYieldOrReturnExpr, _, { YieldOrReturnKeyword = m }) -> let methName = (if isYield then "Yield" else "Return") if ceenv.isQuery && not isYield then @@ -2452,10 +2457,10 @@ let rec TryTranslateComputationExpression ceenv.builderTy ) then - error (Error(FSComp.SR.tcRequireBuilderMethod (methName), m)) + error (Error(FSComp.SR.tcRequireBuilderMethod methName, m)) let yieldOrReturnCall = - mkSynCall methName m [ synYieldOrReturnExpr ] ceenv.builderValName + mkSynCall methName synYieldOrReturnExpr.Range [ synYieldOrReturnExpr ] ceenv.builderValName let yieldOrReturnCall = if IsControlFlowExpression synYieldOrReturnExpr then @@ -2759,7 +2764,7 @@ and TranslateComputationExpressionBind /// The inner option indicates if a custom operation is involved inside and convertSimpleReturnToExpr (ceenv: ComputationExpressionContext<'a>) comp varSpace innerComp = match innerComp with - | SynExpr.YieldOrReturn((false, _), returnExpr, m) -> + | SynExpr.YieldOrReturn((false, _), returnExpr, m, _) -> let returnExpr = SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes m, false, returnExpr) Some(returnExpr, None) @@ -2901,7 +2906,7 @@ and TranslateComputationExpression (ceenv: ComputationExpressionContext<'a>) fir with | minfo :: _ when MethInfoHasAttribute ceenv.cenv.g m ceenv.cenv.g.attrib_DefaultValueAttribute minfo -> SynExpr.ImplicitZero m - | _ -> SynExpr.YieldOrReturn((false, true), SynExpr.Const(SynConst.Unit, m), m) + | _ -> SynExpr.YieldOrReturn((false, true), SynExpr.Const(SynConst.Unit, m), m, SynExprYieldOrReturnTrivia.Zero) let letBangBind = SynExpr.LetOrUseBang( diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index 3a01eaa2efe..4325d503206 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -5991,16 +5991,16 @@ and TcExprUndelayed (cenv: cenv) (overallTy: OverallTy) env tpenv (synExpr: SynE CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy.Commit, env.AccessRights) TcQuotationExpr cenv overallTy env tpenv (oper, raw, ast, isFromQueryExpression, m) - | SynExpr.YieldOrReturn ((isTrueYield, _), _, m) - | SynExpr.YieldOrReturnFrom ((isTrueYield, _), _, m) when isTrueYield -> + | SynExpr.YieldOrReturn ((isTrueYield, _), _, _m, { YieldOrReturnKeyword = m }) + | SynExpr.YieldOrReturnFrom ((isTrueYield, _), _, _m, { YieldOrReturnFromKeyword = m }) when isTrueYield -> error(Error(FSComp.SR.tcConstructRequiresListArrayOrSequence(), m)) - | SynExpr.YieldOrReturn ((_, isTrueReturn), _, m) - | SynExpr.YieldOrReturnFrom ((_, isTrueReturn), _, m) when isTrueReturn -> + | SynExpr.YieldOrReturn ((_, isTrueReturn), _, _m, { YieldOrReturnKeyword = m }) + | SynExpr.YieldOrReturnFrom ((_, isTrueReturn), _, _m, { YieldOrReturnFromKeyword = m }) when isTrueReturn -> error(Error(FSComp.SR.tcConstructRequiresComputationExpressions(), m)) - | SynExpr.YieldOrReturn (_, _, m) - | SynExpr.YieldOrReturnFrom (_, _, m) + | SynExpr.YieldOrReturn (trivia = { YieldOrReturnKeyword = m }) + | SynExpr.YieldOrReturnFrom (trivia = { YieldOrReturnFromKeyword = m }) | SynExpr.ImplicitZero m -> error(Error(FSComp.SR.tcConstructRequiresSequenceOrComputations(), m)) diff --git a/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs b/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs index b627eef2922..781060c8af4 100644 --- a/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs @@ -353,43 +353,44 @@ let TcSequenceExpression (cenv: TcFileState) env tpenv comp (overallTy: OverallT Some(combinatorExpr, tpenv) - | SynExpr.YieldOrReturnFrom((isYield, _), synYieldExpr, m) -> + | SynExpr.YieldOrReturnFrom(flags = (isYield, _); expr = synYieldExpr; trivia = { YieldOrReturnFromKeyword = m }) -> let env = { env with eIsControlFlow = false } let resultExpr, genExprTy, tpenv = TcExprOfUnknownType cenv env tpenv synYieldExpr if not isYield then errorR (Error(FSComp.SR.tcUseYieldBangForMultipleResults (), m)) - AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css m NoTrace genOuterTy genExprTy + AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css synYieldExpr.Range NoTrace genOuterTy genExprTy - let resultExpr = mkCoerceExpr (resultExpr, genOuterTy, m, genExprTy) + let resultExpr = + mkCoerceExpr (resultExpr, genOuterTy, synYieldExpr.Range, genExprTy) let resultExpr = if IsControlFlowExpression synYieldExpr then resultExpr else - mkDebugPoint m resultExpr + mkDebugPoint resultExpr.Range resultExpr Some(resultExpr, tpenv) - | SynExpr.YieldOrReturn((isYield, _), synYieldExpr, m) -> + | SynExpr.YieldOrReturn(flags = (isYield, _); expr = synYieldExpr; trivia = { YieldOrReturnKeyword = m }) -> let env = { env with eIsControlFlow = false } let genResultTy = NewInferenceType g if not isYield then errorR (Error(FSComp.SR.tcSeqResultsUseYield (), m)) - UnifyTypes cenv env m genOuterTy (mkSeqTy cenv.g genResultTy) + UnifyTypes cenv env synYieldExpr.Range genOuterTy (mkSeqTy cenv.g genResultTy) let resultExpr, tpenv = TcExprFlex cenv flex true genResultTy env tpenv synYieldExpr - let resultExpr = mkCallSeqSingleton cenv.g m genResultTy resultExpr + let resultExpr = mkCallSeqSingleton cenv.g synYieldExpr.Range genResultTy resultExpr let resultExpr = if IsControlFlowExpression synYieldExpr then resultExpr else - mkDebugPoint m resultExpr + mkDebugPoint synYieldExpr.Range resultExpr Some(resultExpr, tpenv) diff --git a/src/Compiler/Service/FSharpParseFileResults.fs b/src/Compiler/Service/FSharpParseFileResults.fs index d00b5fe7934..2623cbde347 100644 --- a/src/Compiler/Service/FSharpParseFileResults.fs +++ b/src/Compiler/Service/FSharpParseFileResults.fs @@ -573,11 +573,11 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, yield! checkRange m yield! walkExpr isControlFlow innerExpr - | SynExpr.YieldOrReturn(_, e, m) -> + | SynExpr.YieldOrReturn(_, e, m, _) -> yield! checkRange m yield! walkExpr false e - | SynExpr.YieldOrReturnFrom(_, e, _) + | SynExpr.YieldOrReturnFrom(_, e, _, _) | SynExpr.DoBang(expr = e) -> yield! checkRange e.Range yield! walkExpr false e diff --git a/src/Compiler/Service/ServiceStructure.fs b/src/Compiler/Service/ServiceStructure.fs index 6ca45aa6961..5fab5ef9eb5 100644 --- a/src/Compiler/Service/ServiceStructure.fs +++ b/src/Compiler/Service/ServiceStructure.fs @@ -246,11 +246,11 @@ module Structure = rcheck Scope.New Collapse.Below r e.Range parseExpr e - | SynExpr.YieldOrReturn(_, e, r) -> + | SynExpr.YieldOrReturn(_, e, r, _) -> rcheck Scope.YieldOrReturn Collapse.Below r r parseExpr e - | SynExpr.YieldOrReturnFrom(_, e, r) -> + | SynExpr.YieldOrReturnFrom(_, e, r, _) -> rcheck Scope.YieldOrReturnBang Collapse.Below r r parseExpr e diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs index f97fe05234d..fc0c811e55d 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fs +++ b/src/Compiler/SyntaxTree/SyntaxTree.fs @@ -704,9 +704,9 @@ type SynExpr = | SequentialOrImplicitYield of debugPoint: DebugPointAtSequential * expr1: SynExpr * expr2: SynExpr * ifNotStmt: SynExpr * range: range - | YieldOrReturn of flags: (bool * bool) * expr: SynExpr * range: range + | YieldOrReturn of flags: (bool * bool) * expr: SynExpr * range: range * trivia: SynExprYieldOrReturnTrivia - | YieldOrReturnFrom of flags: (bool * bool) * expr: SynExpr * range: range + | YieldOrReturnFrom of flags: (bool * bool) * expr: SynExpr * range: range * trivia: SynExprYieldOrReturnFromTrivia | LetOrUseBang of bindDebugPoint: DebugPointAtBinding * diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi index 99138631957..45b03ad3b75 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi @@ -877,12 +877,12 @@ type SynExpr = /// F# syntax: yield expr /// F# syntax: return expr /// Computation expressions only - | YieldOrReturn of flags: (bool * bool) * expr: SynExpr * range: range + | YieldOrReturn of flags: (bool * bool) * expr: SynExpr * range: range * trivia: SynExprYieldOrReturnTrivia /// F# syntax: yield! expr /// F# syntax: return! expr /// Computation expressions only - | YieldOrReturnFrom of flags: (bool * bool) * expr: SynExpr * range: range + | YieldOrReturnFrom of flags: (bool * bool) * expr: SynExpr * range: range * trivia: SynExprYieldOrReturnFromTrivia /// F# syntax: let! pat = expr in expr /// F# syntax: use! pat = expr in expr diff --git a/src/Compiler/SyntaxTree/SyntaxTreeOps.fs b/src/Compiler/SyntaxTree/SyntaxTreeOps.fs index 680986ea503..8dc46313341 100644 --- a/src/Compiler/SyntaxTree/SyntaxTreeOps.fs +++ b/src/Compiler/SyntaxTree/SyntaxTreeOps.fs @@ -883,8 +883,8 @@ let rec synExprContainsError inpExpr = | SynExpr.InferredDowncast(e, _) | SynExpr.Lazy(e, _) | SynExpr.TraitCall(_, _, e, _) - | SynExpr.YieldOrReturn(_, e, _) - | SynExpr.YieldOrReturnFrom(_, e, _) + | SynExpr.YieldOrReturn(_, e, _, _) + | SynExpr.YieldOrReturnFrom(_, e, _, _) | SynExpr.DoBang(e, _, _) | SynExpr.Fixed(e, _) | SynExpr.DebugPoint(_, _, e) diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fs b/src/Compiler/SyntaxTree/SyntaxTrivia.fs index 7e03572719e..10aee262292 100644 --- a/src/Compiler/SyntaxTree/SyntaxTrivia.fs +++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fs @@ -117,6 +117,25 @@ type SynExprMatchBangTrivia = WithKeyword: range } +[] +type SynExprYieldOrReturnTrivia = + { + YieldOrReturnKeyword: range + } + + static member Zero: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = Range.Zero } + +[] +type SynExprYieldOrReturnFromTrivia = + { + YieldOrReturnFromKeyword: range + } + + static member Zero: SynExprYieldOrReturnFromTrivia = + { + YieldOrReturnFromKeyword = Range.Zero + } + [] type SynExprDoBangTrivia = { DoBangKeyword: range } diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi index 3c678a72679..fff834beb41 100644 --- a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi @@ -177,6 +177,24 @@ type SynExprDoBangTrivia = DoBangKeyword: range } +/// Represents additional information for SynExpr.YieldOrReturn +[] +type SynExprYieldOrReturnTrivia = + { + /// The syntax range of the `yield` or `return` keyword. + YieldOrReturnKeyword: range + } + + static member Zero: SynExprYieldOrReturnTrivia + +/// Represents additional information for SynExpr.YieldOrReturnFrom +[] +type SynExprYieldOrReturnFromTrivia = + { + /// The syntax range of the `yield!` or `return!` keyword. + YieldOrReturnFromKeyword: range + } + /// Represents additional information for SynExpr.AnonRecd [] type SynExprAnonRecdTrivia = diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 656b75c39ff..185bd1ed842 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -4402,18 +4402,22 @@ declExpr: exprFromParseError (SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, $2, arbExpr ("forLoopCollection", mFor), arbExpr ("forLoopBody3", mForLoopBodyArb), mForLoopAll)) } | YIELD declExpr - { SynExpr.YieldOrReturn(($1, not $1), $2, unionRanges (rhs parseState 1) $2.Range) } + { let trivia: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = rhs parseState 1 } + SynExpr.YieldOrReturn(($1, not $1), $2, (unionRanges (rhs parseState 1) $2.Range), trivia) } | YIELD_BANG declExpr - { SynExpr.YieldOrReturnFrom(($1, not $1), $2, unionRanges (rhs parseState 1) $2.Range) } + { let trivia: SynExprYieldOrReturnFromTrivia = { YieldOrReturnFromKeyword = rhs parseState 1 } + SynExpr.YieldOrReturnFrom(($1, not $1), $2, (unionRanges (rhs parseState 1) $2.Range), trivia) } | YIELD recover { let mYieldAll = rhs parseState 1 - SynExpr.YieldOrReturn(($1, not $1), arbExpr ("yield", mYieldAll), mYieldAll) } + let trivia: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = rhs parseState 1 } + SynExpr.YieldOrReturn(($1, not $1), arbExpr ("yield", mYieldAll), mYieldAll, trivia) } | YIELD_BANG recover { let mYieldAll = rhs parseState 1 - SynExpr.YieldOrReturnFrom(($1, not $1), arbExpr ("yield!", mYieldAll), mYieldAll) } + let trivia: SynExprYieldOrReturnFromTrivia = { YieldOrReturnFromKeyword = rhs parseState 1 } + SynExpr.YieldOrReturnFrom(($1, not $1), arbExpr ("yield!", mYieldAll), mYieldAll, trivia) } | BINDER headBindingPattern EQUALS typedSequentialExprBlock IN opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let { let spBind = DebugPointAtBinding.Yes(rhs2 parseState 1 5) @@ -4458,7 +4462,8 @@ declExpr: { errorR(Error(FSComp.SR.parsArrowUseIsLimited(), lhs parseState)) let mArrow = rhs parseState 1 let expr = $2 mArrow - SynExpr.YieldOrReturn((true, true), expr, (unionRanges mArrow expr.Range)) } + let trivia: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = rhs parseState 1 } + SynExpr.YieldOrReturn((true, true), expr, (unionRanges mArrow expr.Range), trivia) } | declExpr COLON_QMARK typ { SynExpr.TypeTest($1, $3, unionRanges $1.Range $3.Range) } @@ -5456,7 +5461,8 @@ arrowThenExprR: | RARROW typedSequentialExprBlockR { let mArrow = rhs parseState 1 let expr = $2 mArrow - SynExpr.YieldOrReturn((true, false), expr, unionRanges mArrow expr.Range) } + let trivia: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = mArrow } + SynExpr.YieldOrReturn((true, false), expr, (unionRanges mArrow expr.Range), trivia) } forLoopBinder: | parenPattern IN declExpr diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs index 34263b3f7bc..53cb33b5b78 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs @@ -347,7 +347,7 @@ let f4 = |> withDiagnostics [ (Error 1, Line 6, Col 9, Line 6, Col 16, "This expression was expected to have type\n 'int' \nbut here has type\n 'string' ") (Error 1, Line 12, Col 13, Line 12, Col 16, "This expression was expected to have type\n 'int' \nbut here has type\n 'string' ") - (Error 193, Line 21, Col 9, Line 21, Col 24, "Type constraint mismatch. The type \n 'int list' \nis not compatible with type\n 'string seq' \n") + (Error 193, Line 21, Col 16, Line 21, Col 24, "Type constraint mismatch. The type \n 'int list' \nis not compatible with type\n 'string seq' \n") (Error 1, Line 28, Col 9, Line 28, Col 12, "This expression was expected to have type\n 'int64' \nbut here has type\n 'float' ") ] diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs index 319d79aa8ea..9d276c13629 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs @@ -493,4 +493,155 @@ let run r2 r3 = |> shouldFail |> withDiagnostics [ (Error 750, Line 3, Col 5, Line 3, Col 11, "This construct may only be used within computation expressions") + ] + + [] + let ``This control construct may only be used if the computation expression builder defines a 'Yield' method`` () = + Fsx """ +let f3 = + async { + if true then + yield "a" + else + yield "b" + } + """ + |> ignoreWarnings + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 708, Line 5, Col 13, Line 5, Col 18, "This control construct may only be used if the computation expression builder defines a 'Yield' method") + ] + + [] + let ``This control construct may only be used if the computation expression builder defines a 'YieldFrom' method`` () = + Fsx """ +let f3 = + async { + if true then + yield! "a" + else + yield "b" + } + """ + |> ignoreWarnings + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 708, Line 5, Col 13, Line 5, Col 19, "This control construct may only be used if the computation expression builder defines a 'YieldFrom' method") + ] + + + [] + let ``This control construct may only be used if the computation expression builder defines a 'Return' method`` () = + Fsx """ +module Result = + let zip x1 x2 = + match x1,x2 with + | Ok x1res, Ok x2res -> Ok (x1res, x2res) + | Error e, _ -> Error e + | _, Error e -> Error e + +type ResultBuilder() = + member _.MergeSources(t1: Result<'T,'U>, t2: Result<'T1,'U>) = Result.zip t1 t2 + member _.BindReturn(x: Result<'T,'U>, f) = Result.map f x + member _.Delay(f) = f() + + member _.TryWith(r: Result<'T,'U>, f) = + match r with + | Ok x -> Ok x + | Error e -> f e + +let result = ResultBuilder() + +let run r2 r3 = + result { + match r2 with + | Ok x -> return x + | Error e -> return e + } + """ + |> ignoreWarnings + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 708, Line 24, Col 19, Line 24, Col 25, "This control construct may only be used if the computation expression builder defines a 'Return' method") + ] + + + [] + let ``This control construct may only be used if the computation expression builder defines a 'ReturnFrom' method`` () = + Fsx """ +module Result = + let zip x1 x2 = + match x1,x2 with + | Ok x1res, Ok x2res -> Ok (x1res, x2res) + | Error e, _ -> Error e + | _, Error e -> Error e + +type ResultBuilder() = + member _.MergeSources(t1: Result<'T,'U>, t2: Result<'T1,'U>) = Result.zip t1 t2 + member _.BindReturn(x: Result<'T,'U>, f) = Result.map f x + member _.Delay(f) = f() + + member _.TryWith(r: Result<'T,'U>, f) = + match r with + | Ok x -> Ok x + | Error e -> f e + +let result = ResultBuilder() + +let run r2 r3 = + result { + match r2 with + | Ok x -> return! x + | Error e -> return e + } + """ + |> ignoreWarnings + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 708, Line 24, Col 19, Line 24, Col 26, "This control construct may only be used if the computation expression builder defines a 'ReturnFrom' method") + ] + + [] + let ``Type constraint mismatch when using return!`` () = + Fsx """ +open System.Threading.Tasks + +let maybeTask = task { return false } + +let indexHandler (): Task = + task { + return! maybeTask + } + """ + |> ignoreWarnings + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 193, Line 8, Col 17, Line 8, Col 26, "Type constraint mismatch. The type \n 'TaskCode' \nis not compatible with type\n 'TaskCode' \n") + ] + + [] + let ``Type constraint mismatch when using return`` () = + Fsx """ +open System.Threading.Tasks + +let maybeTask = task { return false } + +let indexHandler (): Task = + task { + return maybeTask + } + """ + |> ignoreWarnings + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 8, Col 16, Line 8, Col 25, "This expression was expected to have type + 'string' +but here has type + 'Task' ") ] \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressionTests.fs index 982ae0c820b..8247eaf60e3 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressionTests.fs @@ -442,4 +442,29 @@ let typedSeq = |> withErrorCode 30 |> withDiagnosticMessageMatches "Value restriction: The value 'typedSeq' has an inferred generic type" |> withDiagnosticMessageMatches "val typedSeq: '_a seq" - \ No newline at end of file + +[] +let ``yield may only be used within list, array, and sequence expressions``() = + Fsx """ +let f1 = yield [ 3; 4 ] +let f2 = yield! [ 3; 4 ] + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 747, Line 2, Col 10, Line 2, Col 15, "This construct may only be used within list, array and sequence expressions, e.g. expressions of the form 'seq { ... }', '[ ... ]' or '[| ... |]'. These use the syntax 'for ... in ... do ... yield...' to generate elements"); + (Error 747, Line 3, Col 10, Line 3, Col 16, "This construct may only be used within list, array and sequence expressions, e.g. expressions of the form 'seq { ... }', '[ ... ]' or '[| ... |]'. These use the syntax 'for ... in ... do ... yield...' to generate elements") + ] + +[] +let ``return may only be used within list, array, and sequence expressions``() = + Fsx """ +let f1 = return [ 3; 4 ] +let f2 = return! [ 3; 4 ] + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 748, Line 2, Col 10, Line 2, Col 16, "This construct may only be used within computation expressions. To return a value from an ordinary function simply write the expression without 'return'."); + (Error 748, Line 3, Col 10, Line 3, Col 17, "This construct may only be used within computation expressions. To return a value from an ordinary function simply write the expression without 'return'.") + ] \ No newline at end of file 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 da62302304a..42ec38ee366 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 @@ -7668,8 +7668,22 @@ FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewTyped(FSharp.C FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewUpcast(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewWhile(FSharp.Compiler.Syntax.DebugPointAtWhile, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewWhileBang(FSharp.Compiler.Syntax.DebugPointAtWhile, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range) -FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewYieldOrReturn(System.Tuple`2[System.Boolean,System.Boolean], FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range) -FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewYieldOrReturnFrom(System.Tuple`2[System.Boolean,System.Boolean], FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynExpr+YieldOrReturn: FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia get_trivia() +FSharp.Compiler.Syntax.SynExpr+YieldOrReturn: FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia trivia +FSharp.Compiler.Syntax.SynExpr+YieldOrReturnFrom: FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnFromTrivia get_trivia() +FSharp.Compiler.Syntax.SynExpr+YieldOrReturnFrom: FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnFromTrivia trivia +FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewYieldOrReturn(System.Tuple`2[System.Boolean,System.Boolean], FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia) +FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewYieldOrReturnFrom(System.Tuple`2[System.Boolean,System.Boolean], FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnFromTrivia) +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnFromTrivia: FSharp.Compiler.Text.Range YieldOrReturnFromKeyword +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnFromTrivia: FSharp.Compiler.Text.Range get_YieldOrReturnFromKeyword() +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnFromTrivia: System.String ToString() +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnFromTrivia: Void .ctor(FSharp.Compiler.Text.Range) +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia: FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia Zero +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia: FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia get_Zero() +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia: FSharp.Compiler.Text.Range YieldOrReturnKeyword +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia: FSharp.Compiler.Text.Range get_YieldOrReturnKeyword() +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia: System.String ToString() +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia: Void .ctor(FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr+AddressOf FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr+AnonRecd FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr+App 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 da62302304a..42ec38ee366 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 @@ -7668,8 +7668,22 @@ FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewTyped(FSharp.C FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewUpcast(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewWhile(FSharp.Compiler.Syntax.DebugPointAtWhile, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewWhileBang(FSharp.Compiler.Syntax.DebugPointAtWhile, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range) -FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewYieldOrReturn(System.Tuple`2[System.Boolean,System.Boolean], FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range) -FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewYieldOrReturnFrom(System.Tuple`2[System.Boolean,System.Boolean], FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynExpr+YieldOrReturn: FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia get_trivia() +FSharp.Compiler.Syntax.SynExpr+YieldOrReturn: FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia trivia +FSharp.Compiler.Syntax.SynExpr+YieldOrReturnFrom: FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnFromTrivia get_trivia() +FSharp.Compiler.Syntax.SynExpr+YieldOrReturnFrom: FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnFromTrivia trivia +FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewYieldOrReturn(System.Tuple`2[System.Boolean,System.Boolean], FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia) +FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewYieldOrReturnFrom(System.Tuple`2[System.Boolean,System.Boolean], FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnFromTrivia) +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnFromTrivia: FSharp.Compiler.Text.Range YieldOrReturnFromKeyword +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnFromTrivia: FSharp.Compiler.Text.Range get_YieldOrReturnFromKeyword() +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnFromTrivia: System.String ToString() +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnFromTrivia: Void .ctor(FSharp.Compiler.Text.Range) +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia: FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia Zero +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia: FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia get_Zero() +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia: FSharp.Compiler.Text.Range YieldOrReturnKeyword +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia: FSharp.Compiler.Text.Range get_YieldOrReturnKeyword() +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia: System.String ToString() +FSharp.Compiler.SyntaxTrivia.SynExprYieldOrReturnTrivia: Void .ctor(FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr+AddressOf FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr+AnonRecd FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr+App diff --git a/tests/fsharp/typecheck/sigs/neg104.vsbsl b/tests/fsharp/typecheck/sigs/neg104.vsbsl index 8a6059aa128..165b4348e35 100644 --- a/tests/fsharp/typecheck/sigs/neg104.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg104.vsbsl @@ -27,4 +27,4 @@ neg104.fs(20,9,20,15): typecheck error FS0025: Incomplete pattern matches on thi neg104.fs(23,9,23,15): typecheck error FS0025: Incomplete pattern matches on this expression. -neg104.fs(35,9,35,18): typecheck error FS0748: This construct may only be used within computation expressions. To return a value from an ordinary function simply write the expression without 'return'. +neg104.fs(35,9,35,15): typecheck error FS0748: This construct may only be used within computation expressions. To return a value from an ordinary function simply write the expression without 'return'. diff --git a/tests/fsharp/typecheck/sigs/neg107.bsl b/tests/fsharp/typecheck/sigs/neg107.bsl index 30b24d25c59..580233b4775 100644 --- a/tests/fsharp/typecheck/sigs/neg107.bsl +++ b/tests/fsharp/typecheck/sigs/neg107.bsl @@ -33,11 +33,11 @@ neg107.fsx(28,55,28,66): typecheck error FS0425: The type of a first-class funct neg107.fsx(30,49,30,54): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. -neg107.fsx(30,57,30,65): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. +neg107.fsx(30,64,30,65): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. neg107.fsx(31,70,31,75): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. -neg107.fsx(31,78,31,86): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. +neg107.fsx(31,85,31,86): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. neg107.fsx(32,13,32,30): typecheck error FS3301: The function or method has an invalid return type 'Async>'. This is not permitted by the rules of Common IL. @@ -49,13 +49,13 @@ neg107.fsx(32,48,32,53): typecheck error FS0406: The byref-typed variable 'a' is neg107.fsx(32,48,32,53): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. -neg107.fsx(32,56,32,64): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. +neg107.fsx(32,63,32,64): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. -neg107.fsx(32,56,32,64): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. +neg107.fsx(32,63,32,64): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. -neg107.fsx(32,56,32,64): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. +neg107.fsx(32,63,32,64): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. -neg107.fsx(32,56,32,64): typecheck error FS0425: The type of a first-class function cannot contain byrefs +neg107.fsx(32,63,32,64): typecheck error FS0425: The type of a first-class function cannot contain byrefs neg107.fsx(32,48,32,53): typecheck error FS0425: The type of a first-class function cannot contain byrefs @@ -69,13 +69,13 @@ neg107.fsx(33,56,33,61): typecheck error FS0406: The byref-typed variable 'a' is neg107.fsx(33,56,33,61): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. -neg107.fsx(33,64,33,72): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. +neg107.fsx(33,71,33,72): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. -neg107.fsx(33,64,33,72): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. +neg107.fsx(33,71,33,72): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. -neg107.fsx(33,64,33,72): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. +neg107.fsx(33,71,33,72): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. -neg107.fsx(33,64,33,72): typecheck error FS0425: The type of a first-class function cannot contain byrefs +neg107.fsx(33,71,33,72): typecheck error FS0425: The type of a first-class function cannot contain byrefs neg107.fsx(33,56,33,61): typecheck error FS0425: The type of a first-class function cannot contain byrefs diff --git a/tests/fsharp/typecheck/sigs/neg107.vsbsl b/tests/fsharp/typecheck/sigs/neg107.vsbsl index 30b24d25c59..580233b4775 100644 --- a/tests/fsharp/typecheck/sigs/neg107.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg107.vsbsl @@ -33,11 +33,11 @@ neg107.fsx(28,55,28,66): typecheck error FS0425: The type of a first-class funct neg107.fsx(30,49,30,54): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. -neg107.fsx(30,57,30,65): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. +neg107.fsx(30,64,30,65): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. neg107.fsx(31,70,31,75): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. -neg107.fsx(31,78,31,86): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. +neg107.fsx(31,85,31,86): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. neg107.fsx(32,13,32,30): typecheck error FS3301: The function or method has an invalid return type 'Async>'. This is not permitted by the rules of Common IL. @@ -49,13 +49,13 @@ neg107.fsx(32,48,32,53): typecheck error FS0406: The byref-typed variable 'a' is neg107.fsx(32,48,32,53): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. -neg107.fsx(32,56,32,64): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. +neg107.fsx(32,63,32,64): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. -neg107.fsx(32,56,32,64): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. +neg107.fsx(32,63,32,64): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. -neg107.fsx(32,56,32,64): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. +neg107.fsx(32,63,32,64): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. -neg107.fsx(32,56,32,64): typecheck error FS0425: The type of a first-class function cannot contain byrefs +neg107.fsx(32,63,32,64): typecheck error FS0425: The type of a first-class function cannot contain byrefs neg107.fsx(32,48,32,53): typecheck error FS0425: The type of a first-class function cannot contain byrefs @@ -69,13 +69,13 @@ neg107.fsx(33,56,33,61): typecheck error FS0406: The byref-typed variable 'a' is neg107.fsx(33,56,33,61): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. -neg107.fsx(33,64,33,72): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. +neg107.fsx(33,71,33,72): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. -neg107.fsx(33,64,33,72): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. +neg107.fsx(33,71,33,72): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions. -neg107.fsx(33,64,33,72): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. +neg107.fsx(33,71,33,72): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. -neg107.fsx(33,64,33,72): typecheck error FS0425: The type of a first-class function cannot contain byrefs +neg107.fsx(33,71,33,72): typecheck error FS0425: The type of a first-class function cannot contain byrefs neg107.fsx(33,56,33,61): typecheck error FS0425: The type of a first-class function cannot contain byrefs diff --git a/tests/fsharp/typecheck/sigs/neg20.bsl b/tests/fsharp/typecheck/sigs/neg20.bsl index ea20ab65acf..5229dcaacf6 100644 --- a/tests/fsharp/typecheck/sigs/neg20.bsl +++ b/tests/fsharp/typecheck/sigs/neg20.bsl @@ -67,7 +67,7 @@ but given a 'B list' The type 'A' does not match the type 'B' -neg20.fs(80,23,80,39): typecheck error FS0193: Type constraint mismatch. The type +neg20.fs(80,30,80,39): typecheck error FS0193: Type constraint mismatch. The type 'C list' is not compatible with type 'B seq' diff --git a/tests/fsharp/typecheck/sigs/neg59.bsl b/tests/fsharp/typecheck/sigs/neg59.bsl index 624750b9352..a938f0d271c 100644 --- a/tests/fsharp/typecheck/sigs/neg59.bsl +++ b/tests/fsharp/typecheck/sigs/neg59.bsl @@ -41,6 +41,6 @@ neg59.fs(113,15,113,25): typecheck error FS3140: 'while' expressions may not be neg59.fs(118,15,118,25): typecheck error FS3140: 'while' expressions may not be used in queries -neg59.fs(124,17,124,25): typecheck error FS3144: 'return' and 'return!' may not be used in queries +neg59.fs(124,17,124,23): typecheck error FS3144: 'return' and 'return!' may not be used in queries -neg59.fs(128,17,128,26): typecheck error FS3144: 'return' and 'return!' may not be used in queries +neg59.fs(128,17,128,24): typecheck error FS3144: 'return' and 'return!' may not be used in queries diff --git a/tests/fsharp/typecheck/sigs/neg61.bsl b/tests/fsharp/typecheck/sigs/neg61.bsl index 91291a6cb94..b0e6b151a2c 100644 --- a/tests/fsharp/typecheck/sigs/neg61.bsl +++ b/tests/fsharp/typecheck/sigs/neg61.bsl @@ -63,9 +63,9 @@ neg61.fs(97,13,97,17): typecheck error FS3143: 'let!', 'use!' and 'do!' expressi neg61.fs(102,13,102,16): typecheck error FS3143: 'let!', 'use!' and 'do!' expressions may not be used in queries -neg61.fs(107,13,107,21): typecheck error FS3144: 'return' and 'return!' may not be used in queries +neg61.fs(107,13,107,19): typecheck error FS3144: 'return' and 'return!' may not be used in queries -neg61.fs(111,13,111,24): typecheck error FS3144: 'return' and 'return!' may not be used in queries +neg61.fs(111,13,111,20): typecheck error FS3144: 'return' and 'return!' may not be used in queries neg61.fs(114,13,114,21): typecheck error FS3145: This is not a known query operator. Query operators are identifiers such as 'select', 'where', 'sortBy', 'thenBy', 'groupBy', 'groupValBy', 'join', 'groupJoin', 'sumBy' and 'averageBy', defined using corresponding methods on the 'QueryBuilder' type. diff --git a/tests/fsharp/typecheck/sigs/version50/neg20.bsl b/tests/fsharp/typecheck/sigs/version50/neg20.bsl index 169c18e8573..394f7777b2a 100644 --- a/tests/fsharp/typecheck/sigs/version50/neg20.bsl +++ b/tests/fsharp/typecheck/sigs/version50/neg20.bsl @@ -98,7 +98,7 @@ but given a 'B list' The type 'A' does not match the type 'B' -neg20.fs(80,23,80,39): typecheck error FS0193: Type constraint mismatch. The type +neg20.fs(80,30,80,39): typecheck error FS0193: Type constraint mismatch. The type 'C list' is not compatible with type 'B seq' diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingReturn.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingReturn.fs index a0bb521f1af..5010e70386b 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingReturn.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingReturn.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DataExpressions #ComputationExpressions // Regression test for FSHARP1.0:6149 -//This control construct may only be used if the computation expression builder defines a 'Return' method$ +//This control construct may only be used if the computation expression builder defines a 'Return' method$ type R = S of string diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingReturnFrom.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingReturnFrom.fs index 24f20ffb9ac..f8185a9b7fa 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingReturnFrom.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingReturnFrom.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DataExpressions #ComputationExpressions // Regression test for FSHARP1.0:6149 -//This control construct may only be used if the computation expression builder defines a 'ReturnFrom' method$ +//This control construct may only be used if the computation expression builder defines a 'ReturnFrom' method$ type R = S of string diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingYield.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingYield.fs index b731412bfa6..7251faf3978 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingYield.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingYield.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DataExpressions #ComputationExpressions // Regression test for FSHARP1.0:6149 -//This control construct may only be used if the computation expression builder defines a 'Yield' method$ +//This control construct may only be used if the computation expression builder defines a 'Yield' method$ type R = S of string diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingYieldFrom.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingYieldFrom.fs index 63ada5cd6be..3777c375f2b 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingYieldFrom.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ComputationExpressions/E_MissingYieldFrom.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DataExpressions #ComputationExpressions // Regression test for FSHARP1.0:6149 -//This control construct may only be used if the computation expression builder defines a 'YieldFrom' method$ +//This control construct may only be used if the computation expression builder defines a 'YieldFrom' method$ type R = S of string diff --git a/tests/service/data/SyntaxTree/ComputationExpression/MultipleSynExprAndBangHaveRangeThatStartsAtAndAndEndsAfterExpression.fs.bsl b/tests/service/data/SyntaxTree/ComputationExpression/MultipleSynExprAndBangHaveRangeThatStartsAtAndAndEndsAfterExpression.fs.bsl index 72f8528c23f..16e62c6c1aa 100644 --- a/tests/service/data/SyntaxTree/ComputationExpression/MultipleSynExprAndBangHaveRangeThatStartsAtAndAndEndsAfterExpression.fs.bsl +++ b/tests/service/data/SyntaxTree/ComputationExpression/MultipleSynExprAndBangHaveRangeThatStartsAtAndAndEndsAfterExpression.fs.bsl @@ -39,10 +39,12 @@ ImplFile (5,4--5,24), { AndBangKeyword = (5,4--5,8) EqualsRange = (5,13--5,14) InKeyword = None })], - YieldOrReturn ((false, true), Ident bar, (6,4--6,14)), - (3,4--6,14), { LetOrUseBangKeyword = (3,4--3,8) - EqualsRange = Some (3,13--3,14) }), - (2,6--7,1)), (2,0--7,1)), (2,0--7,1))], PreXmlDocEmpty, [], - None, (2,0--7,1), { LeadingKeyword = None })], (true, true), + YieldOrReturn + ((false, true), Ident bar, (6,4--6,14), + { YieldOrReturnKeyword = (6,4--6,10) }), (3,4--6,14), + { LetOrUseBangKeyword = (3,4--3,8) + EqualsRange = Some (3,13--3,14) }), (2,6--7,1)), + (2,0--7,1)), (2,0--7,1))], PreXmlDocEmpty, [], None, (2,0--7,1), + { LeadingKeyword = None })], (true, true), { ConditionalDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/ComputationExpression/SynExprAndBangRangeStartsAtAndAndEndsAfterExpression.fs.bsl b/tests/service/data/SyntaxTree/ComputationExpression/SynExprAndBangRangeStartsAtAndAndEndsAfterExpression.fs.bsl index d0dd3083e64..9ee7e15f532 100644 --- a/tests/service/data/SyntaxTree/ComputationExpression/SynExprAndBangRangeStartsAtAndAndEndsAfterExpression.fs.bsl +++ b/tests/service/data/SyntaxTree/ComputationExpression/SynExprAndBangRangeStartsAtAndAndEndsAfterExpression.fs.bsl @@ -28,10 +28,12 @@ ImplFile (5,4--5,24), { AndBangKeyword = (5,4--5,8) EqualsRange = (5,13--5,14) InKeyword = None })], - YieldOrReturn ((false, true), Ident bar, (7,4--7,14)), - (3,4--7,14), { LetOrUseBangKeyword = (3,4--3,8) - EqualsRange = Some (3,13--3,14) }), - (2,6--8,1)), (2,0--8,1)), (2,0--8,1))], PreXmlDocEmpty, [], - None, (2,0--8,1), { LeadingKeyword = None })], (true, true), + YieldOrReturn + ((false, true), Ident bar, (7,4--7,14), + { YieldOrReturnKeyword = (7,4--7,10) }), (3,4--7,14), + { LetOrUseBangKeyword = (3,4--3,8) + EqualsRange = Some (3,13--3,14) }), (2,6--8,1)), + (2,0--8,1)), (2,0--8,1))], PreXmlDocEmpty, [], None, (2,0--8,1), + { LeadingKeyword = None })], (true, true), { ConditionalDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/List - Comprehension 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/List - Comprehension 01.fs.bsl index 7cc9b348848..517c835a63a 100644 --- a/tests/service/data/SyntaxTree/Expression/List - Comprehension 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/List - Comprehension 01.fs.bsl @@ -12,8 +12,9 @@ ImplFile Named (SynIdent (x, None), false, None, (3,6--3,7)), ArrayOrList (false, [], (3,11--3,13)), YieldOrReturn - ((true, false), Const (Unit, (3,17--3,19)), (3,14--3,19)), - (3,2--3,19)), (3,0--3,21)), (3,0--3,21))], + ((true, false), Const (Unit, (3,17--3,19)), (3,14--3,19), + { YieldOrReturnKeyword = (3,14--3,16) }), (3,2--3,19)), + (3,0--3,21)), (3,0--3,21))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,21), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/List - Comprehension 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/List - Comprehension 02.fs.bsl index 1a89da1b0fb..9897592fb0a 100644 --- a/tests/service/data/SyntaxTree/Expression/List - Comprehension 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/List - Comprehension 02.fs.bsl @@ -15,7 +15,8 @@ ImplFile ((true, false), ArbitraryAfterError ("typedSequentialExprBlockR1", (3,16--3,16)), - (3,14--3,16)), (3,2--3,16)), (3,0--3,18)), (3,0--3,18))], + (3,14--3,16), { YieldOrReturnKeyword = (3,14--3,16) }), + (3,2--3,16)), (3,0--3,18)), (3,0--3,18))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,18), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Rarrow 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/Rarrow 01.fs.bsl index 9d7e7af2125..c3c454436ce 100644 --- a/tests/service/data/SyntaxTree/Expression/Rarrow 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Rarrow 01.fs.bsl @@ -5,8 +5,8 @@ ImplFile ([Module], false, NamedModule, [Expr (YieldOrReturn - ((true, true), Const (Int32 1, (3,3--3,4)), (3,0--3,4)), - (3,0--3,4))], + ((true, true), Const (Int32 1, (3,3--3,4)), (3,0--3,4), + { YieldOrReturnKeyword = (3,0--3,2) }), (3,0--3,4))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,4), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Rarrow 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/Rarrow 02.fs.bsl index 54570b38728..3a0af632862 100644 --- a/tests/service/data/SyntaxTree/Expression/Rarrow 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Rarrow 02.fs.bsl @@ -7,7 +7,7 @@ ImplFile (YieldOrReturn ((true, true), ArbitraryAfterError ("typedSequentialExprBlockR1", (3,2--3,2)), - (3,0--3,2)), (3,0--3,2))], + (3,0--3,2), { YieldOrReturnKeyword = (3,0--3,2) }), (3,0--3,2))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Rarrow 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/Rarrow 03.fs.bsl index e0d4104ac0a..ceae74bf09b 100644 --- a/tests/service/data/SyntaxTree/Expression/Rarrow 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Rarrow 03.fs.bsl @@ -9,8 +9,9 @@ ImplFile YieldOrReturn ((true, true), ArbitraryAfterError - ("typedSequentialExprBlockR1", (3,5--3,5)), (3,3--3,5)), - (3,0--3,5)), (3,0--3,5))], + ("typedSequentialExprBlockR1", (3,5--3,5)), (3,3--3,5), + { YieldOrReturnKeyword = (3,3--3,5) }), (3,0--3,5), + { YieldOrReturnKeyword = (3,0--3,2) }), (3,0--3,5))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseBangContainsTheRangeOfTheEqualsSign.fs.bsl b/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseBangContainsTheRangeOfTheEqualsSign.fs.bsl index a0f54029820..0264686482c 100644 --- a/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseBangContainsTheRangeOfTheEqualsSign.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseBangContainsTheRangeOfTheEqualsSign.fs.bsl @@ -26,10 +26,11 @@ ImplFile EqualsRange = (4,11--4,12) InKeyword = None })], YieldOrReturn - ((false, true), Const (Unit, (5,11--5,13)), (5,4--5,13)), - (3,4--5,13), { LetOrUseBangKeyword = (3,4--3,8) - EqualsRange = Some (3,11--3,12) }), - (2,5--6,1)), (2,0--6,1)), (2,0--6,1))], PreXmlDocEmpty, [], - None, (2,0--6,1), { LeadingKeyword = None })], (true, true), + ((false, true), Const (Unit, (5,11--5,13)), (5,4--5,13), + { YieldOrReturnKeyword = (5,4--5,10) }), (3,4--5,13), + { LetOrUseBangKeyword = (3,4--3,8) + EqualsRange = Some (3,11--3,12) }), (2,5--6,1)), + (2,0--6,1)), (2,0--6,1))], PreXmlDocEmpty, [], None, (2,0--6,1), + { LeadingKeyword = None })], (true, true), { ConditionalDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/WhileBang 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/WhileBang 01.fs.bsl index 936525524f3..deb6d27aa83 100644 --- a/tests/service/data/SyntaxTree/Expression/WhileBang 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/WhileBang 01.fs.bsl @@ -13,8 +13,9 @@ ImplFile (false, YieldOrReturn ((false, true), Const (Bool true, (3,22--3,26)), - (3,15--3,26)), (3,13--3,28)), (3,7--3,28)), - Const (Int32 2, (4,4--4,5)), (3,0--4,5)), (3,0--4,5)); + (3,15--3,26), { YieldOrReturnKeyword = (3,15--3,21) }), + (3,13--3,28)), (3,7--3,28)), Const (Int32 2, (4,4--4,5)), + (3,0--4,5)), (3,0--4,5)); Expr (Const (Int32 3, (6,0--6,1)), (6,0--6,1))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--6,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), diff --git a/tests/service/data/SyntaxTree/Expression/WhileBang 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/WhileBang 02.fs.bsl index b12f9b0df18..52eaca7bfdc 100644 --- a/tests/service/data/SyntaxTree/Expression/WhileBang 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/WhileBang 02.fs.bsl @@ -13,8 +13,9 @@ ImplFile (false, YieldOrReturn ((false, true), Const (Bool true, (3,22--3,26)), - (3,15--3,26)), (3,13--3,28)), (3,7--3,28)), - Const (Int32 2, (4,4--4,5)), (3,0--5,4)), (3,0--5,4)); + (3,15--3,26), { YieldOrReturnKeyword = (3,15--3,21) }), + (3,13--3,28)), (3,7--3,28)), Const (Int32 2, (4,4--4,5)), + (3,0--5,4)), (3,0--5,4)); Expr (Const (Int32 3, (7,0--7,1)), (7,0--7,1))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), diff --git a/tests/service/data/SyntaxTree/Expression/WhileBang 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/WhileBang 03.fs.bsl index a5793465b34..437c23a2c6b 100644 --- a/tests/service/data/SyntaxTree/Expression/WhileBang 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/WhileBang 03.fs.bsl @@ -20,7 +20,9 @@ ImplFile (false, YieldOrReturn ((false, true), Const (Bool true, (4,26--4,30)), - (4,19--4,30)), (4,17--4,32)), (4,11--4,32)), + (4,19--4,30), + { YieldOrReturnKeyword = (4,19--4,25) }), + (4,17--4,32)), (4,11--4,32)), ArbitraryAfterError ("whileBody1", (6,0--6,1)), (4,4--4,35)), (3,4--3,5), Yes (3,0--4,35), { LeadingKeyword = Let (3,0--3,3) InlineKeyword = None diff --git a/tests/service/data/SyntaxTree/Expression/WhileBang 04.fs.bsl b/tests/service/data/SyntaxTree/Expression/WhileBang 04.fs.bsl index 863c8aaabfe..70db990cb0e 100644 --- a/tests/service/data/SyntaxTree/Expression/WhileBang 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/WhileBang 04.fs.bsl @@ -20,7 +20,9 @@ ImplFile (false, YieldOrReturn ((false, true), Const (Bool true, (4,26--4,30)), - (4,19--4,30)), (4,17--4,32)), (4,11--4,32)), + (4,19--4,30), + { YieldOrReturnKeyword = (4,19--4,25) }), + (4,17--4,32)), (4,11--4,32)), ArbitraryAfterError ("whileBody1", (5,0--5,0)), (4,4--4,35)), (3,4--3,5), Yes (3,0--4,35), { LeadingKeyword = Let (3,0--3,3) InlineKeyword = None diff --git a/tests/service/data/SyntaxTree/Expression/WhileBang 05.fs.bsl b/tests/service/data/SyntaxTree/Expression/WhileBang 05.fs.bsl index e2f5875ef4b..a8b4a21543b 100644 --- a/tests/service/data/SyntaxTree/Expression/WhileBang 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/WhileBang 05.fs.bsl @@ -20,7 +20,9 @@ ImplFile (false, YieldOrReturn ((false, true), Const (Bool true, (4,26--4,30)), - (4,19--4,30)), (4,17--4,32)), (4,11--4,32)), + (4,19--4,30), + { YieldOrReturnKeyword = (4,19--4,25) }), + (4,17--4,32)), (4,11--4,32)), Const (Int32 2, (5,8--5,9)), (4,4--5,9)), (3,4--3,5), Yes (3,0--5,9), { LeadingKeyword = Let (3,0--3,3) InlineKeyword = None diff --git a/tests/service/data/SyntaxTree/Expression/WhileBang 06.fs.bsl b/tests/service/data/SyntaxTree/Expression/WhileBang 06.fs.bsl index 3c8ef1cbebf..df87ceb6a9d 100644 --- a/tests/service/data/SyntaxTree/Expression/WhileBang 06.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/WhileBang 06.fs.bsl @@ -20,7 +20,9 @@ ImplFile (false, YieldOrReturn ((false, true), Const (Bool true, (4,26--4,30)), - (4,19--4,30)), (4,17--4,32)), (4,11--4,32)), + (4,19--4,30), + { YieldOrReturnKeyword = (4,19--4,25) }), + (4,17--4,32)), (4,11--4,32)), Const (Int32 2, (5,4--5,5)), (4,4--5,5)), (3,4--3,5), Yes (3,0--5,5), { LeadingKeyword = Let (3,0--3,3) InlineKeyword = None diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/RemoveReturnOrYield.fs b/vsintegration/src/FSharp.Editor/CodeFixes/RemoveReturnOrYield.fs index cbc22219a12..ec376552709 100644 --- a/vsintegration/src/FSharp.Editor/CodeFixes/RemoveReturnOrYield.fs +++ b/vsintegration/src/FSharp.Editor/CodeFixes/RemoveReturnOrYield.fs @@ -30,7 +30,11 @@ type internal RemoveReturnOrYieldCodeFixProvider [] () = parseResults.TryRangeOfExprInYieldOrReturn errorRange.Start |> ValueOption.ofOption |> ValueOption.map (fun exprRange -> RoslynHelpers.FSharpRangeToTextSpan(sourceText, exprRange)) - |> ValueOption.map (fun exprSpan -> [ TextChange(context.Span, sourceText.GetSubText(exprSpan).ToString()) ]) + |> ValueOption.map (fun exprSpan -> + [ + // meaning: keyword + spacing before the expression + TextChange(TextSpan(context.Span.Start, exprSpan.Start - context.Span.Start), "") + ]) |> ValueOption.map (fun changes -> let title = let text = sourceText.GetSubText(context.Span).ToString() diff --git a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/RemoveReturnOrYieldTests.fs b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/RemoveReturnOrYieldTests.fs index 23d5908d557..a93bd4f6a3a 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/RemoveReturnOrYieldTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/RemoveReturnOrYieldTests.fs @@ -102,3 +102,50 @@ let answer question = let actual = codeFix |> tryFix code Auto Assert.Equal(expected, actual) + +[] +let ``Handles spaces`` () = + let code = + """ +let answer question = + yield 42 +""" + + let expected = + Some + { + Message = "Remove 'yield'" + FixedCode = + """ +let answer question = + 42 +""" + } + + let actual = codeFix |> tryFix code Auto + + Assert.Equal(expected, actual) + +[] +let ``Handles new lines`` () = + let code = + """ +let answer question = + return! + 42 +""" + + let expected = + Some + { + Message = "Remove 'return!'" + FixedCode = + """ +let answer question = + 42 +""" + } + + let actual = codeFix |> tryFix code Auto + + Assert.Equal(expected, actual)