diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs
index 525faf3be3d..5f6588bd770 100644
--- a/src/Compiler/Service/service.fs
+++ b/src/Compiler/Service/service.fs
@@ -72,10 +72,10 @@ module CompileHelpers =
try
f exiter
- 0
+ None
with e ->
stopProcessingRecovery e range0
- 1
+ Some e
/// Compile using the given flags. Source files names are resolved via the FileSystem API. The output file must be given by a -o flag.
let compileFromArgs (ctok, argv: string[], legacyReferenceResolver, tcImportsCapture, dynamicAssemblyCreator) =
diff --git a/src/Compiler/Service/service.fsi b/src/Compiler/Service/service.fsi
index 0e48a0d6360..3e4fde2229c 100644
--- a/src/Compiler/Service/service.fsi
+++ b/src/Compiler/Service/service.fsi
@@ -400,11 +400,12 @@ type public FSharpChecker =
/// Compile using the given flags. Source files names are resolved via the FileSystem API.
/// The output file must be given by a -o flag.
/// The first argument is ignored and can just be "fsc.exe".
+ /// The method returns the collected diagnostics, and (possibly) a terminating exception.
///
///
/// The command line arguments for the project build.
/// An optional string used for tracing compiler operations associated with this request.
- member Compile: argv: string[] * ?userOpName: string -> Async
+ member Compile: argv: string[] * ?userOpName: string -> Async
///
/// Try to get type check results for a file. This looks up the results of recent type checks of the
diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerDirectives/Ifdef.fs b/tests/FSharp.Compiler.ComponentTests/CompilerDirectives/Ifdef.fs
new file mode 100644
index 00000000000..99d019504d6
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/CompilerDirectives/Ifdef.fs
@@ -0,0 +1,57 @@
+namespace CompilerDirectives
+
+open Xunit
+open FSharp.Test.Compiler
+
+module Ifdef =
+
+ let ifdefSource = """
+[]
+let main _ =
+ #if MYDEFINE1
+ 1
+ #else
+ 2
+ #endif
+"""
+
+ []
+ []
+ []
+ let ifdefTest (mydefine, expectedExitCode) =
+
+ FSharp ifdefSource
+ |> withDefines [mydefine]
+ |> compileExeAndRun
+ |> withExitCode expectedExitCode
+
+
+ let sourceExtraEndif = """
+#if MYDEFINE1
+printf "1"
+#endif
+(**)#endif(**)
+0
+"""
+
+ []
+ let extraEndif () =
+
+ FSharp sourceExtraEndif
+ |> withDefines ["MYDEFINE1"]
+ |> asExe
+ |> compile
+ |> withDiagnosticMessage "#endif has no matching #if in implementation file"
+
+ let sourceUnknownHash = """
+module A
+#ifxx
+#abc
+"""
+
+ []
+ let unknownHashDirectiveIsIgnored () =
+
+ FSharp sourceUnknownHash
+ |> compile
+ |> shouldSucceed
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs b/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs
index b3c33031acb..c560008da0c 100644
--- a/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs
+++ b/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs
@@ -45,7 +45,6 @@ else ()
|> compile
|> run
|> shouldSucceed
- |> withExitCode 0
[]
let ``Respect nowarn 957 for extension method`` () =
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TryCatch/TryCatch.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TryCatch/TryCatch.fs
index 9a43d34d429..1e5187167a7 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TryCatch/TryCatch.fs
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TryCatch/TryCatch.fs
@@ -56,9 +56,9 @@ let ``Stackoverflow reproduction`` compilation =
| CompilationResult.Success ({OutputPath = Some dllFile} as s) ->
let fsharpCoreFile = typeof>.Assembly.Location
File.Copy(fsharpCoreFile, Path.Combine(Path.GetDirectoryName(dllFile), Path.GetFileName(fsharpCoreFile)), true)
- let exitCode, _stdout, _stderr = CompilerAssert.ExecuteAndReturnResult (dllFile, isFsx=false, deps = s.Dependencies, newProcess=true)
+ let _exitCode, _stdout, stderr, _exn = CompilerAssert.ExecuteAndReturnResult (dllFile, isFsx=false, deps = s.Dependencies, newProcess=true)
- Assert.NotEqual(0,exitCode)
+ Assert.True(stderr.Contains "stack overflow" || stderr.Contains "StackOverflow")
| _ -> failwith (sprintf "%A" compilationResult)
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
index 4b50b28aa12..4ddec1e3405 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
+++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
@@ -33,6 +33,7 @@
+
diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/CompilationFromCmdlineArgsTests.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/CompilationFromCmdlineArgsTests.fs
index 9cfbbb9df80..294db344223 100644
--- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/CompilationFromCmdlineArgsTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/CompilationFromCmdlineArgsTests.fs
@@ -38,12 +38,12 @@ module CompilationFromCmdlineArgsTests =
yield! methodOptions method
|]
- let diagnostics, exitCode = checker.Compile(args) |> Async.RunSynchronously
+ let diagnostics, exn = checker.Compile(args) |> Async.RunSynchronously
for diag in diagnostics do
printfn "%A" diag
- Assert.Equal(exitCode, 0)
+ Assert.Equal(exn, None)
finally
Environment.CurrentDirectory <- oldWorkDir
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 2bbc7c5bf52..15e1dd848e6 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
@@ -2166,7 +2166,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults]] GetBackgroundCheckResultsForFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]]] GetProjectOptionsFromScript(System.String, FSharp.Compiler.Text.ISourceText, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.DateTime], Microsoft.FSharp.Core.FSharpOption`1[System.String[]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Int64], Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]]] GetProjectSnapshotFromScript(System.String, FSharp.Compiler.Text.ISourceTextNew, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.DocumentSource], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.DateTime], Microsoft.FSharp.Core.FSharpOption`1[System.String[]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Int64], Microsoft.FSharp.Core.FSharpOption`1[System.String])
-FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.Diagnostics.FSharpDiagnostic[],System.Int32]] Compile(System.String[], Microsoft.FSharp.Core.FSharpOption`1[System.String])
+FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.Diagnostics.FSharpDiagnostic[],Microsoft.FSharp.Core.FSharpOption`1[System.Exception]]] Compile(System.String[], Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.Text.Range,FSharp.Compiler.Text.Range][]] MatchBraces(System.String, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpParsingOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.Text.Range,FSharp.Compiler.Text.Range][]] MatchBraces(System.String, System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions],FSharp.Compiler.CodeAnalysis.FSharpProjectOptions] ProjectChecked
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 2bbc7c5bf52..15e1dd848e6 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
@@ -2166,7 +2166,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults,FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults]] GetBackgroundCheckResultsForFileInProject(System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]]] GetProjectOptionsFromScript(System.String, FSharp.Compiler.Text.ISourceText, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.DateTime], Microsoft.FSharp.Core.FSharpOption`1[System.String[]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Int64], Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.CodeAnalysis.ProjectSnapshot+FSharpProjectSnapshot,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Diagnostics.FSharpDiagnostic]]] GetProjectSnapshotFromScript(System.String, FSharp.Compiler.Text.ISourceTextNew, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.DocumentSource], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.DateTime], Microsoft.FSharp.Core.FSharpOption`1[System.String[]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Int64], Microsoft.FSharp.Core.FSharpOption`1[System.String])
-FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.Diagnostics.FSharpDiagnostic[],System.Int32]] Compile(System.String[], Microsoft.FSharp.Core.FSharpOption`1[System.String])
+FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.Diagnostics.FSharpDiagnostic[],Microsoft.FSharp.Core.FSharpOption`1[System.Exception]]] Compile(System.String[], Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.Text.Range,FSharp.Compiler.Text.Range][]] MatchBraces(System.String, FSharp.Compiler.Text.ISourceText, FSharp.Compiler.CodeAnalysis.FSharpParsingOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.FSharpAsync`1[System.Tuple`2[FSharp.Compiler.Text.Range,FSharp.Compiler.Text.Range][]] MatchBraces(System.String, System.String, FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String])
FSharp.Compiler.CodeAnalysis.FSharpChecker: Microsoft.FSharp.Control.IEvent`2[Microsoft.FSharp.Control.FSharpHandler`1[FSharp.Compiler.CodeAnalysis.FSharpProjectOptions],FSharp.Compiler.CodeAnalysis.FSharpProjectOptions] ProjectChecked
diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs
index f535bc21c5a..5e5629b089f 100644
--- a/tests/FSharp.Test.Utilities/Compiler.fs
+++ b/tests/FSharp.Test.Utilities/Compiler.fs
@@ -170,10 +170,13 @@ module rec Compiler =
Message: string
SubCategory: string }
+ // This type is used either for the output of the compiler (typically in CompilationResult coming from 'compile')
+ // or for the output of the code generated by the compiler (in CompilationResult coming from 'run')
type ExecutionOutput =
- { ExitCode: int
+ { ExitCode: int option
StdOut: string
- StdErr: string }
+ StdErr: string
+ Exn: exn option }
type RunOutput =
| EvalOutput of Result
@@ -699,7 +702,7 @@ module rec Compiler =
let private compileFSharpCompilation compilation ignoreWarnings (cUnit: CompilationUnit) : CompilationResult =
use redirect = new RedirectConsole()
- let ((err: FSharpDiagnostic[], rc: int, outputFilePath: string), deps) =
+ let ((err: FSharpDiagnostic[], exn, outputFilePath: string), deps) =
CompilerAssert.CompileRaw(compilation, ignoreWarnings)
// Create and stash the console output
@@ -711,7 +714,7 @@ module rec Compiler =
Adjust = 0
PerFileErrors = diagnostics
Diagnostics = diagnostics |> List.map snd
- Output = Some (RunOutput.ExecutionOutput { ExitCode = rc; StdOut = redirect.Output(); StdErr = redirect.ErrorOutput() })
+ Output = Some (RunOutput.ExecutionOutput { ExitCode = None; StdOut = redirect.Output(); StdErr = redirect.ErrorOutput(); Exn = exn })
Compilation = cUnit
}
@@ -978,14 +981,13 @@ module rec Compiler =
| SourceCodeFileKind.Fsx _ -> true
| _ -> false
| _ -> false
- let exitCode, output, errors = CompilerAssert.ExecuteAndReturnResult (p, isFsx, s.Dependencies, false)
+ let exitCode, output, errors, exn = CompilerAssert.ExecuteAndReturnResult (p, isFsx, s.Dependencies, false)
printfn "---------output-------\n%s\n-------" output
printfn "---------errors-------\n%s\n-------" errors
- let executionResult = { s with Output = Some (ExecutionOutput { ExitCode = exitCode; StdOut = output; StdErr = errors }) }
- if exitCode = 0 then
- CompilationResult.Success executionResult
- else
- CompilationResult.Failure executionResult
+ let executionResult = { s with Output = Some (ExecutionOutput { ExitCode = exitCode; StdOut = output; StdErr = errors; Exn = exn }) }
+ match exn with
+ | None -> CompilationResult.Success executionResult
+ | Some _ -> CompilationResult.Failure executionResult
let compileAndRun = compile >> run
@@ -1080,27 +1082,25 @@ module rec Compiler =
opts.ToArray()
let errors, stdOut = CompilerAssert.RunScriptWithOptionsAndReturnResult options source
- let executionOutputwithStdOut: RunOutput option =
- ExecutionOutput { StdOut = stdOut; ExitCode = 0; StdErr = "" }
- |> Some
- let result =
+ let mkResult output =
{ OutputPath = None
Dependencies = []
Adjust = 0
Diagnostics = []
PerFileErrors= []
- Output = executionOutputwithStdOut
+ Output = Some output
Compilation = cUnit }
-
- if errors.Count > 0 then
- let output = ExecutionOutput {
- ExitCode = -1
- StdOut = String.Empty
- StdErr = ((errors |> String.concat "\n").Replace("\r\n","\n")) }
- CompilationResult.Failure { result with Output = Some output }
+
+ if errors.Count = 0 then
+ let output =
+ ExecutionOutput { ExitCode = None; StdOut = stdOut; StdErr = ""; Exn = None }
+ CompilationResult.Success (mkResult output)
else
- CompilationResult.Success result
-
+ let err = (errors |> String.concat "\n").Replace("\r\n","\n")
+ let output =
+ ExecutionOutput {ExitCode = None; StdOut = String.Empty; StdErr = err; Exn = None }
+ CompilationResult.Failure (mkResult output)
+
finally
disposals
|> Seq.iter (fun x -> x.Dispose())
@@ -1190,7 +1190,7 @@ Actual:
| Some p ->
match ILChecker.verifyILAndReturnActual [] p expected with
| true, _, _ -> result
- | false, errorMsg, _actualIL -> CompilationResult.Failure( {s with Output = Some (ExecutionOutput { StdOut = errorMsg; ExitCode = 0; StdErr = "" })} )
+ | false, errorMsg, _actualIL -> CompilationResult.Failure( {s with Output = Some (ExecutionOutput {ExitCode = None; StdOut = errorMsg; StdErr = ""; Exn = None })} )
| CompilationResult.Failure f -> failwith $"Result should be \"Success\" in order to get IL. Failure: {Environment.NewLine}{f}"
@@ -1706,7 +1706,7 @@ Actual:
| None -> failwith "Execution output is missing, cannot check exit code."
| Some o ->
match o with
- | ExecutionOutput e -> Assert.Equal(expectedExitCode, e.ExitCode)
+ | ExecutionOutput {ExitCode = Some exitCode} -> Assert.Equal(expectedExitCode, exitCode)
| _ -> failwith "Cannot check exit code on this run result."
result
diff --git a/tests/FSharp.Test.Utilities/CompilerAssert.fs b/tests/FSharp.Test.Utilities/CompilerAssert.fs
index fc2875d8955..37a8e25e164 100644
--- a/tests/FSharp.Test.Utilities/CompilerAssert.fs
+++ b/tests/FSharp.Test.Utilities/CompilerAssert.fs
@@ -322,7 +322,7 @@ module rec CompilerAssertHelpers =
else
entryPoint
let args = mkDefaultArgs entryPoint
- captureConsoleOutputs (fun () -> entryPoint.Invoke(Unchecked.defaultof, args) |> ignore)
+ captureConsoleOutputs (fun () -> entryPoint.Invoke(Unchecked.defaultof, args))
#if NETCOREAPP
let executeBuiltApp assembly deps isFsx =
@@ -409,8 +409,8 @@ module rec CompilerAssertHelpers =
// Generate a response file, purely for diagnostic reasons.
File.WriteAllLines(Path.ChangeExtension(outputFilePath, ".rsp"), args)
- let errors, rc = checker.Compile args |> Async.RunImmediate
- errors, rc, outputFilePath
+ let errors, ex = checker.Compile args |> Async.RunImmediate
+ errors, ex, outputFilePath
let compileDisposable (outputDirectory:DirectoryInfo) isExe options targetFramework nameOpt (sources:SourceCodeFileKind list) =
let disposeFile path =
@@ -537,7 +537,7 @@ module rec CompilerAssertHelpers =
let tmp = Path.Combine(outputPath.FullName, Path.ChangeExtension(fileName, ".dll"))
disposals.Add({ new IDisposable with member _.Dispose() = File.Delete tmp })
cmpl.EmitAsFile tmp
- (([||], 0, tmp), []), false)
+ (([||], None, tmp), []), false)
let compilationRefs =
compiledRefs
@@ -559,7 +559,7 @@ module rec CompilerAssertHelpers =
compilationRefs, deps
- let compileCompilationAux outputDirectory (disposals: ResizeArray) ignoreWarnings (cmpl: Compilation) : (FSharpDiagnostic[] * int * string) * string list =
+ let compileCompilationAux outputDirectory (disposals: ResizeArray) ignoreWarnings (cmpl: Compilation) : (FSharpDiagnostic[] * exn option * string) * string list =
let compilationRefs, deps = evaluateReferences outputDirectory disposals ignoreWarnings cmpl
let isExe, sources, options, targetFramework, name =
@@ -604,7 +604,7 @@ module rec CompilerAssertHelpers =
outputDirectory.Create()
compileCompilationAux outputDirectory (ResizeArray()) ignoreWarnings cmpl
- let captureConsoleOutputs (func: unit -> unit) =
+ let captureConsoleOutputs (func: unit -> obj) =
let out = Console.Out
let err = Console.Error
@@ -614,29 +614,30 @@ module rec CompilerAssertHelpers =
use outWriter = new StringWriter (stdout)
use errWriter = new StringWriter (stderr)
- let succeeded, exn =
+ let rc, exn =
try
try
Console.SetOut outWriter
Console.SetError errWriter
- func ()
- true, None
+ let rc = func()
+ match rc with
+ | :? int as rc -> Some rc, None
+ | _ -> None, None
with e ->
let errorMessage = if e.InnerException <> null then e.InnerException.ToString() else e.ToString()
stderr.Append errorMessage |> ignore
- false, Some e
+ None, Some e
finally
Console.SetOut out
Console.SetError err
outWriter.Close()
errWriter.Close()
- succeeded, stdout.ToString(), stderr.ToString(), exn
+ rc, stdout.ToString(), stderr.ToString(), exn
- let executeBuiltAppAndReturnResult (outputFilePath: string) (deps: string list) isFsx : (int * string * string) =
- let succeeded, stdout, stderr, _ = executeBuiltApp outputFilePath deps isFsx
- let exitCode = if succeeded then 0 else -1
- exitCode, stdout, stderr
+ let executeBuiltAppAndReturnResult (outputFilePath: string) (deps: string list) isFsx : (int option * string * string * exn option) =
+ let rc, stdout, stderr, exn = executeBuiltApp outputFilePath deps isFsx
+ rc, stdout, stderr, exn
let executeBuiltAppNewProcessAndReturnResult (outputFilePath: string) : (int * string * string) =
#if !NETCOREAPP
@@ -663,7 +664,7 @@ module rec CompilerAssertHelpers =
member _.Dispose() = try File.Delete runtimeconfigPath with | _ -> () }
#endif
let timeout = 30000
- let exitCode, output, errors = Commands.executeProcess (Some fileName) arguments (Path.GetDirectoryName(outputFilePath)) timeout
+ let exitCode, output, errors = Commands.executeProcess fileName arguments (Path.GetDirectoryName(outputFilePath)) timeout
(exitCode, output |> String.concat "\n", errors |> String.concat "\n")
open CompilerAssertHelpers
@@ -677,7 +678,7 @@ type CompilerAssert private () =
if errors.Length > 0 then
Assert.Fail (sprintf "Compile had warnings and/or errors: %A" errors)
- executeBuiltApp outputExe [] false |> ignore
+ executeBuiltApp outputExe [] false |> ignore
)
static let compileLibraryAndVerifyILWithOptions options (source: SourceCodeFileKind) (f: ILVerifier -> unit) =
@@ -739,11 +740,13 @@ Updated automatically, please check diffs in your pull request, changes must be
returnCompilation cmpl (defaultArg ignoreWarnings false)
static member ExecuteAndReturnResult (outputFilePath: string, isFsx: bool, deps: string list, newProcess: bool) =
- // If we execute in-process (true by default), then the only way of getting STDOUT is to redirect it to SB, and STDERR is from catching an exception.
if not newProcess then
- executeBuiltAppAndReturnResult outputFilePath deps isFsx
+ let entryPointReturnCode, deps, isFsx, exn = executeBuiltAppAndReturnResult outputFilePath deps isFsx
+ entryPointReturnCode, deps, isFsx, exn
else
- executeBuiltAppNewProcessAndReturnResult outputFilePath
+ let processExitCode, deps, isFsx = executeBuiltAppNewProcessAndReturnResult outputFilePath
+ Some processExitCode, deps, isFsx, None
+
static member Execute(cmpl: Compilation, ?ignoreWarnings, ?beforeExecute, ?newProcess, ?onOutput) =
@@ -767,7 +770,7 @@ Updated automatically, please check diffs in your pull request, changes must be
Assert.Fail errors
onOutput output
else
- let _succeeded, _stdout, _stderr, exn = executeBuiltApp outputFilePath deps false
+ let _rc, _stdout, _stderr, exn = executeBuiltApp outputFilePath deps false
exn |> Option.iter raise)
static member ExecutionHasOutput(cmpl: Compilation, expectedOutput: string) =
diff --git a/tests/FSharp.Test.Utilities/ILChecker.fs b/tests/FSharp.Test.Utilities/ILChecker.fs
index 4474ef01c10..de0fbd8050b 100644
--- a/tests/FSharp.Test.Utilities/ILChecker.fs
+++ b/tests/FSharp.Test.Utilities/ILChecker.fs
@@ -16,7 +16,7 @@ module ILChecker =
let private exec exe args =
let arguments = args |> String.concat " "
let timeout = 30000
- let exitCode, _output, errors = Commands.executeProcess (Some exe) arguments "" timeout
+ let exitCode, _output, errors = Commands.executeProcess exe arguments "" timeout
let errors = errors |> String.concat Environment.NewLine
errors, exitCode
diff --git a/tests/FSharp.Test.Utilities/Peverifier.fs b/tests/FSharp.Test.Utilities/Peverifier.fs
index 35db5b208fb..f3ccc7de2b1 100644
--- a/tests/FSharp.Test.Utilities/Peverifier.fs
+++ b/tests/FSharp.Test.Utilities/Peverifier.fs
@@ -25,7 +25,7 @@ module PEVerifier =
let private exec exe args =
let arguments = args |> String.concat " "
let timeout = 30000
- let exitCode, _output, errors = Commands.executeProcess (Some exe) arguments "" timeout
+ let exitCode, _output, errors = Commands.executeProcess exe arguments "" timeout
let errors = errors |> String.concat Environment.NewLine
errors, exitCode
diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
index 78feb049435..a75784240dd 100644
--- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs
+++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs
@@ -1360,9 +1360,8 @@ type ProjectWorkflowBuilder
yield! projectOptions.OtherOptions
yield! projectOptions.SourceFiles
|]
- let! _diagnostics, exitCode = checker.Compile(arguments)
- if exitCode <> 0 then
- exn $"Compilation failed with exit code {exitCode}" |> raise
+ let! _diagnostics, ex = checker.Compile(arguments)
+ if ex.IsSome then raise ex.Value
return ctx
}
diff --git a/tests/FSharp.Test.Utilities/TestFramework.fs b/tests/FSharp.Test.Utilities/TestFramework.fs
index 6e1611beb5c..dfde63f2352 100644
--- a/tests/FSharp.Test.Utilities/TestFramework.fs
+++ b/tests/FSharp.Test.Utilities/TestFramework.fs
@@ -63,69 +63,66 @@ module Commands =
// Execute the process pathToExe passing the arguments: arguments with the working directory: workingDir timeout after timeout milliseconds -1 = wait forever
// returns exit code, stdio and stderr as string arrays
let executeProcess pathToExe arguments workingDir (timeout:int) =
- match pathToExe with
- | Some path ->
- let commandLine = ResizeArray()
- let errorsList = ResizeArray()
- let outputList = ResizeArray()
- let errorslock = obj()
- let outputlock = obj()
- let outputDataReceived (message: string) =
- if not (isNull message) then
- lock outputlock (fun () -> outputList.Add(message))
-
- let errorDataReceived (message: string) =
- if not (isNull message) then
- lock errorslock (fun () -> errorsList.Add(message))
-
- commandLine.Add $"cd {workingDir}"
- commandLine.Add $"{path} {arguments} /bl"
-
- let psi = ProcessStartInfo()
- psi.FileName <- path
- psi.WorkingDirectory <- workingDir
- psi.RedirectStandardOutput <- true
- psi.RedirectStandardError <- true
- psi.Arguments <- arguments
- psi.CreateNoWindow <- true
- // When running tests, we want to roll forward to minor versions (including previews).
- psi.EnvironmentVariables["DOTNET_ROLL_FORWARD"] <- "LatestMajor"
- psi.EnvironmentVariables["DOTNET_ROLL_FORWARD_TO_PRERELEASE"] <- "1"
- psi.EnvironmentVariables.Remove("MSBuildSDKsPath") // Host can sometimes add this, and it can break things
- psi.UseShellExecute <- false
-
- use p = new Process()
- p.StartInfo <- psi
-
- p.OutputDataReceived.Add(fun a -> outputDataReceived a.Data)
- p.ErrorDataReceived.Add(fun a -> errorDataReceived a.Data)
-
- if p.Start() then
- p.BeginOutputReadLine()
- p.BeginErrorReadLine()
- if not(p.WaitForExit(timeout)) then
- // Timed out resolving throw a diagnostic.
- raise (new TimeoutException(sprintf "Timeout executing command '%s' '%s'" (psi.FileName) (psi.Arguments)))
- else
- p.WaitForExit()
- #if DEBUG
- let workingDir' =
- if workingDir = ""
- then
- // Assign working dir to prevent default to C:\Windows\System32
- let executionLocation = Assembly.GetExecutingAssembly().Location
- Path.GetDirectoryName executionLocation
- else
- workingDir
-
- lock gate (fun () ->
- File.WriteAllLines(Path.Combine(workingDir', "commandline.txt"), commandLine)
- File.WriteAllLines(Path.Combine(workingDir', "StandardOutput.txt"), outputList)
- File.WriteAllLines(Path.Combine(workingDir', "StandardError.txt"), errorsList)
- )
- #endif
- p.ExitCode, outputList.ToArray(), errorsList.ToArray()
- | None -> -1, Array.empty, Array.empty
+ let commandLine = ResizeArray()
+ let errorsList = ResizeArray()
+ let outputList = ResizeArray()
+ let errorslock = obj()
+ let outputlock = obj()
+ let outputDataReceived (message: string) =
+ if not (isNull message) then
+ lock outputlock (fun () -> outputList.Add(message))
+
+ let errorDataReceived (message: string) =
+ if not (isNull message) then
+ lock errorslock (fun () -> errorsList.Add(message))
+
+ commandLine.Add $"cd {workingDir}"
+ commandLine.Add $"{pathToExe} {arguments} /bl"
+
+ let psi = ProcessStartInfo()
+ psi.FileName <- pathToExe
+ psi.WorkingDirectory <- workingDir
+ psi.RedirectStandardOutput <- true
+ psi.RedirectStandardError <- true
+ psi.Arguments <- arguments
+ psi.CreateNoWindow <- true
+ // When running tests, we want to roll forward to minor versions (including previews).
+ psi.EnvironmentVariables["DOTNET_ROLL_FORWARD"] <- "LatestMajor"
+ psi.EnvironmentVariables["DOTNET_ROLL_FORWARD_TO_PRERELEASE"] <- "1"
+ psi.EnvironmentVariables.Remove("MSBuildSDKsPath") // Host can sometimes add this, and it can break things
+ psi.UseShellExecute <- false
+
+ use p = new Process()
+ p.StartInfo <- psi
+
+ p.OutputDataReceived.Add(fun a -> outputDataReceived a.Data)
+ p.ErrorDataReceived.Add(fun a -> errorDataReceived a.Data)
+
+ if p.Start() then
+ p.BeginOutputReadLine()
+ p.BeginErrorReadLine()
+ if not(p.WaitForExit(timeout)) then
+ // Timed out resolving throw a diagnostic.
+ raise (new TimeoutException(sprintf "Timeout executing command '%s' '%s'" (psi.FileName) (psi.Arguments)))
+ else
+ p.WaitForExit()
+#if DEBUG
+ let workingDir' =
+ if workingDir = ""
+ then
+ // Assign working dir to prevent default to C:\Windows\System32
+ let executionLocation = Assembly.GetExecutingAssembly().Location
+ Path.GetDirectoryName executionLocation
+ else
+ workingDir
+
+ lock gate (fun () ->
+ File.WriteAllLines(Path.Combine(workingDir', "commandline.txt"), commandLine)
+ File.WriteAllLines(Path.Combine(workingDir', "StandardOutput.txt"), outputList)
+ File.WriteAllLines(Path.Combine(workingDir', "StandardError.txt"), errorsList)
+ )
+#endif
+ p.ExitCode, outputList.ToArray(), errorsList.ToArray()
let getfullpath workDir (path:string) =
let rooted =
diff --git a/tests/FSharp.Test.Utilities/Utilities.fs b/tests/FSharp.Test.Utilities/Utilities.fs
index 6ed885d4e44..1a6d0ff60f8 100644
--- a/tests/FSharp.Test.Utilities/Utilities.fs
+++ b/tests/FSharp.Test.Utilities/Utilities.fs
@@ -245,7 +245,7 @@ let main argv = 0"""
File.WriteAllText(directoryBuildTargetsFileName, directoryBuildTargets)
let timeout = 120000
- let exitCode, dotnetoutput, dotneterrors = Commands.executeProcess (Some config.DotNetExe) "build" projectDirectory timeout
+ let exitCode, dotnetoutput, dotneterrors = Commands.executeProcess config.DotNetExe "build" projectDirectory timeout
if exitCode <> 0 || errors.Length > 0 then
errors <- dotneterrors