diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index cb175b2f067..b446e3a9986 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -240,6 +240,8 @@ + + @@ -269,7 +271,7 @@ - + diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions.fs new file mode 100644 index 00000000000..2b3d490293e --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions.fs @@ -0,0 +1,83 @@ +module TypeChecks.typeextensions +open System +open System.IO +open Xunit +open FSharp.Test +open FSharp.Test.Compiler +open FSharp.Compiler.IO +open NUnit.Framework +let private verifyFSXBaseline (cu) : unit = + match cu with + | FS fs -> + match fs.Baseline with + | None -> failwith "Baseline was not provided." + | Some bsl -> + let errorsExpectedBaseLine = + match bsl.FSBaseline.Content with + | Some b -> b.Replace("\r\n","\n") + | None -> String.Empty + let errorsActual = + match fs.Source with + | SourceCodeFileKind.Fsx _-> + //let fsxScriptFile = FileInfo fs.Source.GetSourceFileName + //let dir = fsxScriptFile.Directory + //RunRealScriptWithOptionsAndReturnResult + //let cfg = testConfig fsxScriptFile.Directory.FullName + let version = ScriptHelpers.LangVersion.Preview + let _r = Miscellaneous.FsharpSuiteMigrated.ScriptRunner.runScriptFile version cu + //let result = TestFramework.fsi cfg "%s" cfg.fsi_flags [] + //let fsxResult = CompilerAssert.RunRealScriptWithOptionsAndReturnResult [||] fsxScriptFile + + //snd fsxResult |> sanitizeFsxOutput + "()" + | _ -> failwith $"not supposed to check %A{fs.Source}" + + if errorsExpectedBaseLine <> errorsActual then + fs.CreateOutputDirectory() + createBaselineErrors bsl.FSBaseline errorsActual + elif FileSystem.FileExistsShim(bsl.FSBaseline.FilePath) then + FileSystem.FileDeleteShim(bsl.FSBaseline.FilePath) + + Assert.AreEqual(errorsExpectedBaseLine, errorsActual, $"\nExpected:\n{errorsExpectedBaseLine}\nActual:\n{errorsActual}") + | _ -> failwith $"not supposed to check %A{cu}" + +[] +let ``issue.16034`` () = + let scriptPath = Path.Combine( + __SOURCE_DIRECTORY__ + , "typeextensions" + , "issue.16034" + , "issue.16034.fsx" + ) + RealFsxFromPath scriptPath + |> withBaseLine + |> verifyILBaseline + |> compileAndRun + |> verifyOutputWithDefaultBaseline + +[] +let ``issue.16034.check1`` () = + + let scriptPath = Path.Combine( + __SOURCE_DIRECTORY__ + , "typeextensions" + , "issue.16034" + , "issue.16034.check1.fsx" + ) + RealFsxFromPath scriptPath + |> withBaseLine + |> verifyFSXBaseline + +[] +let ``issue.16034.check2`` () = + let scriptPath = Path.Combine( + __SOURCE_DIRECTORY__ + , "typeextensions" + , "issue.16034" + , "issue.16034.check2.fsx" + ) + RealFsxFromPath scriptPath + |> withBaseLine + |> verifyFSXBaseline + + \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.check1.fsx b/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.check1.fsx new file mode 100644 index 00000000000..c8c6bd6bc4f --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.check1.fsx @@ -0,0 +1,4 @@ +#load "issue.16034.fsx" +open Issue.``16034`` +open Issue.``16034``.Extensions +t.indexed1(aa1="nok") <- 1 // error FS0073: internal error: The input must be non-negative. (Parameter 'n') (ArgumentException) \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.check1.fsx.actual.fsc.stdout.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.check1.fsx.actual.fsc.stdout.bsl new file mode 100644 index 00000000000..a691cf858db --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.check1.fsx.actual.fsc.stdout.bsl @@ -0,0 +1,25 @@ + + +Copyright (c) Microsoft Corporation. All Rights Reserved. + +For help type #help;; + +> [Loading /tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.fsx + Loading /tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.check2.fsx] +module FSI_0001.Issue.16034 +val mutable i: int +type T = + new: unit -> T + member indexed1: a1: obj -> int with get + member indexed1: a1: obj -> int with set +module Extensions = + val mutable j: int + type T with + member indexed1: aa1: obj -> int with get + type T with + member indexed1: aa1: obj -> int with set +val t: T + +module FSI_0001.Issue.16034.check2 + +error FS0073: internal error: The input must be non-negative. (Parameter 'n') (ArgumentException) \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.check2.fsx b/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.check2.fsx new file mode 100644 index 00000000000..66bdbc2c992 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.check2.fsx @@ -0,0 +1,4 @@ +#load "issue.16034.fsx" +open Issue.``16034`` +open Issue.``16034``.Extensions +t.indexed1(a1="nok") <- 1 // error FS0073: internal error: The input must be non-negative. (Parameter 'n') (ArgumentException) \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.check2.fsx.actual.fsc.stdout.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.check2.fsx.actual.fsc.stdout.bsl new file mode 100644 index 00000000000..a691cf858db --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.check2.fsx.actual.fsc.stdout.bsl @@ -0,0 +1,25 @@ + + +Copyright (c) Microsoft Corporation. All Rights Reserved. + +For help type #help;; + +> [Loading /tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.fsx + Loading /tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.check2.fsx] +module FSI_0001.Issue.16034 +val mutable i: int +type T = + new: unit -> T + member indexed1: a1: obj -> int with get + member indexed1: a1: obj -> int with set +module Extensions = + val mutable j: int + type T with + member indexed1: aa1: obj -> int with get + type T with + member indexed1: aa1: obj -> int with set +val t: T + +module FSI_0001.Issue.16034.check2 + +error FS0073: internal error: The input must be non-negative. (Parameter 'n') (ArgumentException) \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.fsx b/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.fsx new file mode 100644 index 00000000000..cc76d018c9c --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.fsx @@ -0,0 +1,49 @@ +let mutable i = 0 +type T() = + member x.indexed1 + with get (a1: obj) = + i <- i + 1 + printfn $"T().indexed1 %A{a1} !\t%03i{i}" + 1 + and set (a1: obj) (value: int) = + i <- i + 1 + printfn $"T().indexed1 %A{a1} <- %i{value} !\t%03i{i}" + +module Extensions = + let mutable j = 0 + type T with + member x.indexed1 + with get (aa1: obj) = + i <- i + 1 + j <- j + 1 + printfn $"type extensions aa1 %A{aa1} !\t%03i{i}\t%03i{j}" + 1 + and set (aa1: obj) (value: int) = + i <- i + 1 + j <- j + 1 + printfn $"type extension aa1 %A{aa1} <- %i{value}!\t%03i{i}\t%03i{j}" +let t = T() +t.indexed1 ["ok"] <- 1 // calls the intrinsic property +t.indexed1 ("ok") <- 2 // calls the intrinsic property +t.indexed1 "ok" <- 3 // calls the intrinsic property +t.indexed1 "ok" // calls the intrinsic property +t.get_indexed1 "ok" // calls the intrinsic property +t.set_indexed1 (a1="ok",value=1) // calls the intrinsic property + +open Extensions + +t.indexed1 "nok" // calls the intrinsic property? +t.indexed1 (a1="ok") // calls the intrinsic property +t.indexed1 (aa1="ok") // calls the type extension property +t.indexed1 ["nok"] <- 1 // calls the intrinsic property? +t.indexed1 ("nok") <- 2 // calls the intrinsic property? +t.indexed1 "nok" <- 3 // calls the intrinsic property? + +t.get_indexed1 ("nok") // calls the intrinsic property? +t.get_indexed1 ["nok"] // calls the intrinsic property? +t.get_indexed1 "nok" // calls the intrinsic property? + +t.set_indexed1 ("nok_015",1) // calls the intrinsic property? +t.set_indexed1 ("nok_016",value=2) // calls the intrinsic property? +t.set_indexed1 (a1="ok_017",value=1) // calls the intrinsic property +t.set_indexed1 (aa1="ok_018",value=1) // calls the type extension property diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.fsx.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.fsx.il.bsl new file mode 100644 index 00000000000..31b7175bb04 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.fsx.il.bsl @@ -0,0 +1,426 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.mresource public FSharpSignatureData.assembly +{ + + +} +.mresource public FSharpOptimizationData.assembly +{ + + +} +.module assembly.dll + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed Issue.'16034' + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public T + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname + instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig specialname + instance int32 get_indexed1(object a1) cil managed + { + + .maxstack 7 + IL_0000: call int32 Issue.'16034'::get_i() + IL_0005: ldc.i4.1 + IL_0006: add + IL_0007: call void Issue.'16034'::set_i(int32) + IL_000c: ldstr "T().indexed1 %P() !\t%03i%P()" + IL_0011: ldc.i4.2 + IL_0012: newarr [runtime]System.Object + IL_0017: dup + IL_0018: ldc.i4.0 + IL_0019: ldarg.1 + IL_001a: box [runtime]System.Object + IL_001f: stelem [runtime]System.Object + IL_0024: dup + IL_0025: ldc.i4.1 + IL_0026: call int32 Issue.'16034'::get_i() + IL_002b: box [runtime]System.Int32 + IL_0030: stelem [runtime]System.Object + IL_0035: ldnull + IL_0036: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5>::.ctor(string, + object[], + class [runtime]System.Type[]) + IL_003b: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0040: pop + IL_0041: ldc.i4.1 + IL_0042: ret + } + + .method public hidebysig specialname + instance void set_indexed1(object a1, + int32 'value') cil managed + { + + .maxstack 7 + IL_0000: call int32 Issue.'16034'::get_i() + IL_0005: ldc.i4.1 + IL_0006: add + IL_0007: call void Issue.'16034'::set_i(int32) + IL_000c: ldstr "T().indexed1 %P() <- %P() !\t%03i%P()" + IL_0011: ldc.i4.3 + IL_0012: newarr [runtime]System.Object + IL_0017: dup + IL_0018: ldc.i4.0 + IL_0019: ldarg.1 + IL_001a: box [runtime]System.Object + IL_001f: stelem [runtime]System.Object + IL_0024: dup + IL_0025: ldc.i4.1 + IL_0026: ldarg.2 + IL_0027: box [runtime]System.Int32 + IL_002c: stelem [runtime]System.Object + IL_0031: dup + IL_0032: ldc.i4.2 + IL_0033: call int32 Issue.'16034'::get_i() + IL_0038: box [runtime]System.Int32 + IL_003d: stelem [runtime]System.Object + IL_0042: ldnull + IL_0043: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5>::.ctor(string, + object[], + class [runtime]System.Type[]) + IL_0048: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_004d: pop + IL_004e: ret + } + + .property instance int32 indexed1(object) + { + .set instance void Issue.'16034'/T::set_indexed1(object, + int32) + .get instance int32 Issue.'16034'/T::get_indexed1(object) + } + } + + .class abstract auto ansi sealed nested public Extensions + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .method public specialname static int32 + get_j() cil managed + { + + .maxstack 8 + IL_0000: ldsfld int32 '.$Issue'.'16034$fsx'::j@13 + IL_0005: ret + } + + .method public specialname static void + set_j(int32 'value') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: stsfld int32 '.$Issue'.'16034$fsx'::j@13 + IL_0006: ret + } + + .method public static int32 T.get_indexed1(class Issue.'16034'/T x, + object aa1) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 7 + IL_0000: call int32 Issue.'16034'::get_i() + IL_0005: ldc.i4.1 + IL_0006: add + IL_0007: call void Issue.'16034'::set_i(int32) + IL_000c: call int32 Issue.'16034'/Extensions::get_j() + IL_0011: ldc.i4.1 + IL_0012: add + IL_0013: call void Issue.'16034'/Extensions::set_j(int32) + IL_0018: ldstr "type extensions aa1 %P() !\t%03i%P()\t%03i%P()" + IL_001d: ldc.i4.3 + IL_001e: newarr [runtime]System.Object + IL_0023: dup + IL_0024: ldc.i4.0 + IL_0025: ldarg.1 + IL_0026: box [runtime]System.Object + IL_002b: stelem [runtime]System.Object + IL_0030: dup + IL_0031: ldc.i4.1 + IL_0032: call int32 Issue.'16034'::get_i() + IL_0037: box [runtime]System.Int32 + IL_003c: stelem [runtime]System.Object + IL_0041: dup + IL_0042: ldc.i4.2 + IL_0043: call int32 Issue.'16034'/Extensions::get_j() + IL_0048: box [runtime]System.Int32 + IL_004d: stelem [runtime]System.Object + IL_0052: ldnull + IL_0053: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5>::.ctor(string, + object[], + class [runtime]System.Type[]) + IL_0058: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_005d: pop + IL_005e: ldc.i4.1 + IL_005f: ret + } + + .method public static void T.set_indexed1(class Issue.'16034'/T x, + object aa1, + int32 'value') cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 02 00 00 00 00 00 ) + + .maxstack 7 + IL_0000: call int32 Issue.'16034'::get_i() + IL_0005: ldc.i4.1 + IL_0006: add + IL_0007: call void Issue.'16034'::set_i(int32) + IL_000c: call int32 Issue.'16034'/Extensions::get_j() + IL_0011: ldc.i4.1 + IL_0012: add + IL_0013: call void Issue.'16034'/Extensions::set_j(int32) + IL_0018: ldstr "type extension aa1 %P() <- %P()!\t%03i%P()\t%03i%P()" + IL_001d: ldc.i4.4 + IL_001e: newarr [runtime]System.Object + IL_0023: dup + IL_0024: ldc.i4.0 + IL_0025: ldarg.1 + IL_0026: box [runtime]System.Object + IL_002b: stelem [runtime]System.Object + IL_0030: dup + IL_0031: ldc.i4.1 + IL_0032: ldarg.2 + IL_0033: box [runtime]System.Int32 + IL_0038: stelem [runtime]System.Object + IL_003d: dup + IL_003e: ldc.i4.2 + IL_003f: call int32 Issue.'16034'::get_i() + IL_0044: box [runtime]System.Int32 + IL_0049: stelem [runtime]System.Object + IL_004e: dup + IL_004f: ldc.i4.3 + IL_0050: call int32 Issue.'16034'/Extensions::get_j() + IL_0055: box [runtime]System.Int32 + IL_005a: stelem [runtime]System.Object + IL_005f: ldnull + IL_0060: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5>::.ctor(string, + object[], + class [runtime]System.Type[]) + IL_0065: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_006a: pop + IL_006b: ret + } + + .property int32 j() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .set void Issue.'16034'/Extensions::set_j(int32) + .get int32 Issue.'16034'/Extensions::get_j() + } + } + + .method public specialname static int32 + get_i() cil managed + { + + .maxstack 8 + IL_0000: ldsfld int32 '.$Issue'.'16034$fsx'::i@1 + IL_0005: ret + } + + .method public specialname static void + set_i(int32 'value') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: stsfld int32 '.$Issue'.'16034$fsx'::i@1 + IL_0006: ret + } + + .method public specialname static class Issue.'16034'/T + get_t() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class Issue.'16034'/T '.$Issue'.'16034$fsx'::t@25 + IL_0005: ret + } + + .property int32 i() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .set void Issue.'16034'::set_i(int32) + .get int32 Issue.'16034'::get_i() + } + .property class Issue.'16034'/T t() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get class Issue.'16034'/T Issue.'16034'::get_t() + } +} + +.class private abstract auto ansi sealed '.$Issue'.'16034$fsx' + extends [runtime]System.Object +{ + .field static assembly int32 i@1 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly int32 j@13 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly initonly class Issue.'16034'/T t@25 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly int32 init@ + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method private specialname rtspecialname static + void .cctor() cil managed + { + + .maxstack 5 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 '.$Issue'.'16034$fsx'::i@1 + IL_0006: ldc.i4.0 + IL_0007: stsfld int32 '.$Issue'.'16034$fsx'::j@13 + IL_000c: newobj instance void Issue.'16034'/T::.ctor() + IL_0011: stsfld class Issue.'16034'/T '.$Issue'.'16034$fsx'::t@25 + IL_0016: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_001b: ldstr "ok" + IL_0020: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() + IL_0025: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) + IL_002a: ldc.i4.1 + IL_002b: callvirt instance void Issue.'16034'/T::set_indexed1(object, + int32) + IL_0030: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_0035: ldstr "ok" + IL_003a: ldc.i4.2 + IL_003b: callvirt instance void Issue.'16034'/T::set_indexed1(object, + int32) + IL_0040: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_0045: ldstr "ok" + IL_004a: ldc.i4.3 + IL_004b: callvirt instance void Issue.'16034'/T::set_indexed1(object, + int32) + IL_0050: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_0055: ldstr "ok" + IL_005a: callvirt instance int32 Issue.'16034'/T::get_indexed1(object) + IL_005f: pop + IL_0060: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_0065: ldstr "ok" + IL_006a: callvirt instance int32 Issue.'16034'/T::get_indexed1(object) + IL_006f: pop + IL_0070: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_0075: ldstr "ok" + IL_007a: ldc.i4.1 + IL_007b: callvirt instance void Issue.'16034'/T::set_indexed1(object, + int32) + IL_0080: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_0085: ldstr "nok" + IL_008a: callvirt instance int32 Issue.'16034'/T::get_indexed1(object) + IL_008f: pop + IL_0090: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_0095: ldstr "ok" + IL_009a: callvirt instance int32 Issue.'16034'/T::get_indexed1(object) + IL_009f: pop + IL_00a0: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_00a5: ldstr "ok" + IL_00aa: call int32 Issue.'16034'/Extensions::T.get_indexed1(class Issue.'16034'/T, + object) + IL_00af: pop + IL_00b0: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_00b5: ldstr "nok" + IL_00ba: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() + IL_00bf: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) + IL_00c4: ldc.i4.1 + IL_00c5: callvirt instance void Issue.'16034'/T::set_indexed1(object, + int32) + IL_00ca: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_00cf: ldstr "nok" + IL_00d4: ldc.i4.2 + IL_00d5: callvirt instance void Issue.'16034'/T::set_indexed1(object, + int32) + IL_00da: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_00df: ldstr "nok" + IL_00e4: ldc.i4.3 + IL_00e5: callvirt instance void Issue.'16034'/T::set_indexed1(object, + int32) + IL_00ea: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_00ef: ldstr "nok" + IL_00f4: callvirt instance int32 Issue.'16034'/T::get_indexed1(object) + IL_00f9: pop + IL_00fa: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_00ff: ldstr "nok" + IL_0104: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() + IL_0109: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) + IL_010e: callvirt instance int32 Issue.'16034'/T::get_indexed1(object) + IL_0113: pop + IL_0114: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_0119: ldstr "nok" + IL_011e: callvirt instance int32 Issue.'16034'/T::get_indexed1(object) + IL_0123: pop + IL_0124: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_0129: ldstr "nok_015" + IL_012e: ldc.i4.1 + IL_012f: callvirt instance void Issue.'16034'/T::set_indexed1(object, + int32) + IL_0134: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_0139: ldstr "nok_016" + IL_013e: ldc.i4.2 + IL_013f: callvirt instance void Issue.'16034'/T::set_indexed1(object, + int32) + IL_0144: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_0149: ldstr "ok_017" + IL_014e: ldc.i4.1 + IL_014f: callvirt instance void Issue.'16034'/T::set_indexed1(object, + int32) + IL_0154: call class Issue.'16034'/T Issue.'16034'::get_t() + IL_0159: ldstr "ok_018" + IL_015e: ldc.i4.1 + IL_015f: call void Issue.'16034'/Extensions::T.set_indexed1(class Issue.'16034'/T, + object, + int32) + IL_0164: ret + } + +} + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.fsx.stdout.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.fsx.stdout.bsl new file mode 100644 index 00000000000..b0f9ffd34b2 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/typeextensions/issue.16034/issue.16034.fsx.stdout.bsl @@ -0,0 +1,19 @@ +T().indexed1 [ok] <- 1 ! 001 +T().indexed1 ok <- 2 ! 002 +T().indexed1 ok <- 3 ! 003 +T().indexed1 ok ! 004 +T().indexed1 ok ! 005 +T().indexed1 ok <- 1 ! 006 +T().indexed1 nok ! 007 +T().indexed1 ok ! 008 +type extensions aa1 ok ! 009 001 +T().indexed1 [nok] <- 1 ! 010 +T().indexed1 nok <- 2 ! 011 +T().indexed1 nok <- 3 ! 012 +T().indexed1 nok ! 013 +T().indexed1 [nok] ! 014 +T().indexed1 nok ! 015 +T().indexed1 nok_015 <- 1 ! 016 +T().indexed1 nok_016 <- 2 ! 017 +T().indexed1 ok_017 <- 1 ! 018 +type extension aa1 ok_018 <- 1! 019 002 diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs index aabefaf4b35..622b7ee43bd 100644 --- a/tests/FSharp.Test.Utilities/Compiler.fs +++ b/tests/FSharp.Test.Utilities/Compiler.fs @@ -206,6 +206,87 @@ module rec Compiler = | Arm = 5 | Arm64 = 6 + module NamingConventions = + let forActualFSCOutput sourceFilePath = sourceFilePath + ".actual.fsc.stdout.err" + let forActualIL sourceFilePath = sourceFilePath + ".actual.il.err" + let forBaselineFSCOutput sourceFilePath = sourceFilePath + ".fsc.stdout.bsl" + + let forBaseLineIL sourceFilePath = + let ilBslPaths = [| + #if DEBUG + #if NETCOREAPP + yield sourceFilePath + ".il.netcore.debug.bsl" + yield sourceFilePath + ".il.netcore.bsl" + #else + yield sourceFilePath + ".il.net472.debug.bsl" + yield sourceFilePath + ".il.net472.bsl" + #endif + yield sourceFilePath + ".il.debug.bsl" + yield sourceFilePath + ".il.bsl" + #else + #if NETCOREAPP + yield sourceFilePath + ".il.netcore.release.bsl" + yield sourceFilePath + ".il.netcore.bsl" + #else + yield sourceFilePath + ".il.net472.release.bsl" + yield sourceFilePath + ".il.net472.bsl" + #endif + yield sourceFilePath + ".il.release.bsl" + yield sourceFilePath + ".il.bsl" + #endif + |] + + let findBaseline = + ilBslPaths + |> Array.tryPick(fun p -> if File.Exists p then Some p else None) + match findBaseline with + | Some s -> s + | None -> sourceFilePath + ".il.bsl" + + type BaseLineHelper = + + + + + static member readFileOrDefault (path: string) : string option = + match FileSystem.FileExistsShim(path) with + | true -> Some (File.ReadAllText path) + | _ -> None + + static member makeBaseLine(sourceFilePath, ?baselineSuffix) = + let baselineSuffix = Option.defaultValue "" baselineSuffix + let fsBslFilePath = NamingConventions.forBaselineFSCOutput sourceFilePath + let ilBslFilePath = NamingConventions.forBaseLineIL (sourceFilePath + baselineSuffix) + + let fsOutFilePath = normalizePathSeparator <| NamingConventions.forActualFSCOutput sourceFilePath + let ilOutFilePath = normalizePathSeparator <| NamingConventions.forActualIL sourceFilePath + let fsBslSource = BaseLineHelper.readFileOrDefault fsBslFilePath + let ilBslSource = BaseLineHelper.readFileOrDefault ilBslFilePath + + { + SourceFilename = Some sourceFilePath + FSBaseline = { FilePath = fsOutFilePath; BslSource=fsBslFilePath; Content = fsBslSource } + ILBaseline = { FilePath = ilOutFilePath; BslSource=ilBslFilePath ; Content = ilBslSource } + } + static member makeLegacyBaseLine(sourceFilePath, ?baselineSuffix) = + // using change extension is problematic, hence only for legacy baseline + let forActualFSCOutput sourceFilePath = Path.ChangeExtension(sourceFilePath, ".err") + let forActualIL sourceFilePath = Path.ChangeExtension(sourceFilePath, ".il") + + let baselineSuffix = Option.defaultValue "" baselineSuffix + let fsBslFilePath = NamingConventions.forBaselineFSCOutput sourceFilePath + let ilBslFilePath = NamingConventions.forBaseLineIL (sourceFilePath + baselineSuffix) + + let fsOutFilePath = normalizePathSeparator <| forActualFSCOutput sourceFilePath + let ilOutFilePath = normalizePathSeparator <| forActualIL sourceFilePath + let fsBslSource = BaseLineHelper.readFileOrDefault fsBslFilePath + let ilBslSource = BaseLineHelper.readFileOrDefault ilBslFilePath + + { + SourceFilename = Some sourceFilePath + FSBaseline = { FilePath = fsOutFilePath; BslSource=fsBslFilePath; Content = fsBslSource } + ILBaseline = { FilePath = ilOutFilePath; BslSource=ilBslFilePath ; Content = ilBslSource } + } let private defaultOptions : string list = [] let normalizePathSeparator (text:string) = text.Replace(@"\", "/") @@ -353,6 +434,12 @@ module rec Compiler = let Fsx (source: string) : CompilationUnit = fsFromString (FsxSourceCode source) |> FS + let RealFsxFromPath (path: string) = + path + |> SourceCodeFileKind.CreateReal + |> fsFromString + |> FS + let FsxFromPath (path: string) : CompilationUnit = fsFromString (SourceFromPath path) |> FS @@ -456,7 +543,12 @@ module rec Compiler = let withDebug (cUnit: CompilationUnit) : CompilationUnit = withOptionsHelper [ "--debug+" ] "debug+ is only supported on F#" cUnit - + let withBaseLine cUnit = + match cUnit with + | CompilationUnit.FS fs -> + let sourceFileName = fs.Source.GetSourceFileName + FS { fs with Baseline = Some(BaseLineHelper.makeBaseLine(sourceFileName)) } + | _ -> cUnit let withNoDebug (cUnit: CompilationUnit) : CompilationUnit = withOptionsHelper [ "--debug-" ] "debug- is only supported on F#" cUnit @@ -945,7 +1037,14 @@ module rec Compiler = match s.OutputPath with | None -> failwith "Compilation didn't produce any output. Unable to run. (Did you forget to set output type to Exe?)" | Some p -> - let (exitCode, output, errors) = CompilerAssert.ExecuteAndReturnResult (p, s.Dependencies, false) + let isFsx = + match s.Compilation with + | FS fs -> + match fs.Source with + | SourceCodeFileKind.Fsx _ -> true + | _ -> false + | _ -> false + let (exitCode, output, errors) = 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 }) } @@ -1076,7 +1175,8 @@ module rec Compiler = let private createBaselineErrors (baselineFile: BaselineFile) (actualErrors: string) : unit = - FileSystem.OpenFileForWriteShim(baselineFile.FilePath + ".err").Write(actualErrors) + printfn $"creating baseline error file for convenience {baselineFile}" + FileSystem.OpenFileForWriteShim(baselineFile.FilePath).Write(actualErrors) let private verifyFSBaseline (fs) : unit = match fs.Baseline with @@ -1086,10 +1186,19 @@ module rec Compiler = match bsl.FSBaseline.Content with | Some b -> b.Replace("\r\n","\n") | None -> String.Empty - - let typecheckDiagnostics = fs |> typecheckFSharpSourceAndReturnErrors - - let errorsActual = (typecheckDiagnostics |> Array.map (sprintf "%A") |> String.concat "\n").Replace("\r\n","\n") + let errorsActual = + match fs.Source with + | SourceCodeFileKind.Fsx _-> + let fsxScriptFile = FileInfo fs.Source.GetSourceFileName + //let dir = fsxScriptFile.Directory + //RunRealScriptWithOptionsAndReturnResult + let fsxResult = CompilerAssert.RunRealScriptWithOptionsAndReturnResult [||] fsxScriptFile + + snd fsxResult |> sanitizeFsxOutput + | SourceCodeFileKind.Fs _-> + let typecheckDiagnostics = fs |> typecheckFSharpSourceAndReturnErrors + (typecheckDiagnostics |> Array.map (sprintf "%A") |> String.concat "\n").Replace("\r\n","\n") + | _ -> failwith $"not supposed to check %A{fs.Source}" if errorsExpectedBaseLine <> errorsActual then fs.CreateOutputDirectory() @@ -1122,29 +1231,31 @@ module rec Compiler = let verifyILBinary (il: string list) (dll: string)= ILChecker.checkIL dll il let private verifyFSILBaseline (baseline: Baseline option) (result: CompilationOutput) : unit = - match baseline with - | None -> failwith "Baseline was not provided." - | Some bsl -> - match result.OutputPath with - | None -> failwith "Operation didn't produce any output!" - | Some p -> - let expectedIL = - match bsl.ILBaseline.Content with - | Some b -> b - | None -> String.Empty - let (success, errorMsg, actualIL) = ILChecker.verifyILAndReturnActual p expectedIL - - if not success then - // Failed try update baselines if required - // If we are here then the il file has been produced we can write it back to the baseline location - // if the environment variable TEST_UPDATE_BSL has been set - if snd (Int32.TryParse(Environment.GetEnvironmentVariable("TEST_UPDATE_BSL"))) <> 0 then - match baseline with - | Some baseline -> System.IO.File.Copy(baseline.ILBaseline.FilePath, baseline.ILBaseline.BslSource, true) - | None -> () - - createBaselineErrors bsl.ILBaseline actualIL - Assert.Fail(errorMsg) + match result.OutputPath with + | None -> failwith "Operation didn't produce any output!" + | Some p -> + match baseline with + | None -> failwith "Baseline was not provided." + | Some bsl -> + let expectedIL = + match bsl.ILBaseline.Content with + | Some b -> b + | None -> String.Empty + + let (success, errorMsg, actualIL) = ILChecker.verifyILAndReturnActual p expectedIL + + if not success then + // Failed try update baselines if required + // If we are here then the il file has been produced we can write it back to the baseline location + // if the environment variable TEST_UPDATE_BSL has been set + if snd (Int32.TryParse(Environment.GetEnvironmentVariable("TEST_UPDATE_BSL"))) <> 0 then + match baseline with + | Some baseline -> System.IO.File.Copy(baseline.ILBaseline.FilePath, baseline.ILBaseline.FilePath, true) + | None -> () + + createBaselineErrors bsl.ILBaseline actualIL + let messagePrefix = $"failed IL base line\nactual file: {baseline.Value.ILBaseline.FilePath}\nexpected file: {baseline.Value.ILBaseline.BslSource}\n" + Assert.Fail(messagePrefix + errorMsg) let verifyILBaseline (cUnit: CompilationUnit) : CompilationUnit = match cUnit with @@ -1177,6 +1288,14 @@ module rec Compiler = let pattern = @"(Microsoft \(R\) (.*) version (.*) F# (.*))" let result = regexStrip output pattern (RegexOptions.Multiline ||| RegexOptions.ExplicitCapture) result + let sanitizeFsxOutput output = + let slndir = (DirectoryInfo __SOURCE_DIRECTORY__).Parent.Parent.FullName + let pattern = @"(Microsoft \(R\) (.*) version (.*) F# (.*))" + let output = regexStrip output pattern (RegexOptions.Multiline ||| RegexOptions.ExplicitCapture) + let pattern = @"\n\nCopyright (c) Microsoft Corporation. All Rights Reserved.\n\n" + let output = regexStrip output pattern (RegexOptions.Multiline ||| RegexOptions.ExplicitCapture) + output.Replace(slndir, "") + let getOutput (cResult: CompilationResult) : string option = let result = @@ -1198,10 +1317,25 @@ module rec Compiler = | Some actual -> let expected = stripVersion (normalizeNewlines expected) if expected <> actual then - failwith $"""Output does not match expected: ------------{Environment.NewLine}{expected}{Environment.NewLine}Actual: ------------{Environment.NewLine}{actual}{Environment.NewLine}""" + let errFile = + match cResult.Output.Compilation with + | FS s -> s.Source.GetSourceFileName + ".stdout.err" + | _ -> failwith "not supposed to check output of non F# source" + File.WriteAllText(errFile, actual) + failwith $"""Output does not match expected, err file generated at {errFile} for your convenience: \n ------------{Environment.NewLine}{expected}{Environment.NewLine}Actual: ------------{Environment.NewLine}{actual}{Environment.NewLine}""" else cResult + let verifyOutputWithDefaultBaseline (cResult: CompilationResult) = + let expected = + match cResult.Output.Compilation with + | FS s -> + s.Source.GetSourceFileName + ".stdout.bsl" + |> File.ReadAllText + |> normalizeNewlines + |> stripVersion + | _ -> failwith "not supposed to check output of non F# source" + verifyOutput expected cResult let verifyOutputWithBaseline path = verifyOutput (File.ReadAllText(path).Replace(@"\r\n", Environment.NewLine)) diff --git a/tests/FSharp.Test.Utilities/CompilerAssert.fs b/tests/FSharp.Test.Utilities/CompilerAssert.fs index a0eea96e1d4..01d40fe666f 100644 --- a/tests/FSharp.Test.Utilities/CompilerAssert.fs +++ b/tests/FSharp.Test.Utilities/CompilerAssert.fs @@ -59,6 +59,13 @@ type SourceCodeFileKind = | ".fsx" -> Fsx({FileName=path; SourceText=source}) | ".cs" -> Cs({FileName=path; SourceText=source}) | ".fs" | _ -> Fs({FileName=path; SourceText=source}) + static member CreateReal(path:string) = + let source = Some(File.ReadAllText path) + match Path.GetExtension(path).ToLowerInvariant() with + | ".fsi" -> Fsi({FileName=path; SourceText=source}) + | ".fsx" -> Fsx({FileName=path; SourceText=source}) + | ".cs" -> Cs({FileName=path; SourceText=source}) + | ".fs" | _ -> Fs({FileName=path; SourceText=source}) member this.ChangeExtension = match this with @@ -261,18 +268,24 @@ module rec CompilerAssertHelpers = let checker = FSharpChecker.Create(suggestNamesForErrors=true) // Unlike C# whose entrypoint is always string[] F# can make an entrypoint with 0 args, or with an array of string[] - let mkDefaultArgs (entryPoint:MethodInfo) : obj[] = [| - if entryPoint.GetParameters().Length = 1 then + let mkDefaultArgs (entryPoint:MethodBase) : obj[] = [| + if not (isNull entryPoint) && entryPoint.GetParameters().Length = 1 then yield Array.empty |] - let executeAssemblyEntryPoint (asm: Assembly) = - let entryPoint = asm.EntryPoint + let executeAssemblyEntryPoint (asm: Assembly) isFsx = + let entryPoint : MethodBase = asm.EntryPoint + let entryPoint = + if isNull entryPoint && isFsx then + let moduleInitType = asm.GetTypes() |> Array.last + moduleInitType.GetConstructors(BindingFlags.Static ||| BindingFlags.NonPublic).[0] :> MethodBase + else + entryPoint let args = mkDefaultArgs entryPoint captureConsoleOutputs (fun () -> entryPoint.Invoke(Unchecked.defaultof, args) |> ignore) #if NETCOREAPP - let executeBuiltApp assembly deps = + let executeBuiltApp assembly deps isFsx = let ctxt = AssemblyLoadContext("ContextName", true) try ctxt.add_Resolving(fun ctxt name -> @@ -281,7 +294,7 @@ module rec CompilerAssertHelpers = |> Option.map ctxt.LoadFromAssemblyPath |> Option.defaultValue null) - ctxt.LoadFromAssemblyPath assembly |> executeAssemblyEntryPoint + executeAssemblyEntryPoint (ctxt.LoadFromAssemblyPath assembly) isFsx finally ctxt.Unload() #else @@ -577,8 +590,8 @@ module rec CompilerAssertHelpers = succeeded, stdout.ToString(), stderr.ToString(), exn - let executeBuiltAppAndReturnResult (outputFilePath: string) (deps: string list) : (int * string * string) = - let succeeded, stdout, stderr, _ = executeBuiltApp outputFilePath deps + 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 @@ -681,10 +694,10 @@ Updated automatically, please check diffs in your pull request, changes must be static member CompileRaw(cmpl: Compilation, ?ignoreWarnings) = returnCompilation cmpl (defaultArg ignoreWarnings false) - static member ExecuteAndReturnResult (outputFilePath: string, deps: string list, newProcess: bool) = + 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 + executeBuiltAppAndReturnResult outputFilePath deps isFsx else executeBuiltAppNewProcessAndReturnResult outputFilePath @@ -710,7 +723,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 + let _succeeded, _stdout, _stderr, exn = executeBuiltApp outputFilePath deps false exn |> Option.iter raise) static member ExecutionHasOutput(cmpl: Compilation, expectedOutput: string) = @@ -776,6 +789,7 @@ Updated automatically, please check diffs in your pull request, changes must be let errors = let parseResults, fileAnswer = let defaultOptions = defaultProjectOptions TargetFramework.Current + checker.ParseAndCheckFileInProject( name, 0, @@ -960,6 +974,42 @@ Updated automatically, please check diffs in your pull request, changes must be errorMessages, outStream.ToString() + static member RunRealScriptWithOptionsAndReturnResult options (scriptFile: FileInfo) = + //let savedDir = Environment.CurrentDirectory + //use _ = { new IDisposable with member x.Dispose() = Environment.CurrentDirectory <- savedDir } + //Environment.CurrentDirectory <- scriptFile.Directory.FullName + + + // Intialize output and input streams + use inStream = new StringReader("") + use outStream = new StringWriter() + use errStream = new StringWriter() + + // Build command line arguments & start FSI session + let argv = [| "C:\\fsi.exe" |] +#if NETCOREAPP + let args = Array.append argv [|"--noninteractive"; "--targetprofile:netcore"|] +#else + let args = Array.append argv [|"--noninteractive"; "--targetprofile:mscorlib"|] +#endif + let allArgs = Array.append args options + + let fsiConfig = FsiEvaluationSession.GetDefaultConfiguration() + use fsiSession = FsiEvaluationSession.Create(fsiConfig, allArgs, inStream, outStream, errStream, collectible = true) + fsiSession.EvalInteraction($"""#cd @"{scriptFile.Directory.FullName}";; """) + let ch, errors = fsiSession.EvalScriptNonThrowing scriptFile.FullName + + let errorMessages = ResizeArray() + errors + |> Seq.iter (fun error -> errorMessages.Add(error.Message)) + + match ch with + | Choice2Of2 ex -> errorMessages.Add(ex.Message) + | _ -> () + + errorMessages, outStream.ToString() + + static member RunScriptWithOptions options (source: string) (expectedErrorMessages: string list) = let errorMessages, _ = CompilerAssert.RunScriptWithOptionsAndReturnResult options source if expectedErrorMessages.Length <> errorMessages.Count then diff --git a/tests/FSharp.Test.Utilities/DirectoryAttribute.fs b/tests/FSharp.Test.Utilities/DirectoryAttribute.fs index fbb40b70b17..b01a149d30f 100644 --- a/tests/FSharp.Test.Utilities/DirectoryAttribute.fs +++ b/tests/FSharp.Test.Utilities/DirectoryAttribute.fs @@ -26,11 +26,6 @@ type DirectoryAttribute(dir: string) = let mutable baselineSuffix = "" let mutable includes = Array.empty - let readFileOrDefault (path: string) : string option = - match FileSystem.FileExistsShim(path) with - | true -> Some (File.ReadAllText path) - | _ -> None - let createCompilationUnit path (filename: string) methodName multipleFiles = // if there are multiple files being processed, add extra directory for each test to avoid reference file conflicts let extraDirectory = @@ -39,58 +34,15 @@ type DirectoryAttribute(dir: string) = |> normalizeName else "" let outputDirectory = outputDirectory methodName extraDirectory - let outputDirectoryPath = + let _outputDirectoryPath = match outputDirectory with | Some path -> path.FullName | None -> failwith "Can't set the output directory" let sourceFilePath = normalizePathSeparator (path ++ filename) - let fsBslFilePath = sourceFilePath + ".err.bsl" - let ilBslFilePath = - let ilBslPaths = [| -#if DEBUG - #if NETCOREAPP - yield sourceFilePath + baselineSuffix + ".il.netcore.debug.bsl" - yield sourceFilePath + baselineSuffix + ".il.netcore.bsl" - #else - yield sourceFilePath + baselineSuffix + ".il.net472.debug.bsl" - yield sourceFilePath + baselineSuffix + ".il.net472.bsl" - #endif - yield sourceFilePath + baselineSuffix + ".il.debug.bsl" - yield sourceFilePath + baselineSuffix + ".il.bsl" -#else - #if NETCOREAPP - yield sourceFilePath + baselineSuffix + ".il.netcore.release.bsl" - yield sourceFilePath + baselineSuffix + ".il.netcore.bsl" - #else - yield sourceFilePath + baselineSuffix + ".il.net472.release.bsl" - yield sourceFilePath + baselineSuffix + ".il.net472.bsl" - #endif - yield sourceFilePath + baselineSuffix + ".il.release.bsl" - yield sourceFilePath + baselineSuffix + ".il.bsl" -#endif - |] - - let findBaseline = - ilBslPaths - |> Array.tryPick(fun p -> if File.Exists(p) then Some p else None) - match findBaseline with - | Some s -> s - | None -> sourceFilePath + baselineSuffix + ".il.bsl" - - let fsOutFilePath = normalizePathSeparator (Path.ChangeExtension(outputDirectoryPath ++ filename, ".err")) - let ilOutFilePath = normalizePathSeparator ( Path.ChangeExtension(outputDirectoryPath ++ filename, ".il")) - let fsBslSource = readFileOrDefault fsBslFilePath - let ilBslSource = readFileOrDefault ilBslFilePath - + { Source = SourceCodeFileKind.Create(sourceFilePath) AdditionalSources = [] - Baseline = - Some - { - SourceFilename = Some sourceFilePath - FSBaseline = { FilePath = fsOutFilePath; BslSource=fsBslFilePath; Content = fsBslSource } - ILBaseline = { FilePath = ilOutFilePath; BslSource=ilBslFilePath ; Content = ilBslSource } - } + Baseline = Some (BaseLineHelper.makeLegacyBaseLine(sourceFilePath, baselineSuffix)) Options = [] OutputType = Library Name = Some filename