<commit_before>﻿// Copyright (c) Microsoft Corporation.  All Rights Reserved.  See License.txt in the project root for license information.

namespace FSharp.Test.Utilities

open System
open System.Diagnostics
open System.IO
open System.Text
open System.Diagnostics
open System.Collections.Generic
open System.Reflection
open FSharp.Compiler.Text
open FSharp.Compiler.SourceCodeServices
open FSharp.Compiler.Interactive.Shell
#if FX_NO_APP_DOMAINS
open System.Runtime.Loader
#endif
open NUnit.Framework
open System.Reflection.Emit
open Microsoft.CodeAnalysis
open Microsoft.CodeAnalysis.CSharp
open FSharp.Test.Utilities.Utilities

[<Sealed>]
type ILVerifier (dllFilePath: string) =

    member this.VerifyIL (qualifiedItemName: string, expectedIL: string) =
        ILChecker.checkILItem qualifiedItemName dllFilePath [ expectedIL ]

    member this.VerifyIL (expectedIL: string list) =
        ILChecker.checkIL dllFilePath expectedIL

    member this.VerifyILWithLineNumbers (qualifiedItemName: string, expectedIL: string) =
        ILChecker.checkILItemWithLineNumbers qualifiedItemName dllFilePath [ expectedIL ]

type Worker () =
    inherit MarshalByRefObject()

    member x.ExecuteTestCase assemblyPath (deps: string[]) =
        AppDomain.CurrentDomain.add_AssemblyResolve(ResolveEventHandler(fun _ args ->
            deps
            |> Array.tryFind (fun (x: string) -> Path.GetFileNameWithoutExtension x = args.Name)
            |> Option.bind (fun x -> if File.Exists x then Some x else None)
            |> Option.map Assembly.LoadFile
            |> Option.defaultValue null))
        let asm = Assembly.LoadFrom(assemblyPath)
        let entryPoint = asm.EntryPoint
        (entryPoint.Invoke(Unchecked.defaultof<obj>, [||])) |> ignore

type SourceKind =
    | Fs
    | Fsx

type CompileOutput =
    | Library
    | Exe

type CompilationReference =
    private
    | CompilationReference of Compilation * staticLink: bool
    | TestCompilationReference of TestCompilation

    static member CreateFSharp(cmpl: Compilation, ?staticLink) =
        let staticLink = defaultArg staticLink false
        CompilationReference(cmpl, staticLink)

    static member Create(cmpl: TestCompilation) =
        TestCompilationReference cmpl

and Compilation = private Compilation of source: string * SourceKind * CompileOutput * options: string[] * CompilationReference list * name: string option with

    static member Create(source, sourceKind, output, ?options, ?cmplRefs, ?name) =
        let options = defaultArg options [||]
        let cmplRefs = defaultArg cmplRefs []
        Compilation(source, sourceKind, output, options, cmplRefs, name)

[<Sealed;AbstractClass>]
type CompilerAssert private () =

    static let checker = FSharpChecker.Create(suggestNamesForErrors=true)

    static let config = TestFramework.initializeSuite ()

    static let _ = config |> ignore

// Do a one time dotnet sdk build to compute the proper set of reference assemblies to pass to the compiler
    static let projectFile = """
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>$TARGETFRAMEWORK</TargetFramework>
    <UseFSharpPreview>true</UseFSharpPreview>
    <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>
  </PropertyGroup>

  <ItemGroup><Compile Include="Program.fs" /></ItemGroup>
  <ItemGroup><Reference Include="$FSHARPCORELOCATION" /></ItemGroup>
  <ItemGroup Condition="'$(TARGETFRAMEWORK)'=='net472'">
    <Reference Include="System" />
    <Reference Include="System.Runtime" />
    <Reference Include="System.Core.dll" />
    <Reference Include="System.Xml.Linq.dll" />
    <Reference Include="System.Data.DataSetExtensions.dll" />
    <Reference Include="Microsoft.CSharp.dll" />
    <Reference Include="System.Data.dll" />
    <Reference Include="System.Deployment.dll" />
    <Reference Include="System.Drawing.dll" />
    <Reference Include="System.Net.Http.dll" />
    <Reference Include="System.Windows.Forms.dll" />
    <Reference Include="System.Xml.dll" />
  </ItemGroup>

  <Target Name="WriteFrameworkReferences" AfterTargets="AfterBuild">
    <WriteLinesToFile File="FrameworkReferences.txt" Lines="@(ReferencePath)" Overwrite="true" WriteOnlyWhenDifferent="true" />
  </Target>

</Project>"""

    static let programFs = """
open System

[<EntryPoint>]
let main argv = 0"""

    static let getNetCoreAppReferences =
        let mutable output = ""
        let mutable errors = ""
        let mutable cleanUp = true
        let projectDirectory = Path.Combine(Path.GetTempPath(), "CompilerAssert", Path.GetRandomFileName())
        let pathToFSharpCore = typeof<RequireQualifiedAccessAttribute>.Assembly.Location
        try
            try
                Directory.CreateDirectory(projectDirectory) |> ignore
                let projectFileName = Path.Combine(projectDirectory, "ProjectFile.fsproj")
                let programFsFileName = Path.Combine(projectDirectory, "Program.fs")
                let frameworkReferencesFileName = Path.Combine(projectDirectory, "FrameworkReferences.txt")
#if NETCOREAPP
                File.WriteAllText(projectFileName, projectFile.Replace("$TARGETFRAMEWORK", "netcoreapp3.1").Replace("$FSHARPCORELOCATION", pathToFSharpCore))
#else
                File.WriteAllText(projectFileName, projectFile.Replace("$TARGETFRAMEWORK", "net472").Replace("$FSHARPCORELOCATION", pathToFSharpCore))
#endif
                File.WriteAllText(programFsFileName, programFs)

                let pInfo = ProcessStartInfo ()
                pInfo.FileName <- config.DotNetExe
                pInfo.Arguments <- "build"
                pInfo.WorkingDirectory <- projectDirectory
                pInfo.RedirectStandardOutput <- true
                pInfo.RedirectStandardError <- true
                pInfo.UseShellExecute <- false

                let p = Process.Start(pInfo)
                let timeout = 30000
                let succeeded = p.WaitForExit(timeout)

                output <- p.StandardOutput.ReadToEnd ()
                errors <- p.StandardError.ReadToEnd ()

                if not (String.IsNullOrWhiteSpace errors) then Assert.Fail errors
                if p.ExitCode <> 0 then Assert.Fail(sprintf "Program exited with exit code %d" p.ExitCode)
                if not succeeded then Assert.Fail(sprintf "Program timed out after %d ms" timeout)

                File.ReadLines(frameworkReferencesFileName) |> Seq.toArray
            with | e ->
                cleanUp <- false
                printfn "Project directory: %s" projectDirectory
                printfn "STDOUT: %s" output
                printfn "STDERR: %s" errors
                raise (new Exception (sprintf "An error occurred getting netcoreapp references: %A" e))
        finally
            if cleanUp then
                try Directory.Delete(projectDirectory) with | _ -> ()

#if FX_NO_APP_DOMAINS
    static let executeBuiltApp assembly deps =
        let ctxt = AssemblyLoadContext("ContextName", true)
        try
            let asm = ctxt.LoadFromAssemblyPath(assembly)
            let entryPoint = asm.EntryPoint
            ctxt.add_Resolving(fun ctxt name ->
                deps
                |> List.tryFind (fun (x: string) -> Path.GetFileNameWithoutExtension x = name.Name)
                |> Option.map ctxt.LoadFromAssemblyPath
                |> Option.defaultValue null)
            (entryPoint.Invoke(Unchecked.defaultof<obj>, [||])) |> ignore
        finally<commit_msg>Update bframework refencing (#10502)<commit_after>﻿// Copyright (c) Microsoft Corporation.  All Rights Reserved.  See License.txt in the project root for license information.

namespace FSharp.Test.Utilities

open System
open System.Diagnostics
open System.IO
open System.Text
open System.Diagnostics
open System.Collections.Generic
open System.Reflection
open FSharp.Compiler.Text
open FSharp.Compiler.SourceCodeServices
open FSharp.Compiler.Interactive.Shell
#if FX_NO_APP_DOMAINS
open System.Runtime.Loader
#endif
open NUnit.Framework
open System.Reflection.Emit
open Microsoft.CodeAnalysis
open Microsoft.CodeAnalysis.CSharp
open FSharp.Test.Utilities.Utilities

[<Sealed>]
type ILVerifier (dllFilePath: string) =

    member this.VerifyIL (qualifiedItemName: string, expectedIL: string) =
        ILChecker.checkILItem qualifiedItemName dllFilePath [ expectedIL ]

    member this.VerifyIL (expectedIL: string list) =
        ILChecker.checkIL dllFilePath expectedIL

    member this.VerifyILWithLineNumbers (qualifiedItemName: string, expectedIL: string) =
        ILChecker.checkILItemWithLineNumbers qualifiedItemName dllFilePath [ expectedIL ]

type Worker () =
    inherit MarshalByRefObject()

    member x.ExecuteTestCase assemblyPath (deps: string[]) =
        AppDomain.CurrentDomain.add_AssemblyResolve(ResolveEventHandler(fun _ args ->
            deps
            |> Array.tryFind (fun (x: string) -> Path.GetFileNameWithoutExtension x = args.Name)
            |> Option.bind (fun x -> if File.Exists x then Some x else None)
            |> Option.map Assembly.LoadFile
            |> Option.defaultValue null))
        let asm = Assembly.LoadFrom(assemblyPath)
        let entryPoint = asm.EntryPoint
        (entryPoint.Invoke(Unchecked.defaultof<obj>, [||])) |> ignore

type SourceKind =
    | Fs
    | Fsx

type CompileOutput =
    | Library
    | Exe

type CompilationReference =
    private
    | CompilationReference of Compilation * staticLink: bool
    | TestCompilationReference of TestCompilation

    static member CreateFSharp(cmpl: Compilation, ?staticLink) =
        let staticLink = defaultArg staticLink false
        CompilationReference(cmpl, staticLink)

    static member Create(cmpl: TestCompilation) =
        TestCompilationReference cmpl

and Compilation = private Compilation of source: string * SourceKind * CompileOutput * options: string[] * CompilationReference list * name: string option with

    static member Create(source, sourceKind, output, ?options, ?cmplRefs, ?name) =
        let options = defaultArg options [||]
        let cmplRefs = defaultArg cmplRefs []
        Compilation(source, sourceKind, output, options, cmplRefs, name)

[<Sealed;AbstractClass>]
type CompilerAssert private () =

    static let checker = FSharpChecker.Create(suggestNamesForErrors=true)

    static let config = TestFramework.initializeSuite ()

    static let _ = config |> ignore

// Do a one time dotnet sdk build to compute the proper set of reference assemblies to pass to the compiler
    static let projectFile = """
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>$TARGETFRAMEWORK</TargetFramework>
    <UseFSharpPreview>true</UseFSharpPreview>
    <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>
  </PropertyGroup>

  <ItemGroup><Compile Include="Program.fs" /></ItemGroup>
  <ItemGroup><Reference Include="$FSHARPCORELOCATION" /></ItemGroup>
  <ItemGroup Condition="'$(TARGETFRAMEWORK)'=='net472'">
    <Reference Include="System" />
    <Reference Include="System.Runtime" />
    <Reference Include="System.Core.dll" />
    <Reference Include="System.Xml.Linq.dll" />
    <Reference Include="System.Data.DataSetExtensions.dll" />
    <Reference Include="Microsoft.CSharp.dll" />
    <Reference Include="System.Data.dll" />
    <Reference Include="System.Deployment.dll" />
    <Reference Include="System.Drawing.dll" />
    <Reference Include="System.Net.Http.dll" />
    <Reference Include="System.Windows.Forms.dll" />
    <Reference Include="System.Xml.dll" />
  </ItemGroup>

  <Target Name="WriteFrameworkReferences" AfterTargets="AfterBuild">
    <WriteLinesToFile File="FrameworkReferences.txt" Lines="@(ReferencePath)" Overwrite="true" WriteOnlyWhenDifferent="true" />
  </Target>

</Project>"""

    static let directoryBuildProps = """
<Project>
  <PropertyGroup>
    <DisableCompilerRedirection>true</DisableCompilerRedirection>
  </PropertyGroup>

  <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
</Project>
"""

    static let programFs = """
open System

[<EntryPoint>]
let main argv = 0"""

    static let getNetCoreAppReferences =
        let mutable output = ""
        let mutable errors = ""
        let mutable cleanUp = true
        let pathToTemp = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "../../../../Temp"))
        let projectDirectory = Path.Combine(pathToTemp, "CompilerAssert", Path.GetRandomFileName())
        let pathToFSharpCore = typeof<RequireQualifiedAccessAttribute>.Assembly.Location
        try
            try
                Directory.CreateDirectory(projectDirectory) |> ignore
                let projectFileName = Path.Combine(projectDirectory, "ProjectFile.fsproj")
                let programFsFileName = Path.Combine(projectDirectory, "Program.fs")
                let directoryBuildPropsFileName = Path.Combine(projectDirectory, "Directory.Build.props")
                let frameworkReferencesFileName = Path.Combine(projectDirectory, "FrameworkReferences.txt")
#if NETCOREAPP
                File.WriteAllText(projectFileName, projectFile.Replace("$TARGETFRAMEWORK", "netcoreapp3.1").Replace("$FSHARPCORELOCATION", pathToFSharpCore))
#else
                File.WriteAllText(projectFileName, projectFile.Replace("$TARGETFRAMEWORK", "net472").Replace("$FSHARPCORELOCATION", pathToFSharpCore))
#endif
                File.WriteAllText(programFsFileName, programFs)
                File.WriteAllText(directoryBuildPropsFileName, directoryBuildProps)

                let pInfo = ProcessStartInfo ()
                pInfo.FileName <- config.DotNetExe
                pInfo.Arguments <- "build"
                pInfo.WorkingDirectory <- projectDirectory
                pInfo.RedirectStandardOutput <- true
                pInfo.RedirectStandardError <- true
                pInfo.UseShellExecute <- false

                let p = Process.Start(pInfo)
                let timeout = 30000
                let succeeded = p.WaitForExit(timeout)

                output <- p.StandardOutput.ReadToEnd ()
                errors <- p.StandardError.ReadToEnd ()

                if not (String.IsNullOrWhiteSpace errors) then Assert.Fail errors
                if p.ExitCode <> 0 then Assert.Fail(sprintf "Program exited with exit code %d" p.ExitCode)
                if not succeeded then Assert.Fail(sprintf "Program timed out after %d ms" timeout)

                File.ReadLines(frameworkReferencesFileName) |> Seq.toArray
            with | e ->
                cleanUp <- false
                printfn "Project directory: %s" projectDirectory
                printfn "STDOUT: %s" output
                File.WriteAllText(Path.Combine(projectDirectory, "project.stdout"), output)
                printfn "STDERR: %s" errors
                File.WriteAllText(Path.Combine(projectDirectory, "project.stderror"), errors)
                raise (new Exception (sprintf "An error occurred getting netcoreapp references: %A" e))
        finally
            if cleanUp then
                try Directory.Delete(projectDirectory) with | _ -> ()

#if FX_NO_APP_DOMAINS
    static let executeBuiltApp assembly deps =
        let ctxt = AssemblyLoadContext("ContextName", true)
        try
            let asm = ctxt.LoadFromAssemblyPath(assembly)
            let entryPoint = asm.EntryPoint
            ctxt.add_Resolving(fun ctxt name ->
                deps
                |> List.tryFind (fun (x: string) -> Path.GetFileNameWithoutExtension x = name.Name)
                |> Option.map ctxt.LoadFromAssemblyPath
                |> Option.defaultValue null)
            (entryPoint.Invoke(Unchecked.defaultof<obj>, [||])) |> ignore
        finally
{'fraction_non_alphanumeric': 0.09712411705348133, 'fraction_numerical': 0.0022073662966700302, 'mean_word_length': 3.0974160206718344, 'pattern_counts': {'":': 0, '<': 112, '<?xml version=': 0, '>': 132, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6430595', 'n_tokens_mistral': 4433, 'n_tokens_neox': 4138, 'n_words': 1007}