From 37f951d3e842896ced6ad8c22aee000e2770144b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Sep 2025 11:03:36 +0000 Subject: [PATCH 01/10] Initial plan From 633e5172e892e7771ff4baa2fbd88d7f595064c9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Sep 2025 11:33:21 +0000 Subject: [PATCH 02/10] Implement centralized VS installation discovery infrastructure Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com> --- .../FSharp.Editor.Tests.fsproj | 1 + .../Helpers/AssemblyResolver.fs | 31 ++-- .../tests/Salsa/VisualFSharp.Salsa.fsproj | 1 + vsintegration/tests/Salsa/VsMocks.fs | 22 +-- .../tests/TestHelpers/TestHelpers.fsproj | 32 ++++ .../tests/TestHelpers/VSInstallDiscovery.fs | 144 ++++++++++++++++++ .../tests/UnitTests/AssemblyResolver.fs | 23 +-- .../UnitTests/VisualFSharp.UnitTests.fsproj | 1 + 8 files changed, 224 insertions(+), 31 deletions(-) create mode 100644 vsintegration/tests/TestHelpers/TestHelpers.fsproj create mode 100644 vsintegration/tests/TestHelpers/VSInstallDiscovery.fs diff --git a/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj b/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj index c084fc6f06..d0a264e868 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj +++ b/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj @@ -105,6 +105,7 @@ + diff --git a/vsintegration/tests/FSharp.Editor.Tests/Helpers/AssemblyResolver.fs b/vsintegration/tests/FSharp.Editor.Tests/Helpers/AssemblyResolver.fs index f41f10fa13..98db3e27df 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/Helpers/AssemblyResolver.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/Helpers/AssemblyResolver.fs @@ -8,21 +8,26 @@ open System.Reflection module AssemblyResolver = open System.Globalization + open Microsoft.VisualStudio.FSharp.TestHelpers.VSInstallDiscovery let vsInstallDir = - // use the environment variable to find the VS installdir - let vsvar = - let var = Environment.GetEnvironmentVariable("VS170COMNTOOLS") - - if String.IsNullOrEmpty var then - Environment.GetEnvironmentVariable("VSAPPIDDIR") - else - var - - if String.IsNullOrEmpty vsvar then - failwith "VS170COMNTOOLS and VSAPPIDDIR environment variables not found." - - Path.Combine(vsvar, "..") + // Use centralized VS installation discovery with graceful fallback + match tryGetVSInstallDir () with + | Some dir -> dir + | None -> + // Fallback to legacy behavior for backward compatibility + let vsvar = + let var = Environment.GetEnvironmentVariable("VS170COMNTOOLS") + + if String.IsNullOrEmpty var then + Environment.GetEnvironmentVariable("VSAPPIDDIR") + else + var + + if String.IsNullOrEmpty vsvar then + failwith "VS170COMNTOOLS and VSAPPIDDIR environment variables not found." + + Path.Combine(vsvar, "..") let probingPaths = [| diff --git a/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj b/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj index e1e657a651..1e806e423b 100644 --- a/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj +++ b/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj @@ -34,6 +34,7 @@ + diff --git a/vsintegration/tests/Salsa/VsMocks.fs b/vsintegration/tests/Salsa/VsMocks.fs index 5189b7faec..ab8901fcb7 100644 --- a/vsintegration/tests/Salsa/VsMocks.fs +++ b/vsintegration/tests/Salsa/VsMocks.fs @@ -1651,15 +1651,19 @@ module internal VsActual = member public _.JoinableTaskContext : JoinableTaskContext = jtc let vsInstallDir = - // use the environment variable to find the VS installdir - let vsvar = - let var = Environment.GetEnvironmentVariable("VS170COMNTOOLS") - if String.IsNullOrEmpty var then - Environment.GetEnvironmentVariable("VSAPPIDDIR") - else - var - if String.IsNullOrEmpty vsvar then failwith "VS170COMNTOOLS and VSAPPIDDIR environment variables not found." - Path.Combine(vsvar, "..") + // Use centralized VS installation discovery with graceful fallback + match Microsoft.VisualStudio.FSharp.TestHelpers.VSInstallDiscovery.tryGetVSInstallDir () with + | Some dir -> dir + | None -> + // Fallback to legacy behavior for backward compatibility + let vsvar = + let var = Environment.GetEnvironmentVariable("VS170COMNTOOLS") + if String.IsNullOrEmpty var then + Environment.GetEnvironmentVariable("VSAPPIDDIR") + else + var + if String.IsNullOrEmpty vsvar then failwith "VS170COMNTOOLS and VSAPPIDDIR environment variables not found." + Path.Combine(vsvar, "..") let CreateEditorCatalog() = let thisAssembly = Assembly.GetExecutingAssembly().Location diff --git a/vsintegration/tests/TestHelpers/TestHelpers.fsproj b/vsintegration/tests/TestHelpers/TestHelpers.fsproj new file mode 100644 index 0000000000..7ab4b20231 --- /dev/null +++ b/vsintegration/tests/TestHelpers/TestHelpers.fsproj @@ -0,0 +1,32 @@ + + + + Library + net472 + $(NoWarn);44;45;47;52;58;75;1204 + true + true + true + false + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vsintegration/tests/TestHelpers/VSInstallDiscovery.fs b/vsintegration/tests/TestHelpers/VSInstallDiscovery.fs new file mode 100644 index 0000000000..2ae105db98 --- /dev/null +++ b/vsintegration/tests/TestHelpers/VSInstallDiscovery.fs @@ -0,0 +1,144 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +/// Test-only Visual Studio installation discovery infrastructure. +/// Provides a centralized, robust, and graceful discovery mechanism for Visual Studio installations +/// used by integration/editor/unit tests under vsintegration/tests. +[] +module Microsoft.VisualStudio.FSharp.TestHelpers.VSInstallDiscovery + +open System +open System.IO +open System.Diagnostics + +/// Result of VS installation discovery +type VSInstallResult = + | Found of installPath: string * source: string + | NotFound of reason: string + +/// Attempts to find a Visual Studio installation using multiple fallback strategies +let tryFindVSInstallation () : VSInstallResult = + + /// Check if a path exists and looks like a valid VS installation + let validateVSPath path = + if String.IsNullOrEmpty(path) then false + else + try + let fullPath = Path.GetFullPath(path) + Directory.Exists(fullPath) && + Directory.Exists(Path.Combine(fullPath, "IDE")) && + (File.Exists(Path.Combine(fullPath, "IDE", "devenv.exe")) || + File.Exists(Path.Combine(fullPath, "IDE", "VSIXInstaller.exe"))) + with + | _ -> false + + /// Strategy 1: FSHARP_VS_INSTALL_DIR (explicit override for tests) + let tryExplicitOverride () = + let envVar = Environment.GetEnvironmentVariable("FSHARP_VS_INSTALL_DIR") + if validateVSPath envVar then + Some (Found (Path.GetFullPath(envVar), "FSHARP_VS_INSTALL_DIR environment variable")) + else None + + /// Strategy 2: VSAPPIDDIR (derive parent of Common7/IDE) + let tryVSAppIdDir () = + let envVar = Environment.GetEnvironmentVariable("VSAPPIDDIR") + if not (String.IsNullOrEmpty(envVar)) then + try + let parentPath = Path.Combine(envVar, "..") + if validateVSPath parentPath then + Some (Found (Path.GetFullPath(parentPath), "VSAPPIDDIR environment variable")) + else None + with + | _ -> None + else None + + /// Strategy 3: Highest version among VS*COMNTOOLS environment variables + let tryVSCommonTools () = + let vsVersions = [ + ("VS170COMNTOOLS", 17) // Visual Studio 2022 + ("VS160COMNTOOLS", 16) // Visual Studio 2019 + ("VS150COMNTOOLS", 15) // Visual Studio 2017 + ("VS140COMNTOOLS", 14) // Visual Studio 2015 + ("VS120COMNTOOLS", 12) // Visual Studio 2013 + ] + + vsVersions + |> List.tryPick (fun (envName, version) -> + let envVar = Environment.GetEnvironmentVariable(envName) + if not (String.IsNullOrEmpty(envVar)) then + try + let parentPath = Path.Combine(envVar, "..") + if validateVSPath parentPath then + Some (Found (Path.GetFullPath(parentPath), $"{envName} environment variable (VS version {version})")) + else None + with + | _ -> None + else None) + + /// Strategy 4: vswhere.exe (Visual Studio Installer) + let tryVSWhere () = + try + let programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) + let vswherePath = Path.Combine(programFiles, "Microsoft Visual Studio", "Installer", "vswhere.exe") + + if File.Exists(vswherePath) then + let startInfo = ProcessStartInfo( + FileName = vswherePath, + Arguments = "-latest -products * -requires Microsoft.Component.MSBuild -property installationPath", + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true + ) + + use proc = Process.Start(startInfo) + proc.WaitForExit(5000) |> ignore // 5 second timeout + + if proc.ExitCode = 0 then + let output = proc.StandardOutput.ReadToEnd().Trim() + if validateVSPath output then + Some (Found (Path.GetFullPath(output), "vswhere.exe discovery")) + else None + else None + else None + with + | _ -> None + + // Try each strategy in order of precedence + match tryExplicitOverride () with + | Some result -> result + | None -> + match tryVSAppIdDir () with + | Some result -> result + | None -> + match tryVSCommonTools () with + | Some result -> result + | None -> + match tryVSWhere () with + | Some result -> result + | None -> NotFound "No Visual Studio installation found using any discovery method" + +/// Gets the VS installation directory, with graceful fallback behavior. +/// Returns None if no VS installation can be found, allowing callers to handle gracefully. +let tryGetVSInstallDir () : string option = + match tryFindVSInstallation () with + | Found (path, _) -> Some path + | NotFound _ -> None + +/// Gets the VS installation directory with detailed logging. +/// Useful for debugging installation discovery issues in tests. +let getVSInstallDirWithLogging (logAction: string -> unit) : string option = + match tryFindVSInstallation () with + | Found (path, source) -> + logAction $"Visual Studio installation found at: {path} (via {source})" + Some path + | NotFound reason -> + logAction $"Visual Studio installation not found: {reason}" + None + +/// Legacy compatibility function that maintains the old behavior of hard-failing. +/// Use this only for tests that must maintain the old behavior. +[] +let getVSInstallDirOrFail () : string = + match tryFindVSInstallation () with + | Found (path, _) -> path + | NotFound reason -> failwith $"VS170COMNTOOLS and VSAPPIDDIR environment variables not found. {reason}" \ No newline at end of file diff --git a/vsintegration/tests/UnitTests/AssemblyResolver.fs b/vsintegration/tests/UnitTests/AssemblyResolver.fs index aab95cc46f..538fddb688 100644 --- a/vsintegration/tests/UnitTests/AssemblyResolver.fs +++ b/vsintegration/tests/UnitTests/AssemblyResolver.fs @@ -6,17 +6,22 @@ open System.Reflection module AssemblyResolver = open System.Globalization + open Microsoft.VisualStudio.FSharp.TestHelpers.VSInstallDiscovery let vsInstallDir = - // use the environment variable to find the VS installdir - let vsvar = - let var = Environment.GetEnvironmentVariable("VS170COMNTOOLS") - if String.IsNullOrEmpty var then - Environment.GetEnvironmentVariable("VSAPPIDDIR") - else - var - if String.IsNullOrEmpty vsvar then failwith "VS170COMNTOOLS and VSAPPIDDIR environment variables not found." - Path.Combine(vsvar, "..") + // Use centralized VS installation discovery with graceful fallback + match tryGetVSInstallDir () with + | Some dir -> dir + | None -> + // Fallback to legacy behavior for backward compatibility + let vsvar = + let var = Environment.GetEnvironmentVariable("VS170COMNTOOLS") + if String.IsNullOrEmpty var then + Environment.GetEnvironmentVariable("VSAPPIDDIR") + else + var + if String.IsNullOrEmpty vsvar then failwith "VS170COMNTOOLS and VSAPPIDDIR environment variables not found." + Path.Combine(vsvar, "..") let probingPaths = [| Path.Combine(vsInstallDir, @"IDE\CommonExtensions\Microsoft\Editor") diff --git a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj index 96fde123dc..256e52d6f1 100644 --- a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj +++ b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj @@ -78,6 +78,7 @@ + From 18b2cd8ce043662d6dbe3d01109b6c184ebe0304 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Sep 2025 11:38:23 +0000 Subject: [PATCH 03/10] Complete VS installation discovery with tests and validation Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com> --- .../tests/TestHelpers/TestHelpers.fsproj | 1 + .../TestHelpers/VSInstallDiscoveryTests.fs | 84 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 vsintegration/tests/TestHelpers/VSInstallDiscoveryTests.fs diff --git a/vsintegration/tests/TestHelpers/TestHelpers.fsproj b/vsintegration/tests/TestHelpers/TestHelpers.fsproj index 7ab4b20231..3e4836b535 100644 --- a/vsintegration/tests/TestHelpers/TestHelpers.fsproj +++ b/vsintegration/tests/TestHelpers/TestHelpers.fsproj @@ -18,6 +18,7 @@ + diff --git a/vsintegration/tests/TestHelpers/VSInstallDiscoveryTests.fs b/vsintegration/tests/TestHelpers/VSInstallDiscoveryTests.fs new file mode 100644 index 0000000000..10a505d228 --- /dev/null +++ b/vsintegration/tests/TestHelpers/VSInstallDiscoveryTests.fs @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +/// Simple test to verify VS installation discovery functionality +module Microsoft.VisualStudio.FSharp.TestHelpers.VSInstallDiscoveryTests + +open System +open System.IO + +/// Test basic discovery functionality +let testBasicDiscovery () = + printfn "Testing VS installation discovery..." + + // Test the discovery process + let result = VSInstallDiscovery.tryFindVSInstallation () + match result with + | VSInstallDiscovery.Found (path, source) -> + printfn $"✓ VS installation found at: {path}" + printfn $" Source: {source}" + + // Validate that the path looks reasonable + if Directory.Exists(path) && Directory.Exists(Path.Combine(path, "IDE")) then + printfn " ✓ Path validation passed" + else + printfn " ✗ Path validation failed - directory structure not as expected" + + | VSInstallDiscovery.NotFound reason -> + printfn $"✗ VS installation not found: {reason}" + printfn " This is expected if VS is not installed or environment variables are not set" + + // Test the optional version + let optPath = VSInstallDiscovery.tryGetVSInstallDir () + match optPath with + | Some path -> printfn $"✓ tryGetVSInstallDir returned: {path}" + | None -> printfn "✗ tryGetVSInstallDir returned None" + + // Test the logging version + let logMessages = ResizeArray() + let logger msg = logMessages.Add(msg) + let pathWithLogging = VSInstallDiscovery.getVSInstallDirWithLogging logger + + printfn "Logged messages:" + for msg in logMessages do + printfn $" LOG: {msg}" + + printfn "✓ Basic discovery test completed" + +/// Test environment variable scenarios +let testEnvironmentVariables () = + printfn "\nTesting environment variable scenarios..." + + // Save original values + let originalVS170 = Environment.GetEnvironmentVariable("VS170COMNTOOLS") + let originalVSAPP = Environment.GetEnvironmentVariable("VSAPPIDDIR") + let originalFSHARP = Environment.GetEnvironmentVariable("FSHARP_VS_INSTALL_DIR") + + try + // Test explicit override (highest priority) + Environment.SetEnvironmentVariable("FSHARP_VS_INSTALL_DIR", @"C:\TestPath") + Environment.SetEnvironmentVariable("VS170COMNTOOLS", @"C:\VS\Common7\Tools\") + + let result = VSInstallDiscovery.tryFindVSInstallation () + match result with + | VSInstallDiscovery.Found (path, source) when source.Contains("FSHARP_VS_INSTALL_DIR") -> + printfn "✓ FSHARP_VS_INSTALL_DIR override works correctly" + | _ -> + printfn "✗ FSHARP_VS_INSTALL_DIR override not working as expected" + + // Clear explicit override to test VS170COMNTOOLS + Environment.SetEnvironmentVariable("FSHARP_VS_INSTALL_DIR", null) + + printfn "✓ Environment variable scenario tests completed" + + finally + // Restore original values + Environment.SetEnvironmentVariable("VS170COMNTOOLS", originalVS170) + Environment.SetEnvironmentVariable("VSAPPIDDIR", originalVSAPP) + Environment.SetEnvironmentVariable("FSHARP_VS_INSTALL_DIR", originalFSHARP) + +/// Run all tests +let runTests () = + printfn "=== VS Installation Discovery Tests ===" + testBasicDiscovery () + testEnvironmentVariables () + printfn "=== Tests completed ===" \ No newline at end of file From 1aad0e2a06e688502805d7411af5b2255259f948 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 17 Sep 2025 10:22:25 +0000 Subject: [PATCH 04/10] Address feedback: Move to FSharp.Test.Utilities, remove FSHARP_VS_INSTALL_DIR, add VS180COMNTOOLS support Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com> --- .../FSharp.Test.Utilities.fsproj | 3 + .../VSInstallDiscovery.fs | 27 ++---- .../FSharp.Editor.Tests.fsproj | 1 - .../Helpers/AssemblyResolver.fs | 2 +- .../tests/Salsa/VisualFSharp.Salsa.fsproj | 1 - vsintegration/tests/Salsa/VsMocks.fs | 2 +- .../tests/TestHelpers/TestHelpers.fsproj | 33 -------- .../TestHelpers/VSInstallDiscoveryTests.fs | 84 ------------------- .../tests/UnitTests/AssemblyResolver.fs | 2 +- .../UnitTests/VisualFSharp.UnitTests.fsproj | 1 - 10 files changed, 15 insertions(+), 141 deletions(-) rename {vsintegration/tests/TestHelpers => tests/FSharp.Test.Utilities}/VSInstallDiscovery.fs (85%) delete mode 100644 vsintegration/tests/TestHelpers/TestHelpers.fsproj delete mode 100644 vsintegration/tests/TestHelpers/VSInstallDiscoveryTests.fs diff --git a/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj b/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj index 484f8acfbb..4431505152 100644 --- a/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj +++ b/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj @@ -33,6 +33,7 @@ + @@ -80,6 +81,8 @@ + + diff --git a/vsintegration/tests/TestHelpers/VSInstallDiscovery.fs b/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs similarity index 85% rename from vsintegration/tests/TestHelpers/VSInstallDiscovery.fs rename to tests/FSharp.Test.Utilities/VSInstallDiscovery.fs index 2ae105db98..1233c7e4b7 100644 --- a/vsintegration/tests/TestHelpers/VSInstallDiscovery.fs +++ b/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs @@ -4,7 +4,7 @@ /// Provides a centralized, robust, and graceful discovery mechanism for Visual Studio installations /// used by integration/editor/unit tests under vsintegration/tests. [] -module Microsoft.VisualStudio.FSharp.TestHelpers.VSInstallDiscovery +module FSharp.Test.Utilities.VSInstallDiscovery open System open System.IO @@ -31,14 +31,7 @@ let tryFindVSInstallation () : VSInstallResult = with | _ -> false - /// Strategy 1: FSHARP_VS_INSTALL_DIR (explicit override for tests) - let tryExplicitOverride () = - let envVar = Environment.GetEnvironmentVariable("FSHARP_VS_INSTALL_DIR") - if validateVSPath envVar then - Some (Found (Path.GetFullPath(envVar), "FSHARP_VS_INSTALL_DIR environment variable")) - else None - - /// Strategy 2: VSAPPIDDIR (derive parent of Common7/IDE) + /// Strategy 1: VSAPPIDDIR (derive parent of Common7/IDE) let tryVSAppIdDir () = let envVar = Environment.GetEnvironmentVariable("VSAPPIDDIR") if not (String.IsNullOrEmpty(envVar)) then @@ -51,9 +44,10 @@ let tryFindVSInstallation () : VSInstallResult = | _ -> None else None - /// Strategy 3: Highest version among VS*COMNTOOLS environment variables + /// Strategy 2: Highest version among VS*COMNTOOLS environment variables let tryVSCommonTools () = let vsVersions = [ + ("VS180COMNTOOLS", 18) // Visual Studio 2026 ("VS170COMNTOOLS", 17) // Visual Studio 2022 ("VS160COMNTOOLS", 16) // Visual Studio 2019 ("VS150COMNTOOLS", 15) // Visual Studio 2017 @@ -74,7 +68,7 @@ let tryFindVSInstallation () : VSInstallResult = | _ -> None else None) - /// Strategy 4: vswhere.exe (Visual Studio Installer) + /// Strategy 3: vswhere.exe (Visual Studio Installer) let tryVSWhere () = try let programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) @@ -104,18 +98,15 @@ let tryFindVSInstallation () : VSInstallResult = | _ -> None // Try each strategy in order of precedence - match tryExplicitOverride () with + match tryVSAppIdDir () with | Some result -> result | None -> - match tryVSAppIdDir () with + match tryVSCommonTools () with | Some result -> result | None -> - match tryVSCommonTools () with + match tryVSWhere () with | Some result -> result - | None -> - match tryVSWhere () with - | Some result -> result - | None -> NotFound "No Visual Studio installation found using any discovery method" + | None -> NotFound "No Visual Studio installation found using any discovery method" /// Gets the VS installation directory, with graceful fallback behavior. /// Returns None if no VS installation can be found, allowing callers to handle gracefully. diff --git a/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj b/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj index d0a264e868..c084fc6f06 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj +++ b/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj @@ -105,7 +105,6 @@ - diff --git a/vsintegration/tests/FSharp.Editor.Tests/Helpers/AssemblyResolver.fs b/vsintegration/tests/FSharp.Editor.Tests/Helpers/AssemblyResolver.fs index 98db3e27df..9f5faafd7e 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/Helpers/AssemblyResolver.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/Helpers/AssemblyResolver.fs @@ -8,7 +8,7 @@ open System.Reflection module AssemblyResolver = open System.Globalization - open Microsoft.VisualStudio.FSharp.TestHelpers.VSInstallDiscovery + open FSharp.Test.Utilities.VSInstallDiscovery let vsInstallDir = // Use centralized VS installation discovery with graceful fallback diff --git a/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj b/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj index 1e806e423b..e1e657a651 100644 --- a/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj +++ b/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj @@ -34,7 +34,6 @@ - diff --git a/vsintegration/tests/Salsa/VsMocks.fs b/vsintegration/tests/Salsa/VsMocks.fs index ab8901fcb7..9caa86e9e1 100644 --- a/vsintegration/tests/Salsa/VsMocks.fs +++ b/vsintegration/tests/Salsa/VsMocks.fs @@ -1652,7 +1652,7 @@ module internal VsActual = let vsInstallDir = // Use centralized VS installation discovery with graceful fallback - match Microsoft.VisualStudio.FSharp.TestHelpers.VSInstallDiscovery.tryGetVSInstallDir () with + match FSharp.Test.Utilities.VSInstallDiscovery.tryGetVSInstallDir () with | Some dir -> dir | None -> // Fallback to legacy behavior for backward compatibility diff --git a/vsintegration/tests/TestHelpers/TestHelpers.fsproj b/vsintegration/tests/TestHelpers/TestHelpers.fsproj deleted file mode 100644 index 3e4836b535..0000000000 --- a/vsintegration/tests/TestHelpers/TestHelpers.fsproj +++ /dev/null @@ -1,33 +0,0 @@ - - - - Library - net472 - $(NoWarn);44;45;47;52;58;75;1204 - true - true - true - false - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vsintegration/tests/TestHelpers/VSInstallDiscoveryTests.fs b/vsintegration/tests/TestHelpers/VSInstallDiscoveryTests.fs deleted file mode 100644 index 10a505d228..0000000000 --- a/vsintegration/tests/TestHelpers/VSInstallDiscoveryTests.fs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -/// Simple test to verify VS installation discovery functionality -module Microsoft.VisualStudio.FSharp.TestHelpers.VSInstallDiscoveryTests - -open System -open System.IO - -/// Test basic discovery functionality -let testBasicDiscovery () = - printfn "Testing VS installation discovery..." - - // Test the discovery process - let result = VSInstallDiscovery.tryFindVSInstallation () - match result with - | VSInstallDiscovery.Found (path, source) -> - printfn $"✓ VS installation found at: {path}" - printfn $" Source: {source}" - - // Validate that the path looks reasonable - if Directory.Exists(path) && Directory.Exists(Path.Combine(path, "IDE")) then - printfn " ✓ Path validation passed" - else - printfn " ✗ Path validation failed - directory structure not as expected" - - | VSInstallDiscovery.NotFound reason -> - printfn $"✗ VS installation not found: {reason}" - printfn " This is expected if VS is not installed or environment variables are not set" - - // Test the optional version - let optPath = VSInstallDiscovery.tryGetVSInstallDir () - match optPath with - | Some path -> printfn $"✓ tryGetVSInstallDir returned: {path}" - | None -> printfn "✗ tryGetVSInstallDir returned None" - - // Test the logging version - let logMessages = ResizeArray() - let logger msg = logMessages.Add(msg) - let pathWithLogging = VSInstallDiscovery.getVSInstallDirWithLogging logger - - printfn "Logged messages:" - for msg in logMessages do - printfn $" LOG: {msg}" - - printfn "✓ Basic discovery test completed" - -/// Test environment variable scenarios -let testEnvironmentVariables () = - printfn "\nTesting environment variable scenarios..." - - // Save original values - let originalVS170 = Environment.GetEnvironmentVariable("VS170COMNTOOLS") - let originalVSAPP = Environment.GetEnvironmentVariable("VSAPPIDDIR") - let originalFSHARP = Environment.GetEnvironmentVariable("FSHARP_VS_INSTALL_DIR") - - try - // Test explicit override (highest priority) - Environment.SetEnvironmentVariable("FSHARP_VS_INSTALL_DIR", @"C:\TestPath") - Environment.SetEnvironmentVariable("VS170COMNTOOLS", @"C:\VS\Common7\Tools\") - - let result = VSInstallDiscovery.tryFindVSInstallation () - match result with - | VSInstallDiscovery.Found (path, source) when source.Contains("FSHARP_VS_INSTALL_DIR") -> - printfn "✓ FSHARP_VS_INSTALL_DIR override works correctly" - | _ -> - printfn "✗ FSHARP_VS_INSTALL_DIR override not working as expected" - - // Clear explicit override to test VS170COMNTOOLS - Environment.SetEnvironmentVariable("FSHARP_VS_INSTALL_DIR", null) - - printfn "✓ Environment variable scenario tests completed" - - finally - // Restore original values - Environment.SetEnvironmentVariable("VS170COMNTOOLS", originalVS170) - Environment.SetEnvironmentVariable("VSAPPIDDIR", originalVSAPP) - Environment.SetEnvironmentVariable("FSHARP_VS_INSTALL_DIR", originalFSHARP) - -/// Run all tests -let runTests () = - printfn "=== VS Installation Discovery Tests ===" - testBasicDiscovery () - testEnvironmentVariables () - printfn "=== Tests completed ===" \ No newline at end of file diff --git a/vsintegration/tests/UnitTests/AssemblyResolver.fs b/vsintegration/tests/UnitTests/AssemblyResolver.fs index 538fddb688..a2839358e5 100644 --- a/vsintegration/tests/UnitTests/AssemblyResolver.fs +++ b/vsintegration/tests/UnitTests/AssemblyResolver.fs @@ -6,7 +6,7 @@ open System.Reflection module AssemblyResolver = open System.Globalization - open Microsoft.VisualStudio.FSharp.TestHelpers.VSInstallDiscovery + open FSharp.Test.Utilities.VSInstallDiscovery let vsInstallDir = // Use centralized VS installation discovery with graceful fallback diff --git a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj index 256e52d6f1..96fde123dc 100644 --- a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj +++ b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj @@ -78,7 +78,6 @@ - From 478dc9038c494cb693d41e28dc97292ae1779c5f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Sep 2025 09:10:38 +0000 Subject: [PATCH 05/10] Fix namespace conflict and formatting issues Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com> --- tests/FSharp.Test.Utilities/VSInstallDiscovery.fs | 4 +++- .../tests/FSharp.Editor.Tests/Helpers/AssemblyResolver.fs | 4 ++-- vsintegration/tests/Salsa/VsMocks.fs | 2 +- vsintegration/tests/UnitTests/AssemblyResolver.fs | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs b/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs index 1233c7e4b7..5ceb041798 100644 --- a/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs +++ b/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs @@ -1,10 +1,12 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. +namespace FSharp.Test + /// Test-only Visual Studio installation discovery infrastructure. /// Provides a centralized, robust, and graceful discovery mechanism for Visual Studio installations /// used by integration/editor/unit tests under vsintegration/tests. [] -module FSharp.Test.Utilities.VSInstallDiscovery +module VSInstallDiscovery = open System open System.IO diff --git a/vsintegration/tests/FSharp.Editor.Tests/Helpers/AssemblyResolver.fs b/vsintegration/tests/FSharp.Editor.Tests/Helpers/AssemblyResolver.fs index 9f5faafd7e..78a5779351 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/Helpers/AssemblyResolver.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/Helpers/AssemblyResolver.fs @@ -8,13 +8,13 @@ open System.Reflection module AssemblyResolver = open System.Globalization - open FSharp.Test.Utilities.VSInstallDiscovery + open FSharp.Test.VSInstallDiscovery let vsInstallDir = // Use centralized VS installation discovery with graceful fallback match tryGetVSInstallDir () with | Some dir -> dir - | None -> + | None -> // Fallback to legacy behavior for backward compatibility let vsvar = let var = Environment.GetEnvironmentVariable("VS170COMNTOOLS") diff --git a/vsintegration/tests/Salsa/VsMocks.fs b/vsintegration/tests/Salsa/VsMocks.fs index 9caa86e9e1..6551206fde 100644 --- a/vsintegration/tests/Salsa/VsMocks.fs +++ b/vsintegration/tests/Salsa/VsMocks.fs @@ -1652,7 +1652,7 @@ module internal VsActual = let vsInstallDir = // Use centralized VS installation discovery with graceful fallback - match FSharp.Test.Utilities.VSInstallDiscovery.tryGetVSInstallDir () with + match FSharp.Test.VSInstallDiscovery.tryGetVSInstallDir () with | Some dir -> dir | None -> // Fallback to legacy behavior for backward compatibility diff --git a/vsintegration/tests/UnitTests/AssemblyResolver.fs b/vsintegration/tests/UnitTests/AssemblyResolver.fs index a2839358e5..38b5ee4529 100644 --- a/vsintegration/tests/UnitTests/AssemblyResolver.fs +++ b/vsintegration/tests/UnitTests/AssemblyResolver.fs @@ -6,7 +6,7 @@ open System.Reflection module AssemblyResolver = open System.Globalization - open FSharp.Test.Utilities.VSInstallDiscovery + open FSharp.Test.VSInstallDiscovery let vsInstallDir = // Use centralized VS installation discovery with graceful fallback From f35a2819b1b0af3b2986e8590d37a11c98718304 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Sep 2025 14:11:19 +0000 Subject: [PATCH 06/10] Fix indentation in VSInstallDiscovery module to resolve syntax errors Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com> --- .../VSInstallDiscovery.fs | 210 +++++++++--------- 1 file changed, 105 insertions(+), 105 deletions(-) diff --git a/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs b/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs index 5ceb041798..4c14435d4a 100644 --- a/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs +++ b/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs @@ -8,130 +8,130 @@ namespace FSharp.Test [] module VSInstallDiscovery = -open System -open System.IO -open System.Diagnostics + open System + open System.IO + open System.Diagnostics -/// Result of VS installation discovery -type VSInstallResult = - | Found of installPath: string * source: string - | NotFound of reason: string + /// Result of VS installation discovery + type VSInstallResult = + | Found of installPath: string * source: string + | NotFound of reason: string -/// Attempts to find a Visual Studio installation using multiple fallback strategies -let tryFindVSInstallation () : VSInstallResult = - - /// Check if a path exists and looks like a valid VS installation - let validateVSPath path = - if String.IsNullOrEmpty(path) then false - else - try - let fullPath = Path.GetFullPath(path) - Directory.Exists(fullPath) && - Directory.Exists(Path.Combine(fullPath, "IDE")) && - (File.Exists(Path.Combine(fullPath, "IDE", "devenv.exe")) || - File.Exists(Path.Combine(fullPath, "IDE", "VSIXInstaller.exe"))) - with - | _ -> false - - /// Strategy 1: VSAPPIDDIR (derive parent of Common7/IDE) - let tryVSAppIdDir () = - let envVar = Environment.GetEnvironmentVariable("VSAPPIDDIR") - if not (String.IsNullOrEmpty(envVar)) then - try - let parentPath = Path.Combine(envVar, "..") - if validateVSPath parentPath then - Some (Found (Path.GetFullPath(parentPath), "VSAPPIDDIR environment variable")) - else None - with - | _ -> None - else None - - /// Strategy 2: Highest version among VS*COMNTOOLS environment variables - let tryVSCommonTools () = - let vsVersions = [ - ("VS180COMNTOOLS", 18) // Visual Studio 2026 - ("VS170COMNTOOLS", 17) // Visual Studio 2022 - ("VS160COMNTOOLS", 16) // Visual Studio 2019 - ("VS150COMNTOOLS", 15) // Visual Studio 2017 - ("VS140COMNTOOLS", 14) // Visual Studio 2015 - ("VS120COMNTOOLS", 12) // Visual Studio 2013 - ] + /// Attempts to find a Visual Studio installation using multiple fallback strategies + let tryFindVSInstallation () : VSInstallResult = - vsVersions - |> List.tryPick (fun (envName, version) -> - let envVar = Environment.GetEnvironmentVariable(envName) + /// Check if a path exists and looks like a valid VS installation + let validateVSPath path = + if String.IsNullOrEmpty(path) then false + else + try + let fullPath = Path.GetFullPath(path) + Directory.Exists(fullPath) && + Directory.Exists(Path.Combine(fullPath, "IDE")) && + (File.Exists(Path.Combine(fullPath, "IDE", "devenv.exe")) || + File.Exists(Path.Combine(fullPath, "IDE", "VSIXInstaller.exe"))) + with + | _ -> false + + /// Strategy 1: VSAPPIDDIR (derive parent of Common7/IDE) + let tryVSAppIdDir () = + let envVar = Environment.GetEnvironmentVariable("VSAPPIDDIR") if not (String.IsNullOrEmpty(envVar)) then try let parentPath = Path.Combine(envVar, "..") if validateVSPath parentPath then - Some (Found (Path.GetFullPath(parentPath), $"{envName} environment variable (VS version {version})")) + Some (Found (Path.GetFullPath(parentPath), "VSAPPIDDIR environment variable")) else None with | _ -> None - else None) + else None - /// Strategy 3: vswhere.exe (Visual Studio Installer) - let tryVSWhere () = - try - let programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) - let vswherePath = Path.Combine(programFiles, "Microsoft Visual Studio", "Installer", "vswhere.exe") + /// Strategy 2: Highest version among VS*COMNTOOLS environment variables + let tryVSCommonTools () = + let vsVersions = [ + ("VS180COMNTOOLS", 18) // Visual Studio 2026 + ("VS170COMNTOOLS", 17) // Visual Studio 2022 + ("VS160COMNTOOLS", 16) // Visual Studio 2019 + ("VS150COMNTOOLS", 15) // Visual Studio 2017 + ("VS140COMNTOOLS", 14) // Visual Studio 2015 + ("VS120COMNTOOLS", 12) // Visual Studio 2013 + ] - if File.Exists(vswherePath) then - let startInfo = ProcessStartInfo( - FileName = vswherePath, - Arguments = "-latest -products * -requires Microsoft.Component.MSBuild -property installationPath", - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - CreateNoWindow = true - ) - - use proc = Process.Start(startInfo) - proc.WaitForExit(5000) |> ignore // 5 second timeout + vsVersions + |> List.tryPick (fun (envName, version) -> + let envVar = Environment.GetEnvironmentVariable(envName) + if not (String.IsNullOrEmpty(envVar)) then + try + let parentPath = Path.Combine(envVar, "..") + if validateVSPath parentPath then + Some (Found (Path.GetFullPath(parentPath), $"{envName} environment variable (VS version {version})")) + else None + with + | _ -> None + else None) + + /// Strategy 3: vswhere.exe (Visual Studio Installer) + let tryVSWhere () = + try + let programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) + let vswherePath = Path.Combine(programFiles, "Microsoft Visual Studio", "Installer", "vswhere.exe") - if proc.ExitCode = 0 then - let output = proc.StandardOutput.ReadToEnd().Trim() - if validateVSPath output then - Some (Found (Path.GetFullPath(output), "vswhere.exe discovery")) + if File.Exists(vswherePath) then + let startInfo = ProcessStartInfo( + FileName = vswherePath, + Arguments = "-latest -products * -requires Microsoft.Component.MSBuild -property installationPath", + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true + ) + + use proc = Process.Start(startInfo) + proc.WaitForExit(5000) |> ignore // 5 second timeout + + if proc.ExitCode = 0 then + let output = proc.StandardOutput.ReadToEnd().Trim() + if validateVSPath output then + Some (Found (Path.GetFullPath(output), "vswhere.exe discovery")) + else None else None else None - else None - with - | _ -> None + with + | _ -> None - // Try each strategy in order of precedence - match tryVSAppIdDir () with - | Some result -> result - | None -> - match tryVSCommonTools () with + // Try each strategy in order of precedence + match tryVSAppIdDir () with | Some result -> result | None -> - match tryVSWhere () with + match tryVSCommonTools () with | Some result -> result - | None -> NotFound "No Visual Studio installation found using any discovery method" + | None -> + match tryVSWhere () with + | Some result -> result + | None -> NotFound "No Visual Studio installation found using any discovery method" -/// Gets the VS installation directory, with graceful fallback behavior. -/// Returns None if no VS installation can be found, allowing callers to handle gracefully. -let tryGetVSInstallDir () : string option = - match tryFindVSInstallation () with - | Found (path, _) -> Some path - | NotFound _ -> None + /// Gets the VS installation directory, with graceful fallback behavior. + /// Returns None if no VS installation can be found, allowing callers to handle gracefully. + let tryGetVSInstallDir () : string option = + match tryFindVSInstallation () with + | Found (path, _) -> Some path + | NotFound _ -> None -/// Gets the VS installation directory with detailed logging. -/// Useful for debugging installation discovery issues in tests. -let getVSInstallDirWithLogging (logAction: string -> unit) : string option = - match tryFindVSInstallation () with - | Found (path, source) -> - logAction $"Visual Studio installation found at: {path} (via {source})" - Some path - | NotFound reason -> - logAction $"Visual Studio installation not found: {reason}" - None + /// Gets the VS installation directory with detailed logging. + /// Useful for debugging installation discovery issues in tests. + let getVSInstallDirWithLogging (logAction: string -> unit) : string option = + match tryFindVSInstallation () with + | Found (path, source) -> + logAction $"Visual Studio installation found at: {path} (via {source})" + Some path + | NotFound reason -> + logAction $"Visual Studio installation not found: {reason}" + None -/// Legacy compatibility function that maintains the old behavior of hard-failing. -/// Use this only for tests that must maintain the old behavior. -[] -let getVSInstallDirOrFail () : string = - match tryFindVSInstallation () with - | Found (path, _) -> path - | NotFound reason -> failwith $"VS170COMNTOOLS and VSAPPIDDIR environment variables not found. {reason}" \ No newline at end of file + /// Legacy compatibility function that maintains the old behavior of hard-failing. + /// Use this only for tests that must maintain the old behavior. + [] + let getVSInstallDirOrFail () : string = + match tryFindVSInstallation () with + | Found (path, _) -> path + | NotFound reason -> failwith $"VS170COMNTOOLS and VSAPPIDDIR environment variables not found. {reason}" \ No newline at end of file From 86ec73c6057b59d8be405781fe6fd7f03460a17e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Sep 2025 13:05:18 +0000 Subject: [PATCH 07/10] Fix FS1204 compiler error and missing project reference for Salsa Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com> --- tests/FSharp.Test.Utilities/VSInstallDiscovery.fs | 1 - vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs b/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs index 4c14435d4a..c61fd39cb6 100644 --- a/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs +++ b/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs @@ -5,7 +5,6 @@ namespace FSharp.Test /// Test-only Visual Studio installation discovery infrastructure. /// Provides a centralized, robust, and graceful discovery mechanism for Visual Studio installations /// used by integration/editor/unit tests under vsintegration/tests. -[] module VSInstallDiscovery = open System diff --git a/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj b/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj index e1e657a651..a27ab2aca1 100644 --- a/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj +++ b/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj @@ -34,6 +34,7 @@ + From 2e17a0657cd8e45d8af3fd5623995b43abe74d39 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Oct 2025 13:14:11 +0000 Subject: [PATCH 08/10] Revert Salsa project changes to avoid Microsoft.CodeAnalysis version conflicts Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com> --- .../FSharp.Test.Utilities.fsproj | 1 - .../tests/Salsa/VisualFSharp.Salsa.fsproj | 14 ++++++++++-- vsintegration/tests/Salsa/VsMocks.fs | 22 ++++++++----------- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj b/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj index da3b9a2ccd..7bc4f6e058 100644 --- a/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj +++ b/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj @@ -95,7 +95,6 @@ - diff --git a/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj b/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj index ca18bd89fc..e1e657a651 100644 --- a/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj +++ b/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj @@ -16,7 +16,7 @@ - + CompilerLocation.fs @@ -34,7 +34,6 @@ - @@ -52,11 +51,22 @@ + + + + + + + + + + + diff --git a/vsintegration/tests/Salsa/VsMocks.fs b/vsintegration/tests/Salsa/VsMocks.fs index 6551206fde..5189b7faec 100644 --- a/vsintegration/tests/Salsa/VsMocks.fs +++ b/vsintegration/tests/Salsa/VsMocks.fs @@ -1651,19 +1651,15 @@ module internal VsActual = member public _.JoinableTaskContext : JoinableTaskContext = jtc let vsInstallDir = - // Use centralized VS installation discovery with graceful fallback - match FSharp.Test.VSInstallDiscovery.tryGetVSInstallDir () with - | Some dir -> dir - | None -> - // Fallback to legacy behavior for backward compatibility - let vsvar = - let var = Environment.GetEnvironmentVariable("VS170COMNTOOLS") - if String.IsNullOrEmpty var then - Environment.GetEnvironmentVariable("VSAPPIDDIR") - else - var - if String.IsNullOrEmpty vsvar then failwith "VS170COMNTOOLS and VSAPPIDDIR environment variables not found." - Path.Combine(vsvar, "..") + // use the environment variable to find the VS installdir + let vsvar = + let var = Environment.GetEnvironmentVariable("VS170COMNTOOLS") + if String.IsNullOrEmpty var then + Environment.GetEnvironmentVariable("VSAPPIDDIR") + else + var + if String.IsNullOrEmpty vsvar then failwith "VS170COMNTOOLS and VSAPPIDDIR environment variables not found." + Path.Combine(vsvar, "..") let CreateEditorCatalog() = let thisAssembly = Assembly.GetExecutingAssembly().Location From 23f564a7c4c3277caf577f915835d57df3416553 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Oct 2025 13:54:53 +0000 Subject: [PATCH 09/10] Reduce Salsa project package references to match main branch Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com> --- vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj b/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj index e1e657a651..f741021443 100644 --- a/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj +++ b/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj @@ -51,22 +51,11 @@ - - - - - - - - - - - From 4354e4f42a7629635bcc21c85ed0450170da9735 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 6 Nov 2025 15:52:46 +0100 Subject: [PATCH 10/10] Apply suggestion from @T-Gro --- tests/FSharp.Test.Utilities/VSInstallDiscovery.fs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs b/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs index c61fd39cb6..e491ea329b 100644 --- a/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs +++ b/tests/FSharp.Test.Utilities/VSInstallDiscovery.fs @@ -126,11 +126,3 @@ module VSInstallDiscovery = | NotFound reason -> logAction $"Visual Studio installation not found: {reason}" None - - /// Legacy compatibility function that maintains the old behavior of hard-failing. - /// Use this only for tests that must maintain the old behavior. - [] - let getVSInstallDirOrFail () : string = - match tryFindVSInstallation () with - | Found (path, _) -> path - | NotFound reason -> failwith $"VS170COMNTOOLS and VSAPPIDDIR environment variables not found. {reason}" \ No newline at end of file