* impl

* ControlledExecution
This commit is contained in:
Kevin Ransom (msft) 2023-05-04 11:44:33 -07:00 коммит произвёл GitHub
Родитель d1237f8e3f
Коммит 1727f90f59
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 53 добавлений и 13 удалений

Просмотреть файл

@ -1880,6 +1880,8 @@ type Exception with
| :? UnauthorizedAccessException as exn -> Printf.bprintf os "%s" exn.Message
| :? InvalidOperationException as exn when exn.Message.Contains "ControlledExecution.Run" -> Printf.bprintf os "%s" exn.Message
| exn ->
os.AppendString(TargetInvocationExceptionWrapperE().Format exn.Message)
#if DEBUG

Просмотреть файл

@ -16,7 +16,7 @@ open Internal.Utilities.FSharpEnvironment
open Unchecked
type internal ControlledExecution() =
type internal ControlledExecution(isInteractive: bool) =
let mutable cts: CancellationTokenSource voption = ValueNone
let mutable thread: Thread voption = ValueNone
@ -46,8 +46,8 @@ type internal ControlledExecution() =
| _ -> None
member _.Run(action: Action) =
match ceRun with
| Some run ->
match isInteractive, ceRun with
| true, Some run ->
cts <- ValueSome(new CancellationTokenSource())
run.Invoke(null, [| action; cts.Value.Token |]) |> ignore
| _ ->
@ -55,16 +55,14 @@ type internal ControlledExecution() =
action.Invoke()
member _.TryAbort() : unit =
match isRunningOnCoreClr, cts, thread with
| true, ValueSome cts, _ -> cts.Cancel()
| false, _, ValueSome thread ->
thread.Abort()
()
match isInteractive, isRunningOnCoreClr, cts, thread with
| true, true, ValueSome cts, _ -> cts.Cancel()
| true, false, _, ValueSome thread -> thread.Abort()
| _ -> ()
member _.ResetAbort() =
match thread, threadResetAbort with
| thread, Some threadResetAbort -> threadResetAbort.Invoke(thread, [||]) |> ignore
match isInteractive, thread, threadResetAbort with
| true, thread, Some threadResetAbort -> threadResetAbort.Invoke(thread, [||]) |> ignore
| _ -> ()
static member StripTargetInvocationException(exn: Exception) =

Просмотреть файл

@ -4623,7 +4623,7 @@ type FsiEvaluationSession
resolveAssemblyRef
)
let controlledExecution = ControlledExecution()
let controlledExecution = ControlledExecution(fsiOptions.Interact)
let fsiInterruptController =
FsiInterruptController(fsiOptions, controlledExecution, fsiConsoleOutput)

Просмотреть файл

@ -8,9 +8,11 @@
<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>
<UnitTestType>xunit</UnitTestType>
<ExcludeFromSourceBuild>true</ExcludeFromSourceBuild>
<NoWarn>$(NoWarn);44</NoWarn> <!-- Obsolete -->
</PropertyGroup>
<ItemGroup>
<Compile Include="$(FSharpSourcesRoot)\Compiler\Interactive\ControlledExecution.fs" />
<Compile Include="$(FSharpSourcesRoot)\Compiler\Utilities\RidHelpers.fs" />
<Compile Include="DependencyManagerInteractiveTests.fs" />
<Compile Include="DependencyManagerLineParserTests.fs" />
@ -19,7 +21,7 @@
</ItemGroup>
<ItemGroup>
<None Include="housing.csv" CopyToOutputDirectory="PreserveNewest" />
<None Include="housing.csv" CopyToOutputDirectory="PreserveNewest" />
<Content Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

Просмотреть файл

@ -9,6 +9,7 @@ open System.Reflection
open System.Runtime.InteropServices
open System.Threading
open System.Threading.Tasks
open FSharp.Compiler.Interactive
open FSharp.Compiler.Interactive.Shell
open FSharp.Test.ScriptHelpers
open FSharp.Test.Utilities
@ -42,6 +43,44 @@ type InteractiveTests() =
Assert.Equal(typeof<int>, value.ReflectionType)
Assert.Equal(3, value.ReflectionValue :?> int)
[<Fact>]
member _.``ExecuteScript with host providing ControlledExecution should succeed with --noninteractive``() =
let ce = new FSharp.Compiler.Interactive.ControlledExecution(true)
ce.Run(fun () ->
use script = new FSharpScript([|"--noninteractive"|])
let opt =
script.Eval("""
open System
let x = 1 + 2
x
""") |> getValue
let value = opt.Value
Assert.Equal(typeof<int>, value.ReflectionType)
Assert.Equal(3, value.ReflectionValue :?> int)
)
#if NETSTANDARD
[<Fact>]
member _.``ExecuteScript with host providing ControlledExecution should fail without --noninteractive``() =
let ce = new ControlledExecution(true)
ce.Run(fun () ->
use script = new FSharpScript()
let result, errors =
script.Eval("""
open System
let x = 1 + 2
x
""")
match result with
| Ok(_) -> Assert.True(false, "expected a failure")
| Error(ex) ->
Assert.IsAssignableFrom(typeof<FsiCompilationException>, ex)
match ex with
| :? FsiCompilationException as e when Option.isSome(e.ErrorInfos) -> Assert.Equal("The thread is already executing the ControlledExecution.Run method.", e.ErrorInfos.Value[0].Message)
| _ -> Assert.True(false, "threw incorrect exception expects: 'The thread is already executing the ControlledExecution.Run method.'")
)
#endif
[<Fact>]
member _.``Capture console input``() =
use input = new RedirectConsoleInput()

Просмотреть файл

@ -37,7 +37,6 @@ type FSharpScript(?additionalArgs: string[], ?quiet: bool, ?langVersion: LangVer
let baseArgs = [|
typeof<FSharpScript>.Assembly.Location;
"--noninteractive";
"--targetprofile:" + computedProfile
if quiet then "--quiet"
match langVersion with