diff --git a/FSharp.sln b/FSharp.sln index e1c47795e8d..75fa9032a91 100644 --- a/FSharp.sln +++ b/FSharp.sln @@ -39,6 +39,10 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.LanguageSer EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.LanguageServer.UnitTests", "tests\FSharp.Compiler.LanguageServer.UnitTests\FSharp.Compiler.LanguageServer.UnitTests.fsproj", "{C97819B0-B428-4B96-9CD7-497D2D1C738C}" EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Scripting", "src\fsharp\FSharp.Compiler.Scripting\FSharp.Compiler.Scripting.fsproj", "{6771860A-614D-4FDD-A655-4C70EBCC91B0}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Scripting.UnitTests", "tests\FSharp.Compiler.Scripting.UnitTests\FSharp.Compiler.Scripting.UnitTests.fsproj", "{4FEDF286-0252-4EBC-9E75-879CCA3B85DC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -205,6 +209,30 @@ Global {C97819B0-B428-4B96-9CD7-497D2D1C738C}.Release|Any CPU.Build.0 = Release|Any CPU {C97819B0-B428-4B96-9CD7-497D2D1C738C}.Release|x86.ActiveCfg = Release|Any CPU {C97819B0-B428-4B96-9CD7-497D2D1C738C}.Release|x86.Build.0 = Release|Any CPU + {6771860A-614D-4FDD-A655-4C70EBCC91B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6771860A-614D-4FDD-A655-4C70EBCC91B0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6771860A-614D-4FDD-A655-4C70EBCC91B0}.Debug|x86.ActiveCfg = Debug|Any CPU + {6771860A-614D-4FDD-A655-4C70EBCC91B0}.Debug|x86.Build.0 = Debug|Any CPU + {6771860A-614D-4FDD-A655-4C70EBCC91B0}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {6771860A-614D-4FDD-A655-4C70EBCC91B0}.Proto|Any CPU.Build.0 = Debug|Any CPU + {6771860A-614D-4FDD-A655-4C70EBCC91B0}.Proto|x86.ActiveCfg = Debug|Any CPU + {6771860A-614D-4FDD-A655-4C70EBCC91B0}.Proto|x86.Build.0 = Debug|Any CPU + {6771860A-614D-4FDD-A655-4C70EBCC91B0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6771860A-614D-4FDD-A655-4C70EBCC91B0}.Release|Any CPU.Build.0 = Release|Any CPU + {6771860A-614D-4FDD-A655-4C70EBCC91B0}.Release|x86.ActiveCfg = Release|Any CPU + {6771860A-614D-4FDD-A655-4C70EBCC91B0}.Release|x86.Build.0 = Release|Any CPU + {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Debug|x86.ActiveCfg = Debug|Any CPU + {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Debug|x86.Build.0 = Debug|Any CPU + {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Proto|Any CPU.Build.0 = Debug|Any CPU + {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Proto|x86.ActiveCfg = Debug|Any CPU + {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Proto|x86.Build.0 = Debug|Any CPU + {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Release|Any CPU.Build.0 = Release|Any CPU + {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Release|x86.ActiveCfg = Release|Any CPU + {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -223,6 +251,8 @@ Global {81B9FE26-C976-4FC7-B6CC-C7DB5903CAA7} = {3840F2E7-3898-45F7-8CF7-1E6829E56DB8} {99B3F4A5-80B4-41D9-A073-117DB6D7DBBA} = {B8DDA694-7939-42E3-95E5-265C2217C142} {C97819B0-B428-4B96-9CD7-497D2D1C738C} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} + {6771860A-614D-4FDD-A655-4C70EBCC91B0} = {B8DDA694-7939-42E3-95E5-265C2217C142} + {4FEDF286-0252-4EBC-9E75-879CCA3B85DC} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BD5177C7-1380-40E7-94D2-7768E1A8B1B8} diff --git a/VisualFSharp.sln b/VisualFSharp.sln index 4a1e75f446a..6e4587ddb62 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -158,7 +158,11 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.LanguageSer EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.LanguageServer.UnitTests", "tests\FSharp.Compiler.LanguageServer.UnitTests\FSharp.Compiler.LanguageServer.UnitTests.fsproj", "{AAF2D233-1C38-4090-8FFA-F7C545625E06}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FSharp.Editor.Helpers", "vsintegration\src\FSharp.Editor.Helpers\FSharp.Editor.Helpers.csproj", "{79255A92-ED00-40BA-9D64-12FCC664A976}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FSharp.Editor.Helpers", "vsintegration\src\FSharp.Editor.Helpers\FSharp.Editor.Helpers.csproj", "{79255A92-ED00-40BA-9D64-12FCC664A976}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Scripting", "src\fsharp\FSharp.Compiler.Scripting\FSharp.Compiler.Scripting.fsproj", "{20B7BC36-CF51-4D75-9E13-66681C07977F}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Scripting.UnitTests", "tests\FSharp.Compiler.Scripting.UnitTests\FSharp.Compiler.Scripting.UnitTests.fsproj", "{09F56540-AFA5-4694-B7A6-0DBF6D4618C2}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -926,6 +930,30 @@ Global {79255A92-ED00-40BA-9D64-12FCC664A976}.Release|Any CPU.Build.0 = Release|Any CPU {79255A92-ED00-40BA-9D64-12FCC664A976}.Release|x86.ActiveCfg = Release|Any CPU {79255A92-ED00-40BA-9D64-12FCC664A976}.Release|x86.Build.0 = Release|Any CPU + {20B7BC36-CF51-4D75-9E13-66681C07977F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {20B7BC36-CF51-4D75-9E13-66681C07977F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {20B7BC36-CF51-4D75-9E13-66681C07977F}.Debug|x86.ActiveCfg = Debug|Any CPU + {20B7BC36-CF51-4D75-9E13-66681C07977F}.Debug|x86.Build.0 = Debug|Any CPU + {20B7BC36-CF51-4D75-9E13-66681C07977F}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {20B7BC36-CF51-4D75-9E13-66681C07977F}.Proto|Any CPU.Build.0 = Debug|Any CPU + {20B7BC36-CF51-4D75-9E13-66681C07977F}.Proto|x86.ActiveCfg = Debug|Any CPU + {20B7BC36-CF51-4D75-9E13-66681C07977F}.Proto|x86.Build.0 = Debug|Any CPU + {20B7BC36-CF51-4D75-9E13-66681C07977F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {20B7BC36-CF51-4D75-9E13-66681C07977F}.Release|Any CPU.Build.0 = Release|Any CPU + {20B7BC36-CF51-4D75-9E13-66681C07977F}.Release|x86.ActiveCfg = Release|Any CPU + {20B7BC36-CF51-4D75-9E13-66681C07977F}.Release|x86.Build.0 = Release|Any CPU + {09F56540-AFA5-4694-B7A6-0DBF6D4618C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09F56540-AFA5-4694-B7A6-0DBF6D4618C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09F56540-AFA5-4694-B7A6-0DBF6D4618C2}.Debug|x86.ActiveCfg = Debug|Any CPU + {09F56540-AFA5-4694-B7A6-0DBF6D4618C2}.Debug|x86.Build.0 = Debug|Any CPU + {09F56540-AFA5-4694-B7A6-0DBF6D4618C2}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {09F56540-AFA5-4694-B7A6-0DBF6D4618C2}.Proto|Any CPU.Build.0 = Debug|Any CPU + {09F56540-AFA5-4694-B7A6-0DBF6D4618C2}.Proto|x86.ActiveCfg = Debug|Any CPU + {09F56540-AFA5-4694-B7A6-0DBF6D4618C2}.Proto|x86.Build.0 = Debug|Any CPU + {09F56540-AFA5-4694-B7A6-0DBF6D4618C2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09F56540-AFA5-4694-B7A6-0DBF6D4618C2}.Release|Any CPU.Build.0 = Release|Any CPU + {09F56540-AFA5-4694-B7A6-0DBF6D4618C2}.Release|x86.ActiveCfg = Release|Any CPU + {09F56540-AFA5-4694-B7A6-0DBF6D4618C2}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1001,6 +1029,8 @@ Global {60BAFFA5-6631-4328-B044-2E012AB76DCA} = {B8DDA694-7939-42E3-95E5-265C2217C142} {AAF2D233-1C38-4090-8FFA-F7C545625E06} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {79255A92-ED00-40BA-9D64-12FCC664A976} = {4C7B48D7-19AF-4AE7-9D1D-3BB289D5480D} + {20B7BC36-CF51-4D75-9E13-66681C07977F} = {B8DDA694-7939-42E3-95E5-265C2217C142} + {09F56540-AFA5-4694-B7A6-0DBF6D4618C2} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {48EDBBBE-C8EE-4E3C-8B19-97184A487B37} diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 53288c73d3f..891be559808 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -56,6 +56,7 @@ stages: - group: DotNet-Blob-Feed - group: DotNet-Symbol-Server-Pats - group: DotNet-DevDiv-Insertion-Workflow-Variables + - group: 'F# MyGet API Keys' - name: _SignType value: Real - name: _DotNetPublishToBlobFeed @@ -130,6 +131,13 @@ stages: DropFolder: '$(Build.SourcesDirectory)\artifacts\VSSetup\$(_BuildConfig)\Insertion' AccessToken: $(dn-bot-devdiv-drop-rw-code-rw) condition: succeeded() + - pwsh: .\eng\publish-myget.ps1 + -artifactsDir "$(Build.SourcesDirectory)\artifacts" + -apiKey "$(FSharpMyGetAPIKey)" + -configuration $(_BuildConfig) + displayName: Upload MyGet packages + continueOnError: true + condition: and(succeeded(), eq('$(Build.SourceBranch)', 'master')) #-------------------------------------------------------------------------------------------------------------------# # PR builds # diff --git a/eng/Build.ps1 b/eng/Build.ps1 index 75f0178b7d2..f6a3f289c48 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -337,6 +337,7 @@ try { if ($testDesktop -and -not $noVisualStudio) { TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.UnitTests\FSharp.Compiler.UnitTests.fsproj" -targetFramework $desktopTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.LanguageServer.UnitTests\FSharp.Compiler.LanguageServer.UnitTests.fsproj" -targetFramework $desktopTargetFramework + TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.Scripting.UnitTests\FSharp.Compiler.Scripting.UnitTests.fsproj" -targetFramework $desktopTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Build.UnitTests\FSharp.Build.UnitTests.fsproj" -targetFramework $desktopTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Core.UnitTests\FSharp.Core.UnitTests.fsproj" -targetFramework $desktopTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\fsharp\FSharpSuite.Tests.fsproj" -targetFramework $desktopTargetFramework @@ -345,6 +346,7 @@ try { if ($testCoreClr) { TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.UnitTests\FSharp.Compiler.UnitTests.fsproj" -targetFramework $coreclrTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.LanguageServer.UnitTests\FSharp.Compiler.LanguageServer.UnitTests.fsproj" -targetFramework $coreclrTargetFramework + TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.Scripting.UnitTests\FSharp.Compiler.Scripting.UnitTests.fsproj" -targetFramework $coreclrTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Build.UnitTests\FSharp.Build.UnitTests.fsproj" -targetFramework $coreclrTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Core.UnitTests\FSharp.Core.UnitTests.fsproj" -targetFramework $coreclrTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\fsharp\FSharpSuite.Tests.fsproj" -targetFramework $coreclrTargetFramework diff --git a/eng/build.sh b/eng/build.sh index e806856c556..164dd747f36 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -272,6 +272,7 @@ if [[ "$test_core_clr" == true ]]; then coreclrtestframework=netcoreapp3.0 TestUsingNUnit --testproject "$repo_root/tests/FSharp.Compiler.UnitTests/FSharp.Compiler.UnitTests.fsproj" --targetframework $coreclrtestframework TestUsingNUnit --testproject "$repo_root/tests/FSharp.Compiler.LanguageServer.UnitTests/FSharp.Compiler.LanguageServer.UnitTests.fsproj" --targetframework $coreclrtestframework + TestUsingNUnit --testproject "$repo_root/tests/FSharp.Compiler.Scripting.UnitTests/FSharp.Compiler.Scripting.UnitTests.fsproj" --targetframework $coreclrtestframework TestUsingNUnit --testproject "$repo_root/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj" --targetframework $coreclrtestframework TestUsingNUnit --testproject "$repo_root/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj" --targetframework $coreclrtestframework fi diff --git a/eng/publish-myget.ps1 b/eng/publish-myget.ps1 new file mode 100644 index 00000000000..23f3aa81c9a --- /dev/null +++ b/eng/publish-myget.ps1 @@ -0,0 +1,17 @@ +[CmdletBinding(PositionalBinding=$false)] +param ( + [string]$artifactsDir, + [string]$apiKey, + [string]$configuration +) + +Set-StrictMode -version 2.0 +$ErrorActionPreference = "Stop" + +$shippingDir = "$artifactsDir\packages\$configuration\Shipping" +$packages = @( + "$shippingDir\FSharp.Compiler.Scripting.*.nupkg", + "$shippingDir\FSharp.Core.*.nupkg" +) + +. (Join-Path $PSScriptRoot "publish-myget.ps1") -apiKey "$apiKey" -feedUrl "https://dotnet.myget.org/F/fsharp/api/v2/package" $packages diff --git a/eng/publish.ps1 b/eng/publish.ps1 new file mode 100644 index 00000000000..214d69b3c9f --- /dev/null +++ b/eng/publish.ps1 @@ -0,0 +1,21 @@ +[CmdletBinding(PositionalBinding=$false)] +param ( + [string]$apiKey, + [string]$feedUrl, + + [parameter(ValueFromRemainingArguments=$true)][string[]]$packages +) + +Set-StrictMode -version 2.0 +$ErrorActionPreference = "Stop" + +$failedPackages = 0 +foreach ($package in $packages) { + $response = Invoke-WebRequest -Uri $feedUrl -Headers @{"X-NuGet-ApiKey"=$apiKey} -ContentType "multipart/form-data" -InFile "$package" -Method Post -UseBasicParsing + if ($response.StatusCode -ne 201) { + Write-Error "Failed to upload package. Upload failed with status code: $response.StatusCode." + $failedPackages++ + } +} + +exit $failedPackages diff --git a/src/fsharp/FSharp.Compiler.Scripting/Directory.Build.props b/src/fsharp/FSharp.Compiler.Scripting/Directory.Build.props new file mode 100644 index 00000000000..7cd41381b5d --- /dev/null +++ b/src/fsharp/FSharp.Compiler.Scripting/Directory.Build.props @@ -0,0 +1,9 @@ + + + + true + + + + + diff --git a/src/fsharp/FSharp.Compiler.Scripting/FSharp.Compiler.Scripting.fsproj b/src/fsharp/FSharp.Compiler.Scripting/FSharp.Compiler.Scripting.fsproj new file mode 100644 index 00000000000..23c51fdf157 --- /dev/null +++ b/src/fsharp/FSharp.Compiler.Scripting/FSharp.Compiler.Scripting.fsproj @@ -0,0 +1,27 @@ + + + + netstandard2.0 + true + Provides embedding F# language scripting. + FSharp.Compiler.Scripting.nuspec + true + + + + + + + + + + + + + + + + + + + diff --git a/src/fsharp/FSharp.Compiler.Scripting/FSharp.Compiler.Scripting.nuspec b/src/fsharp/FSharp.Compiler.Scripting/FSharp.Compiler.Scripting.nuspec new file mode 100644 index 00000000000..c5c1756f6e1 --- /dev/null +++ b/src/fsharp/FSharp.Compiler.Scripting/FSharp.Compiler.Scripting.nuspec @@ -0,0 +1,20 @@ + + + + $CommonMetadataElements$ + en-US + + + + + + + + + + + + + + + diff --git a/src/fsharp/FSharp.Compiler.Scripting/FSharpScript.fs b/src/fsharp/FSharp.Compiler.Scripting/FSharpScript.fs new file mode 100644 index 00000000000..114e1e6cd33 --- /dev/null +++ b/src/fsharp/FSharp.Compiler.Scripting/FSharpScript.fs @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.Scripting + +open System +open FSharp.Compiler.Interactive.Shell + +type FSharpScript(?captureInput: bool, ?captureOutput: bool) as this = + let outputProduced = Event() + let errorProduced = Event() + + // handle stdin/stdout + let stdin = new CapturedTextReader() + let stdout = new EventedTextWriter() + let stderr = new EventedTextWriter() + do stdout.LineWritten.Add outputProduced.Trigger + do stderr.LineWritten.Add errorProduced.Trigger + let captureInput = defaultArg captureInput false + let captureOutput = defaultArg captureOutput false + let savedInput = Console.In + let savedOutput = Console.Out + let savedError = Console.Error + do (fun () -> + if captureInput then + Console.SetIn(stdin) + if captureOutput then + Console.SetOut(stdout) + Console.SetError(stderr) + ())() + + let config = FsiEvaluationSession.GetDefaultConfiguration() + let argv = [| this.GetType().Assembly.Location; "--noninteractive"; "--targetprofile:netcore"; "--quiet" |] + let fsi = FsiEvaluationSession.Create (config, argv, stdin, stdout, stderr, collectible=true) + + member __.ProvideInput = stdin.ProvideInput + + member __.OutputProduced = outputProduced.Publish + + member __.ErrorProduced = errorProduced.Publish + + member __.Eval(code: string) = + let ch, errors = fsi.EvalExpressionNonThrowing code + match ch with + | Choice1Of2(Some(value)) -> Ok(value), errors + | Choice1Of2 None -> Error(Exception("No value produced")), errors + | Choice2Of2 ex -> Error(ex), errors + + interface IDisposable with + member __.Dispose() = + if captureInput then + Console.SetIn(savedInput) + if captureOutput then + Console.SetOut(savedOutput) + Console.SetError(savedError) + stdin.Dispose() + stdout.Dispose() + stderr.Dispose() diff --git a/src/fsharp/FSharp.Compiler.Scripting/TextHelpers.fs b/src/fsharp/FSharp.Compiler.Scripting/TextHelpers.fs new file mode 100644 index 00000000000..87e846b4009 --- /dev/null +++ b/src/fsharp/FSharp.Compiler.Scripting/TextHelpers.fs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.Scripting + +open System.Collections.Generic +open System.IO +open System.Text + +type internal CapturedTextReader() = + inherit TextReader() + let queue = Queue() + member __.ProvideInput(text: string) = + for c in text.ToCharArray() do + queue.Enqueue(c) + override __.Peek() = + if queue.Count > 0 then queue.Peek() |> int + else -1 + override __.Read() = + if queue.Count > 0 then queue.Dequeue() |> int + else -1 + +type internal EventedTextWriter() = + inherit TextWriter() + let sb = StringBuilder() + let lineWritten = Event() + member __.LineWritten = lineWritten.Publish + override __.Encoding = Encoding.UTF8 + override __.Write(c: char) = + if c = '\n' then + let line = + let v = sb.ToString() + if v.EndsWith("\r") then v.Substring(0, v.Length - 1) + else v + sb.Clear() |> ignore + lineWritten.Trigger(line) + else sb.Append(c) |> ignore diff --git a/tests/FSharp.Compiler.Scripting.UnitTests/Directory.Build.props b/tests/FSharp.Compiler.Scripting.UnitTests/Directory.Build.props new file mode 100644 index 00000000000..7cd41381b5d --- /dev/null +++ b/tests/FSharp.Compiler.Scripting.UnitTests/Directory.Build.props @@ -0,0 +1,9 @@ + + + + true + + + + + diff --git a/tests/FSharp.Compiler.Scripting.UnitTests/FSharp.Compiler.Scripting.UnitTests.fsproj b/tests/FSharp.Compiler.Scripting.UnitTests/FSharp.Compiler.Scripting.UnitTests.fsproj new file mode 100644 index 00000000000..56f4523740d --- /dev/null +++ b/tests/FSharp.Compiler.Scripting.UnitTests/FSharp.Compiler.Scripting.UnitTests.fsproj @@ -0,0 +1,22 @@ + + + + + net472;netcoreapp3.0 + netcoreapp3.0 + Library + true + nunit + true + + + + + + + + + + + + diff --git a/tests/FSharp.Compiler.Scripting.UnitTests/FSharpScriptTests.fs b/tests/FSharp.Compiler.Scripting.UnitTests/FSharpScriptTests.fs new file mode 100644 index 00000000000..38d5c3d431a --- /dev/null +++ b/tests/FSharp.Compiler.Scripting.UnitTests/FSharpScriptTests.fs @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.Scripting.UnitTests + +open System +open System.Threading +open FSharp.Compiler.Interactive.Shell +open FSharp.Compiler.Scripting +open FSharp.Compiler.SourceCodeServices +open NUnit.Framework + +[] +type InteractiveTests() = + + let getValue ((value: Result), (errors: FSharpErrorInfo[])) = + if errors.Length > 0 then + failwith <| sprintf "Evaluation returned %d errors:\r\n\t%s" errors.Length (String.Join("\r\n\t", errors)) + match value with + | Ok(value) -> value + | Error ex -> raise ex + + [] + member __.``Eval object value``() = + use fsi = new FSharpScript() + let value = fsi.Eval("1+1") |> getValue + Assert.AreEqual(typeof, value.ReflectionType) + Assert.AreEqual(2, value.ReflectionValue :?> int) + + [] + member __.``Capture console input``() = + use script = new FSharpScript(captureInput=true) + script.ProvideInput "stdin:1234\r\n" + let value = script.Eval("System.Console.ReadLine()") |> getValue + Assert.AreEqual(typeof, value.ReflectionType) + Assert.AreEqual("stdin:1234", value.ReflectionValue) + + [] + member __.``Capture console output/error``() = + use script = new FSharpScript(captureOutput=true) + use sawOutputSentinel = new ManualResetEvent(false) + use sawErrorSentinel = new ManualResetEvent(false) + script.OutputProduced.Add (fun line -> if line = "stdout:1234" then sawOutputSentinel.Set() |> ignore) + script.ErrorProduced.Add (fun line -> if line = "stderr:5678" then sawErrorSentinel.Set() |> ignore) + let value = script.Eval("printfn \"stdout:1234\"; eprintfn \"stderr:5678\"") |> getValue + Assert.AreEqual(typeof, value.ReflectionType) + Assert.Null(value.ReflectionValue) + Assert.True(sawOutputSentinel.WaitOne(TimeSpan.FromSeconds(5.0)), "Expected to see output sentinel value written") + Assert.True(sawErrorSentinel.WaitOne(TimeSpan.FromSeconds(5.0)), "Expected to see error sentinel value written")