<commit_before>﻿module BlackFox.Stidgen.CsharpCodeTesting

open BlackFox.Stidgen.CsharpGeneration
open Microsoft.CodeAnalysis
open Microsoft.CodeAnalysis.CSharp
open System
open System.IO
open System.Reflection

let private metadataRef<'t> = MetadataReference.CreateFromFile(typeof<'t>.Assembly.Location)

let private createCompilation (code:string seq) =
    let syntaxTrees = code |> Seq.map(fun c -> CSharpSyntaxTree.ParseText(c))

    let assemblyName = Path.GetRandomFileName();
    
    let (references : MetadataReference[]) =
        [|
            metadataRef<obj>
            metadataRef<System.Linq.Enumerable>
            metadataRef<System.CodeDom.Compiler.GeneratedCodeAttribute>
            metadataRef<NUnit.Framework.Assert>
            metadataRef<NFluent.Check>
        |]

    let options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
    CSharpCompilation.Create(assemblyName, syntaxTrees, references, options);

let private loadCsharpCode code =
    let compilation = createCompilation code

    use ms = new MemoryStream()
    let result = compilation.Emit(ms);

    if not result.Success then
        let isError (diagnostic:Diagnostic) = diagnostic.IsWarningAsError || diagnostic.Severity = DiagnosticSeverity.Error
        let failures = result.Diagnostics |> Seq.filter isError
        let failures = failures |> Seq.map (fun d -> sprintf "%s: %s" d.Id (d.GetMessage()))
        let failures = System.String.Join(", ", failures)

        failwith ("Compilation failed -> " + failures)
    else
        ms.Seek(0L, SeekOrigin.Begin) |> ignore
        Assembly.Load(ms.ToArray());

let private wrapTestCode code =
    let name = Guid.NewGuid().ToByteArray() |> Seq.map( fun b -> b.ToString("X2"))
    let name = System.String.Join("", name)
    let name = sprintf "CodeGen_UnitTest_%s" name
    let template =sprintf "using System;
using System;
using System.Globalization;
using System.Collections.Generic;<commit_msg>Better exception in tests when compilation fails<commit_after>﻿module BlackFox.Stidgen.CsharpCodeTesting

open BlackFox.Stidgen.CsharpGeneration
open Microsoft.CodeAnalysis
open Microsoft.CodeAnalysis.CSharp
open System
open System.IO
open System.Reflection

exception CompilationFailedException of string

let private metadataRef<'t> = MetadataReference.CreateFromFile(typeof<'t>.Assembly.Location)

let private createCompilation (code:string seq) =
    let syntaxTrees = code |> Seq.map(fun c -> CSharpSyntaxTree.ParseText(c))

    let assemblyName = Path.GetRandomFileName();
    
    let (references : MetadataReference[]) =
        [|
            metadataRef<obj>
            metadataRef<System.Linq.Enumerable>
            metadataRef<System.CodeDom.Compiler.GeneratedCodeAttribute>
            metadataRef<NUnit.Framework.Assert>
            metadataRef<NFluent.Check>
        |]

    let options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
    CSharpCompilation.Create(assemblyName, syntaxTrees, references, options);

let private loadCsharpCode code =
    let compilation = createCompilation code

    use ms = new MemoryStream()
    let result = compilation.Emit(ms);

    if not result.Success then
        let isError (diagnostic:Diagnostic) = diagnostic.IsWarningAsError || diagnostic.Severity = DiagnosticSeverity.Error
        let failures = result.Diagnostics |> Seq.filter isError
        let failures = failures |> Seq.map (fun d -> sprintf "%s: %s" d.Id (d.GetMessage()))
        let failures = System.String.Join(", ", failures)

        raise (CompilationFailedException ("Compilation failed -> " + failures))
    else
        ms.Seek(0L, SeekOrigin.Begin) |> ignore
        Assembly.Load(ms.ToArray());

let private wrapTestCode code =
    let name = Guid.NewGuid().ToByteArray() |> Seq.map( fun b -> b.ToString("X2"))
    let name = System.String.Join("", name)
    let name = sprintf "CodeGen_UnitTest_%s" name
    let template =sprintf "using System;
using System;
using System.Globalization;
using System.Collections.Generic;
{'fraction_non_alphanumeric': 0.09948032665181886, 'fraction_numerical': 0.000989853996535511, 'mean_word_length': 3.694541231126597, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 35, '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': '5005712', 'n_tokens_mistral': 1149, 'n_tokens_neox': 1134, 'n_words': 276}