From b7af3750449f8279f5d0532337d65aed10cb68e9 Mon Sep 17 00:00:00 2001 From: Robin Neatherway Date: Thu, 13 Aug 2015 00:20:41 +0100 Subject: [PATCH 01/10] Implement simple path-based search for FSharp.Core --- FsAutoComplete.Tests/Tests.fs | 6 ++ FsAutoComplete/CompilerLocationUtils.fs | 81 ++++++++++++++++++++++--- FsAutoComplete/Utils.fs | 5 ++ 3 files changed, 84 insertions(+), 8 deletions(-) diff --git a/FsAutoComplete.Tests/Tests.fs b/FsAutoComplete.Tests/Tests.fs index 9c6a24cc7..e680d0d59 100644 --- a/FsAutoComplete.Tests/Tests.fs +++ b/FsAutoComplete.Tests/Tests.fs @@ -33,3 +33,9 @@ let ``normalCracking`` () = Assert.AreEqual(11,col) Assert.AreEqual(["First";"Second"],idents) Assert.AreEqual("First.Second.Third".[col], 'd') + +[] +let ``should find FSharp.Core`` () = + match DotNetEnvironment.fsharpCoreOpt with + | None -> Assert.Fail() + | Some fileName -> printfn "FSharp.Core found at '%s'" fileName; Assert.Pass() diff --git a/FsAutoComplete/CompilerLocationUtils.fs b/FsAutoComplete/CompilerLocationUtils.fs index aae331526..f4a84fcd0 100644 --- a/FsAutoComplete/CompilerLocationUtils.fs +++ b/FsAutoComplete/CompilerLocationUtils.fs @@ -11,12 +11,6 @@ open System.Text.RegularExpressions #nowarn "44" // ConfigurationSettings is obsolete but the new stuff is horribly complicated. -module Environment = - /// Are we running on the Mono platform? - let runningOnMono = - try System.Type.GetType("Mono.Runtime") <> null - with _ -> false - /// Target framework (used to find the right version of F# binaries) type FSharpTargetFramework = | NET_2_0 @@ -206,7 +200,7 @@ module FSharpEnvironment = let tryWindowsConfig (reqLangVersion: FSharpCompilerVersion) = //early termination on Mono, continuing here results in failed pinvokes and reg key failures ~18-35ms - if Environment.runningOnMono then None else + if Utils.runningOnMono then None else // On windows the location of the compiler is via a registry key let key20 = @"Software\Microsoft\.NETFramework\AssemblyFolders\Microsoft.FSharp-" + FSharpTeamVersionNumber let key40 = match reqLangVersion with @@ -302,7 +296,7 @@ module FSharpEnvironment = // the right FSharp.Core.dll. let result = //early termination on Mono, continuing here results in failed pinvokes and reg key failures ~18-35ms - if Environment.runningOnMono then None else + if Utils.runningOnMono then None else match reqLangVersion, targetFramework with | FSharp_2_0, x when (x = NET_2_0 || x = NET_3_0 || x = NET_3_5) -> tryRegKey @"Software\Microsoft\.NETFramework\v2.0.50727\AssemblyFoldersEx\Microsoft Visual F# 4.0" @@ -406,3 +400,74 @@ module FSharpEnvironment = | _ -> resolveAssembly dirs asm | [] -> None +module DotNetEnvironment = + let environVar v = Environment.GetEnvironmentVariable v + + let programFilesX86 = + let wow64 = environVar "PROCESSOR_ARCHITEW6432" + let globalArch = environVar "PROCESSOR_ARCHITECTURE" + match wow64, globalArch with + | "AMD64", "AMD64" + | null, "AMD64" + | "x86", "AMD64" -> environVar "ProgramFiles(x86)" + | _ -> environVar "ProgramFiles" + |> fun detected -> if detected = null then @"C:\Program Files (x86)\" else detected + + // Below code slightly modified from FAKE MSBuildHelper.fs + + let inline combinePaths path1 (path2 : string) = Path.Combine(path1, path2.TrimStart [| '\\'; '/' |]) + + let inline (@@) path1 path2 = combinePaths path1 path2 + + let tryFindFile dirs file = + let files = + dirs + |> Seq.map (fun (path : string) -> + let dir = new DirectoryInfo(path) + if not dir.Exists then "" + else + let fi = new FileInfo(dir.FullName @@ file) + if fi.Exists then fi.FullName + else "") + |> Seq.filter ((<>) "") + |> Seq.cache + if not (Seq.isEmpty files) then Some(Seq.head files) + else None + + let tryFindPath backupPaths tool = + let paths = Environment.GetEnvironmentVariable "PATH" + string Path.PathSeparator + backupPaths + let paths = paths.Split(Path.PathSeparator) + tryFindFile paths tool + + let findPath backupPaths tool = + match tryFindPath backupPaths tool with + | Some file -> file + | None -> tool + + let msBuildExe = + if Utils.runningOnMono then "xbuild" + else + let MSBuildPath = + (programFilesX86 @@ @"\MSBuild\14.0\Bin") + ";" + + (programFilesX86 @@ @"\MSBuild\12.0\Bin") + ";" + + (programFilesX86 @@ @"\MSBuild\12.0\Bin\amd64") + ";" + + @"c:\Windows\Microsoft.NET\Framework\v4.0.30319\;" + + @"c:\Windows\Microsoft.NET\Framework\v4.0.30128\;" + + @"c:\Windows\Microsoft.NET\Framework\v3.5\" + let ev = Environment.GetEnvironmentVariable "MSBuild" + if not (String.IsNullOrEmpty ev) then ev + else findPath MSBuildPath "MSBuild.exe" + + let fsharpCoreOpt = + if Utils.runningOnMono then + let mscorlibDir = Path.GetDirectoryName typeof.Assembly.Location + if List.forall File.Exists (List.map (combinePaths mscorlibDir) ["FSharp.Core.dll"; "FSharp.Core.optdata"; "FSharp.Core.sigdata"]) then + Some (mscorlibDir @@ "FSharp.Core.dll") + else + None + else + let referenceAssembliesPath = + programFilesX86 @@ @"Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\" + let fsharpCoreVersions = ["4.4.0.0"; "4.3.1.0"; "4.3.0.0"] + tryFindFile (List.map (combinePaths referenceAssembliesPath) fsharpCoreVersions) "FSharp.Core.dll" + diff --git a/FsAutoComplete/Utils.fs b/FsAutoComplete/Utils.fs index 396c6f9bd..47b572084 100644 --- a/FsAutoComplete/Utils.fs +++ b/FsAutoComplete/Utils.fs @@ -7,3 +7,8 @@ module Utils = let isAScript fileName = let ext = Path.GetExtension fileName [".fsx";".fsscript";".sketchfs"] |> List.exists ((=) ext) + + let runningOnMono = + try System.Type.GetType("Mono.Runtime") <> null + with _ -> false + From 4b584aa2db644e163bec8a9843d8072ec0355a69 Mon Sep 17 00:00:00 2001 From: Robin Neatherway Date: Thu, 13 Aug 2015 15:46:43 +0100 Subject: [PATCH 02/10] Replace FSharp.Core correctly with newest version Also improve compilerlocation command --- FsAutoComplete.Tests/Tests.fs | 12 + FsAutoComplete/CommandResponse.fs | 11 + FsAutoComplete/CompilerLocationUtils.fs | 417 +-------------------- FsAutoComplete/CompilerServiceInterface.fs | 20 +- FsAutoComplete/Program.fs | 6 +- FsAutoComplete/Utils.fs | 7 +- appveyor.yml | 3 + 7 files changed, 58 insertions(+), 418 deletions(-) diff --git a/FsAutoComplete.Tests/Tests.fs b/FsAutoComplete.Tests/Tests.fs index e680d0d59..478b82f9a 100644 --- a/FsAutoComplete.Tests/Tests.fs +++ b/FsAutoComplete.Tests/Tests.fs @@ -39,3 +39,15 @@ let ``should find FSharp.Core`` () = match DotNetEnvironment.fsharpCoreOpt with | None -> Assert.Fail() | Some fileName -> printfn "FSharp.Core found at '%s'" fileName; Assert.Pass() + +[] +let ``should find fsc on Windows`` () = + if not Utils.runningOnMono then + printfn "fsc.exe found at '%s'" DotNetEnvironment.fsc + Assert.That(DotNetEnvironment.fsc.Contains("Microsoft SDKs"), "fsc.exe resolution failed") + +[] +let ``should find msbuild on Windows`` () = + if not Utils.runningOnMono then + printfn "msbuild.exe found at '%s'" DotNetEnvironment.msBuildExe + Assert.That(DotNetEnvironment.msBuildExe.Length > "MSBuild.exe".Length, "MSBuild.exe resolution failed") diff --git a/FsAutoComplete/CommandResponse.fs b/FsAutoComplete/CommandResponse.fs index 05f69ef59..237efe8b9 100644 --- a/FsAutoComplete/CommandResponse.fs +++ b/FsAutoComplete/CommandResponse.fs @@ -124,6 +124,13 @@ module CommandResponse = Text: string } + type CompilerLocationResponse = + { + Fsc: string + Fsi: string + MSBuild: string + } + type FSharpErrorInfo = { FileName: string @@ -275,6 +282,10 @@ module CommandResponse = let toolTip(tip) = writeJson { Kind = "tooltip"; Data = TipFormatter.formatTip tip } + let compilerLocation fsc fsi msbuild = + let data = { Fsi = fsi; Fsc = fsc; MSBuild = msbuild } + writeJson { Kind = "compilerlocation"; Data = data } + let message(kind: string, data: 'a) = writeJson { Kind = kind; Data = data } diff --git a/FsAutoComplete/CompilerLocationUtils.fs b/FsAutoComplete/CompilerLocationUtils.fs index f4a84fcd0..8e093f024 100644 --- a/FsAutoComplete/CompilerLocationUtils.fs +++ b/FsAutoComplete/CompilerLocationUtils.fs @@ -1,414 +1,17 @@ namespace FsAutoComplete open System -open System.Diagnostics open System.IO -open System.Configuration -open System.Reflection -open Microsoft.Win32 -open System.Runtime.InteropServices -open System.Text.RegularExpressions - -#nowarn "44" // ConfigurationSettings is obsolete but the new stuff is horribly complicated. - -/// Target framework (used to find the right version of F# binaries) -type FSharpTargetFramework = - | NET_2_0 - | NET_3_0 - | NET_3_5 - | NET_4_0 - | NET_4_5 - -type FSharpCompilerVersion = - // F# 2.0 - | FSharp_2_0 - // F# 3.0 - | FSharp_3_0 - // F# 3.1 - | FSharp_3_1 - override x.ToString() = match x with | FSharp_2_0 -> "4.0.0.0" | FSharp_3_0 -> "4.3.0.0" | FSharp_3_1 -> "4.3.1.0" - /// The current requested language version can be overriden by the user using environment variable. - static member LatestKnown = - match System.Environment.GetEnvironmentVariable("FSHARP_PREFERRED_VERSION") with - | null -> FSharp_3_1 - | "4.0.0.0" -> FSharp_2_0 - | "4.3.0.0" -> FSharp_3_0 - | "4.3.1.0" -> FSharp_3_1 - | _ -> FSharp_3_1 - -module FSharpEnvironment = - - let fsharpVers = [ FSharp_3_1; FSharp_3_0; FSharp_2_0 ] - - let safeExists f = (try File.Exists(f) with _ -> false) - - let FSharpCoreLibRunningVersion = - try - match (typeof>).Assembly.GetName().Version.ToString() with - | null -> None - | "" -> None - | s -> Some(s) - with _ -> None - - // Returns: - // -- on 2.0: "v2.0.50727" - // -- on 4.0: "v4.0.30109" (last 5 digits vary by build) - let MSCorLibRunningRuntimeVersion = - typeof.Assembly.ImageRuntimeVersion - - // The F# team version number. This version number is used for - // - the F# version number reported by the fsc.exe and fsi.exe banners in the CTP release - // - the F# version number printed in the HTML documentation generator - // - the .NET DLL version number for all VS2008 DLLs - // - the VS2008 registry key, written by the VS2008 installer - // HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\AssemblyFolders\Microsoft.FSharp-" + FSharpTeamVersionNumber - // Also for Beta2, the language revision number indicated on the F# language spec - // - // It is NOT the version number listed on FSharp.Core.dll - let FSharpTeamVersionNumber = "2.0.0.0" - - // The F# binary format revision number. The first three digits of this form the significant part of the - // format revision number for F# binary signature and optimization metadata. The last digit is not significant. - // - // WARNING: Do not change this revision number unless you absolutely know what you're doing. - let FSharpBinaryMetadataFormatRevision = "2.0.0.0" - - [] - extern uint32 RegOpenKeyExW(UIntPtr _hKey, string _lpSubKey, uint32 _ulOptions, int _samDesired, UIntPtr & _phkResult); - - [] - extern uint32 RegQueryValueExW(UIntPtr _hKey, string _lpValueName, uint32 _lpReserved, uint32 & _lpType, IntPtr _lpData, int & _lpchData); - - [] - extern uint32 RegCloseKey(UIntPtr _hKey) - - module Option = - /// Convert string into Option string where null and String.Empty result in None - let ofString s = - if String.IsNullOrEmpty(s) then None - else Some(s) - - - // MaxPath accounts for the null-terminating character, for example, the maximum path on the D drive is "D:\<256 chars>\0". - // See: ndp\clr\src\BCL\System\IO\Path.cs - let maxPath = 260 - let maxDataLength = (new System.Text.UTF32Encoding()).GetMaxByteCount(maxPath) - let KEY_WOW64_DEFAULT = 0x0000 - let KEY_WOW64_32KEY = 0x0200 - let HKEY_LOCAL_MACHINE = UIntPtr(0x80000002u) - let KEY_QUERY_VALUE = 0x1 - let REG_SZ = 1u - - let GetDefaultRegistryStringValueViaDotNet(subKey: string) = - Option.ofString - (try - downcast Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\"+subKey,null,null) - with e-> - System.Diagnostics.Debug.Assert(false, sprintf "Failed in GetDefaultRegistryStringValueViaDotNet: %s" (e.ToString())) - null) - - let Get32BitRegistryStringValueViaPInvoke(subKey:string) = - Option.ofString - (try - // 64 bit flag is not available <= Win2k - let options = - match Environment.OSVersion.Version.Major with - | major when major >= 5 -> KEY_WOW64_32KEY - | _ -> KEY_WOW64_DEFAULT - - - let mutable hkey = UIntPtr.Zero; - let pathResult = Marshal.AllocCoTaskMem(maxDataLength); - - try - let res = RegOpenKeyExW(HKEY_LOCAL_MACHINE,subKey, 0u, KEY_QUERY_VALUE ||| options, & hkey) - if res = 0u then - let mutable uType = REG_SZ; - let mutable cbData = maxDataLength; - - let res = RegQueryValueExW(hkey, null, 0u, &uType, pathResult, &cbData); - - if (res = 0u && cbData > 0 && cbData <= maxDataLength) then - Marshal.PtrToStringUni(pathResult, (cbData - 2)/2); - else - null - else - null - finally - if hkey <> UIntPtr.Zero then - RegCloseKey(hkey) |> ignore - - if pathResult <> IntPtr.Zero then - Marshal.FreeCoTaskMem(pathResult) - with e-> - System.Diagnostics.Debug.Assert(false, sprintf "Failed in Get32BitRegistryStringValueViaPInvoke: %s" (e.ToString())) - null) - - let is32Bit = IntPtr.Size = 4 - - let tryRegKey(subKey:string) = - - if is32Bit then - let s = GetDefaultRegistryStringValueViaDotNet(subKey) - // If we got here AND we're on a 32-bit OS then we can validate that Get32BitRegistryStringValueViaPInvoke(...) works - // by comparing against the result from GetDefaultRegistryStringValueViaDotNet(...) -#if DEBUG - let viaPinvoke = Get32BitRegistryStringValueViaPInvoke(subKey) - System.Diagnostics.Debug.Assert((s = viaPinvoke), sprintf "32bit path: pi=%A def=%A" viaPinvoke s) -#endif - s - else - Get32BitRegistryStringValueViaPInvoke(subKey) - - let internal tryCurrentDomain() = - let pathFromCurrentDomain = System.AppDomain.CurrentDomain.BaseDirectory - if not(String.IsNullOrEmpty(pathFromCurrentDomain)) then - Some pathFromCurrentDomain - else - None - - let internal tryAppConfig (appConfigKey:string) = - - let locationFromAppConfig = ConfigurationSettings.AppSettings.[appConfigKey] - System.Diagnostics.Debug.Print(sprintf "Considering appConfigKey %s which has value '%s'" appConfigKey locationFromAppConfig) - - if String.IsNullOrEmpty(locationFromAppConfig) then - None - else - let exeAssemblyFolder = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) - let locationFromAppConfig = locationFromAppConfig.Replace("{exepath}", exeAssemblyFolder) - System.Diagnostics.Debug.Print(sprintf "Using path %s" locationFromAppConfig) - Some locationFromAppConfig - - /// Try to find the F# compiler location by looking at the "fsharpi" script installed by F# packages - let internal tryFsharpiScript(url:string) = - try - let str = File.ReadAllText(url) - let reg = new Regex("mono.* (\/.*)\/fsi\.exe") - let res = reg.Match(str) - if res.Success then Some(res.Groups.[1].Value) else None - with e -> - None - - let BackupInstallationProbePoints = - [ // prefer the latest installation of Mono on Mac - "/Library/Frameworks/Mono.framework/Versions/Current" - // prefer freshly built F# compilers on Linux - "/usr/local" - // otherwise look in the standard place - "/usr" ] - - let tryWindowsConfig (reqLangVersion: FSharpCompilerVersion) = - //early termination on Mono, continuing here results in failed pinvokes and reg key failures ~18-35ms - if Utils.runningOnMono then None else - // On windows the location of the compiler is via a registry key - let key20 = @"Software\Microsoft\.NETFramework\AssemblyFolders\Microsoft.FSharp-" + FSharpTeamVersionNumber - let key40 = match reqLangVersion with - | FSharp_2_0 -> @"Software\Microsoft\FSharp\2.0\Runtime\v4.0" - | FSharp_3_0 -> @"Software\Microsoft\FSharp\3.0\Runtime\v4.0" - | FSharp_3_1 -> @"Software\Microsoft\FSharp\3.1\Runtime\v4.0" - - let key1,key2 = match FSharpCoreLibRunningVersion with - | None -> key20,key40 - | Some v -> if v.Length > 1 && v.[0] <= '3' then key20,key40 - else key40,key20 - - Debug.WriteLine(sprintf "BinFolderOfDefaultFSharpCore: Probing registry key %s" key1) - let result = tryRegKey key1 - match result with - | Some _ -> result - | None -> Debug.WriteLine(sprintf "Resolution: BinFolderOfDefaultFSharpCore: Probing registry key %s" key2) - tryRegKey key2 - - let tryUnixConfig() = - // On Unix we let you set FSHARP_COMILER_BIN. I've rarely seen this used and its not documented in the install isntructions. - Debug.WriteLine(sprintf "Resolution: BinFolderOfDefaultFSharpCore: Probing environment variable FSHARP_COMPILER_BIN") - let result = - let var = System.Environment.GetEnvironmentVariable("FSHARP_COMPILER_BIN") - if String.IsNullOrEmpty(var) then None - else Some(var) - - match result with - | Some _ -> result - | None -> - - // On Unix we probe 'bin' under various hardwired paths for the scripts 'fsharpc' and 'fsharpi'. - // We then loko in the script to see the Mono location it is pointing to. - // This is pretty fragile, e.g. the script lookup is done via a regular expression. - // Really we should just search the path or otherwise resolve the 'mono' command? - BackupInstallationProbePoints - |> List.tryPick (fun x -> - Debug.WriteLine(sprintf "Resolution: BinFolderOfDefaultFSharpCore: Probing %s" x) - let file f = Path.Combine(Path.Combine(x,"bin"),f) - let exists f = safeExists(file f) - match (if exists "fsc" && exists "fsi" then tryFsharpiScript (file "fsi") else None) with - | Some res -> Some res - | None -> if exists "fsharpc" && exists "fsharpi" then tryFsharpiScript (file "fsharpi") - else None) - - - // The default location of FSharp.Core.dll and fsc.exe based on the version of fsc.exe that is running - // Used for - // - location of design-time copies of FSharp.Core.dll and FSharp.Compiler.Interactive.Settings.dll for the default assumed environment for scripts - // - default ToolPath in tasks in FSharp.Build.dll (for Fsc tasks) - // - default F# binaries directory in service.fs (REVIEW: check this) - // - default location of fsi.exe in FSharp.VS.FSI.dll - // - default location of fsc.exe in FSharp.Compiler.CodeDom.dll - let BinFolderOfDefaultFSharpCompiler(reqLangVersion: Option) = - - let getBinFolder(reqLangVersion: FSharpCompilerVersion) = - // Check for an app.config setting to redirect the default compiler location - // Like fsharp-compiler-location - try - // FSharp.Compiler support setting an appkey for compiler location. I've never seen this used. - Debug.WriteLine("Resolution:BinFolderOfDefaultFSharpCore: Probing app.config") - let result = tryAppConfig "fsharp-compiler-location" - match result with - | Some _ -> result - | None -> let result = tryWindowsConfig reqLangVersion - match result with - | Some _ -> result - | None -> let result = tryUnixConfig() - match result with - | Some _ -> result - | None -> None - with e -> - System.Diagnostics.Debug.Assert(false, "Error while determining default location of F# compiler") - Debug.WriteLine(sprintf "Resolution: BinFolderOfDefaultFSharpCore: error %s" (e.ToString())) - None - - match reqLangVersion with - | Some v -> getBinFolder v - | None -> List.tryPick getBinFolder fsharpVers - - let FolderOfDefaultFSharpCore(reqLangVersion:Option, targetFramework) = - - let getFolder reqLangVersion = - try - Debug.WriteLine(sprintf "Resolution: Determing folder of FSharp.Core for target framework '%A'" targetFramework) - let result = tryAppConfig "fsharp-core-location" - match result with - | Some _ -> result - | None -> - - // On Windows, look for the registry key giving the installation location of FSharp.Core.dll. - // This only works for .NET 2.0 - 4.0. To target Silverlight or Portable you'll need to use a direct reference to - // the right FSharp.Core.dll. - let result = - //early termination on Mono, continuing here results in failed pinvokes and reg key failures ~18-35ms - if Utils.runningOnMono then None else - match reqLangVersion, targetFramework with - | FSharp_2_0, x when (x = NET_2_0 || x = NET_3_0 || x = NET_3_5) -> - tryRegKey @"Software\Microsoft\.NETFramework\v2.0.50727\AssemblyFoldersEx\Microsoft Visual F# 4.0" - | FSharp_2_0, _ -> - tryRegKey @"Software\Microsoft\.NETFramework\v4.0.30319\AssemblyFoldersEx\Microsoft Visual F# 4.0" - | FSharp_3_0, x when (x = NET_2_0 || x = NET_3_0 || x = NET_3_5) -> - tryRegKey @"Software\Microsoft\.NETFramework\v2.0.50727\AssemblyFoldersEx\F# 3.0 Core Assemblies" - | FSharp_3_0, NET_4_0 -> - tryRegKey @"Software\Microsoft\.NETFramework\v4.0.30319\AssemblyFoldersEx\F# 3.0 Core Assemblies" - | FSharp_3_0, NET_4_5 -> - tryRegKey @"Software\Microsoft\.NETFramework\v4.5.50709\AssemblyFoldersEx\F# 3.0 Core Assemblies" - | FSharp_3_1, NET_4_5 -> - tryRegKey @"Software\Microsoft\.NETFramework\v4.5.50709\AssemblyFoldersEx\F# 3.1 Core Assemblies" - | _ -> None - - match result with - | Some _ -> result - | None -> - Debug.WriteLine(sprintf "Resolution: FSharp.Core: looking in environment variable") - let result = - let var = System.Environment.GetEnvironmentVariable("FSHARP_CORE_LOCATION") - if String.IsNullOrEmpty(var) then None - else Some(var) - match result with - | Some _ -> result - | None -> - let possibleInstallationPoints = - Option.toList (BinFolderOfDefaultFSharpCompiler(Some reqLangVersion) |> Option.map Path.GetDirectoryName) @ - BackupInstallationProbePoints - Debug.WriteLine(sprintf "Resolution: targetFramework = %A" targetFramework) - let ext = - match targetFramework with - | NET_2_0 | NET_3_0 | NET_3_5 -> "2.0" - | NET_4_0 -> "4.0" - | NET_4_5 -> "4.5" - - let safeExists f = (try File.Exists(f) with _ -> false) - let result = - possibleInstallationPoints |> List.tryPick (fun possibleInstallationDir -> - - Debug.WriteLine(sprintf "Resolution: Probing for %s/lib/mono/%s/FSharp.Core.dll" possibleInstallationDir ext) - let (++) s x = Path.Combine(s,x) - let candidate = possibleInstallationDir ++ "lib" ++ "mono" ++ ext - if safeExists (candidate ++ "FSharp.Core.dll") then - Some candidate - else - None) - - match result with - | Some _ -> result - | None -> - let result = - possibleInstallationPoints |> List.tryPick (fun possibleInstallationDir -> - - Debug.WriteLine(sprintf "Resolution: Probing %s/bin for fsc/fsi scripts or fsharpc/fsharpi scripts" possibleInstallationDir) - - let file f = Path.Combine(Path.Combine(possibleInstallationDir,"bin"),f) - let exists f = safeExists(file f) - match (if exists "fsc" && exists "fsi" then tryFsharpiScript (file "fsi") else None) with - | Some res -> Some res - | None -> - match (if exists "fsharpc" && exists "fsharpi" then tryFsharpiScript (file "fsharpi") else None) with - | Some res -> Some res - | None -> None) - - match result with - | Some _ -> result - | None -> None - - with e -> - System.Diagnostics.Debug.Assert(false, "Error while determining default location of F# compiler") - None - - match reqLangVersion with - | Some v -> getFolder v - | None -> List.tryPick getFolder fsharpVers - - /// Returns default directories to be used when searching for DLL files - let getDefaultDirectories(langVersion: Option<_>, fsTargetFramework) = - - let dir = - match langVersion with - | Some _ -> FolderOfDefaultFSharpCore(langVersion, fsTargetFramework) - | None -> List.tryPick (fun v -> FolderOfDefaultFSharpCore(Some v, fsTargetFramework)) fsharpVers - - // Return all known directories, get the location of the System DLLs - [ match dir with - | Some dir -> Debug.WriteLine(sprintf "Resolution: Using '%A' as the location of default FSharp.Core.dll" dir) - yield dir - | None -> Debug.WriteLine(sprintf "Resolution: Unable to find a default location for FSharp.Core.dll") - yield System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()] - - /// Resolve assembly in the specified list of directories - let rec resolveAssembly dirs asm = - match dirs with - | dir::dirs -> - let asmPath = Path.Combine(dir, asm) - let any = List.tryFind safeExists [ asmPath + ".dll" ] - match any with - | Some(file) -> Some(file) - | _ -> resolveAssembly dirs asm - | [] -> None module DotNetEnvironment = let environVar v = Environment.GetEnvironmentVariable v - let programFilesX86 = + let programFilesX86 = let wow64 = environVar "PROCESSOR_ARCHITEW6432" let globalArch = environVar "PROCESSOR_ARCHITECTURE" match wow64, globalArch with - | "AMD64", "AMD64" - | null, "AMD64" + | "AMD64", "AMD64" + | null, "AMD64" | "x86", "AMD64" -> environVar "ProgramFiles(x86)" | _ -> environVar "ProgramFiles" |> fun detected -> if detected = null then @"C:\Program Files (x86)\" else detected @@ -458,6 +61,20 @@ module DotNetEnvironment = if not (String.IsNullOrEmpty ev) then ev else findPath MSBuildPath "MSBuild.exe" + let fsharpInstallationPath = + List.tryFind (fun v -> Directory.Exists (programFilesX86 @@ @"\Microsoft SDKs\F#\" @@ v @@ "\Framework\v4.0")) + ["4.0"; "3.1"; "3.0"] + + let fsi = + if Utils.runningOnMono then "fsharpi" + else + Option.getOrElse "" fsharpInstallationPath @@ "fsi.exe" + + let fsc = + if Utils.runningOnMono then "fsharpc" + else + Option.getOrElse "" fsharpInstallationPath @@ "fsc.exe" + let fsharpCoreOpt = if Utils.runningOnMono then let mscorlibDir = Path.GetDirectoryName typeof.Assembly.Location diff --git a/FsAutoComplete/CompilerServiceInterface.fs b/FsAutoComplete/CompilerServiceInterface.fs index 55f9f0bae..47618b14c 100644 --- a/FsAutoComplete/CompilerServiceInterface.fs +++ b/FsAutoComplete/CompilerServiceInterface.fs @@ -103,23 +103,19 @@ type FSharpCompilerServiceChecker() = let checker = FSharpChecker.Instance do checker.BeforeBackgroundFileCheck.Add (fun _ -> ()) - let ensureFSharpCore (options: string[]) = - if options |> Seq.exists (fun s -> s.Contains("FSharp.Core.dll")) then options - else - let dirs = FSharpEnvironment.getDefaultDirectories (None, FSharpTargetFramework.NET_4_5 ) - [| yield! options - match FSharpEnvironment.resolveAssembly dirs "FSharp.Core" with - | Some fn -> yield sprintf "-r:%s" fn - | None -> - match FSharpEnvironment.resolveAssembly dirs "FSharp.Compiler.Interactive.Settings" with - | Some fn -> yield sprintf "-r:%s" fn - | None -> () |] + let ensureCorrectFSharpCore (options: string[]) = + DotNetEnvironment.fsharpCoreOpt + |> Option.map (fun path -> + let fsharpCoreRef = sprintf "-r:%s" path + [| yield fsharpCoreRef + yield! Seq.filter (fun (s: string) -> not (s.EndsWith("FSharp.Core.dll"))) options |]) + |> Option.getOrElse options member x.GetProjectOptionsFromScript(file, source) = let rawOptions = checker.GetProjectOptionsFromScript(file, source) |> Async.RunSynchronously { rawOptions - with OtherOptions = ensureFSharpCore rawOptions.OtherOptions } + with OtherOptions = ensureCorrectFSharpCore rawOptions.OtherOptions } member x.ParseAndCheckFileInProject(fileName, version, source, options) = checker.ParseAndCheckFileInProject(fileName, version, source, options) diff --git a/FsAutoComplete/Program.fs b/FsAutoComplete/Program.fs index 5be2082ce..f854886bd 100644 --- a/FsAutoComplete/Program.fs +++ b/FsAutoComplete/Program.fs @@ -234,11 +234,7 @@ module internal Main = main state | CompilerLocation -> - let locopt = FSharpEnvironment.BinFolderOfDefaultFSharpCompiler None - match locopt with - | None -> Response.error "Could not find compiler" - | Some loc -> Response.message("compilerlocation", loc) - + Response.compilerLocation DotNetEnvironment.fsc DotNetEnvironment.fsi DotNetEnvironment.msBuildExe main state | Error(msg) -> diff --git a/FsAutoComplete/Utils.fs b/FsAutoComplete/Utils.fs index 47b572084..4125056cb 100644 --- a/FsAutoComplete/Utils.fs +++ b/FsAutoComplete/Utils.fs @@ -10,5 +10,10 @@ module Utils = let runningOnMono = try System.Type.GetType("Mono.Runtime") <> null - with _ -> false + with _ -> false +module Option = + let getOrElse defaultValue option = + match option with + | None -> defaultValue + | Some x -> x diff --git a/appveyor.yml b/appveyor.yml index 765badd7f..ed9a095ef 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,3 +1,6 @@ +os: + - Windows Server 2012 + - Visual Studio 2015 matrix: fast_finish: true build_script: From 86938cabcc1c07e89c3f004c1b9fe126f169560c Mon Sep 17 00:00:00 2001 From: Robin Neatherway Date: Thu, 13 Aug 2015 15:59:38 +0100 Subject: [PATCH 03/10] Add FSharp.Core reference to projects without one --- FsAutoComplete/CompilerServiceInterface.fs | 8 +- .../NoFSharpCoreReference/FileTwo.fs | 14 ++++ .../NoFSharpCoreReference/Program.fs | 15 ++++ .../NoFSharpCoreReference/Runner.fsx | 21 ++++++ .../NoFSharpCoreReference/Script.fsx | 6 ++ .../NoFSharpCoreReference/Test1.fsproj | 73 +++++++++++++++++++ .../NoFSharpCoreReference/output.json | 18 +++++ 7 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 FsAutoComplete/test/integration/NoFSharpCoreReference/FileTwo.fs create mode 100644 FsAutoComplete/test/integration/NoFSharpCoreReference/Program.fs create mode 100644 FsAutoComplete/test/integration/NoFSharpCoreReference/Runner.fsx create mode 100644 FsAutoComplete/test/integration/NoFSharpCoreReference/Script.fsx create mode 100644 FsAutoComplete/test/integration/NoFSharpCoreReference/Test1.fsproj create mode 100644 FsAutoComplete/test/integration/NoFSharpCoreReference/output.json diff --git a/FsAutoComplete/CompilerServiceInterface.fs b/FsAutoComplete/CompilerServiceInterface.fs index 47618b14c..48ab89342 100644 --- a/FsAutoComplete/CompilerServiceInterface.fs +++ b/FsAutoComplete/CompilerServiceInterface.fs @@ -136,7 +136,11 @@ type FSharpCompilerServiceChecker() = else try let p = FSharpProjectFileInfo.Parse(file) - let args = p.Options |> Array.ofList + let args, references = + if not (Seq.exists (fun (s: string) -> s.Contains "FSharp.Core.dll") p.Options) then + ensureCorrectFSharpCore (Array.ofList p.Options), Option.toList DotNetEnvironment.fsharpCoreOpt @ p.References + else + Array.ofList p.Options, p.References let projectOptions = checker.GetProjectOptionsFromCommandLineArgs(file, args) let referencedProjectOptions = @@ -146,7 +150,7 @@ type FSharpCompilerServiceChecker() = let po = { projectOptions with ReferencedProjects = referencedProjectOptions } - Success (po, p.CompileFiles, p.OutputFile, p.References, p.FrameworkVersion) + Success (po, p.CompileFiles, p.OutputFile, references, p.FrameworkVersion) with e -> Failure e.Message diff --git a/FsAutoComplete/test/integration/NoFSharpCoreReference/FileTwo.fs b/FsAutoComplete/test/integration/NoFSharpCoreReference/FileTwo.fs new file mode 100644 index 000000000..105081bdb --- /dev/null +++ b/FsAutoComplete/test/integration/NoFSharpCoreReference/FileTwo.fs @@ -0,0 +1,14 @@ +module FileTwo + +type Foo = + | Bar + | Qux + +let addition x y = x + y + +let add x y = x + y + +type NewObjectType() = + + member x.Terrific (y : int) : int = + y diff --git a/FsAutoComplete/test/integration/NoFSharpCoreReference/Program.fs b/FsAutoComplete/test/integration/NoFSharpCoreReference/Program.fs new file mode 100644 index 000000000..60181db4e --- /dev/null +++ b/FsAutoComplete/test/integration/NoFSharpCoreReference/Program.fs @@ -0,0 +1,15 @@ +module X = + let func x = x + 1 + +let testval = FileTwo.NewObjectType() + +let val2 = X.func 2 + +let val3 = testval.Terrific val2 + +let val4 : FileTwo.NewObjectType = testval + +[] +let main args = + printfn "Hello %d" val2 + 0 diff --git a/FsAutoComplete/test/integration/NoFSharpCoreReference/Runner.fsx b/FsAutoComplete/test/integration/NoFSharpCoreReference/Runner.fsx new file mode 100644 index 000000000..a968c2974 --- /dev/null +++ b/FsAutoComplete/test/integration/NoFSharpCoreReference/Runner.fsx @@ -0,0 +1,21 @@ +#load "../TestHelpers.fsx" +open TestHelpers +open System.IO +open System + +(* + * This test is a simple sanity check of a basic run of the program. + * A few completions, files and script. + *) + +Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ +File.Delete "output.json" + +let p = new FsAutoCompleteWrapper() + + +p.project "Test1.fsproj" +p.send "quit\n" +p.finalOutput () +|> writeNormalizedOutput "output.json" + diff --git a/FsAutoComplete/test/integration/NoFSharpCoreReference/Script.fsx b/FsAutoComplete/test/integration/NoFSharpCoreReference/Script.fsx new file mode 100644 index 000000000..eea456da4 --- /dev/null +++ b/FsAutoComplete/test/integration/NoFSharpCoreReference/Script.fsx @@ -0,0 +1,6 @@ + + +module XA = + let funky x = x + 1 + +let val99 = XA.funky 21 diff --git a/FsAutoComplete/test/integration/NoFSharpCoreReference/Test1.fsproj b/FsAutoComplete/test/integration/NoFSharpCoreReference/Test1.fsproj new file mode 100644 index 000000000..b93ea970d --- /dev/null +++ b/FsAutoComplete/test/integration/NoFSharpCoreReference/Test1.fsproj @@ -0,0 +1,73 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {116cc2f9-f987-4b3d-915a-34cac04a73da} + Exe + Test1 + Test1 + Test1 + False + + + Program.fs + + + 4.3.0.0 + 11 + + + True + full + False + False + bin\Debug\ + DEBUG;TRACE + 3 + x86 + bin\Debug\Test1.XML + + + pdbonly + True + True + bin\Release\ + TRACE + 3 + x86 + bin\Release\Test1.XML + False + + + + + + + + + + + + + + $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets + + + + + + diff --git a/FsAutoComplete/test/integration/NoFSharpCoreReference/output.json b/FsAutoComplete/test/integration/NoFSharpCoreReference/output.json new file mode 100644 index 000000000..340edbe9c --- /dev/null +++ b/FsAutoComplete/test/integration/NoFSharpCoreReference/output.json @@ -0,0 +1,18 @@ +{ + "Kind": "project", + "Data": { + "Project": "/test/integration/NoFSharpCoreReference/Test1.fsproj", + "Files": [ + "/test/integration/NoFSharpCoreReference/FileTwo.fs", + "/test/integration/NoFSharpCoreReference/Program.fs" + ], + "Output": "/test/integration/NoFSharpCoreReference/bin/Debug/Test1.exe", + "References": [ + "/FSharp.Core.dll", + "/System.Core.dll", + "/System.dll", + "/mscorlib.dll" + ], + "Framework": "v4.0" + } +} From ceb139e17794dd47fa44844c8373182412ab04bc Mon Sep 17 00:00:00 2001 From: Robin Neatherway Date: Thu, 13 Aug 2015 17:06:34 +0100 Subject: [PATCH 04/10] Increase debug output --- FsAutoComplete/Program.fs | 6 +++++- appveyor.yml | 2 -- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/FsAutoComplete/Program.fs b/FsAutoComplete/Program.fs index f854886bd..63cd2032a 100644 --- a/FsAutoComplete/Program.fs +++ b/FsAutoComplete/Program.fs @@ -248,7 +248,11 @@ module internal Main = let msg = "Unexpected internal error. Please report at \ https://github.com/fsharp/FsAutoComplete/issues, \ attaching the following stack trace:\n" - + e.Message + e.StackTrace + + e.Message + "\n" + e.StackTrace + let msg = + if e.InnerException = null then msg + else msg + "\nCaused by:\n" + e.InnerException.Message + + "\n" + e.InnerException.StackTrace Response.error msg main state diff --git a/appveyor.yml b/appveyor.yml index ed9a095ef..4dbd8112f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,8 +1,6 @@ os: - Windows Server 2012 - Visual Studio 2015 -matrix: - fast_finish: true build_script: - cmd: build.cmd Test test: off From 109080d9c64d061cf341c684127f6ff9861b8c71 Mon Sep 17 00:00:00 2001 From: Robin Neatherway Date: Thu, 13 Aug 2015 17:30:00 +0100 Subject: [PATCH 05/10] Try Exception.ToString() --- FsAutoComplete/Program.fs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/FsAutoComplete/Program.fs b/FsAutoComplete/Program.fs index 63cd2032a..54c7e5c0b 100644 --- a/FsAutoComplete/Program.fs +++ b/FsAutoComplete/Program.fs @@ -247,12 +247,8 @@ module internal Main = with e -> let msg = "Unexpected internal error. Please report at \ https://github.com/fsharp/FsAutoComplete/issues, \ - attaching the following stack trace:\n" - + e.Message + "\n" + e.StackTrace - let msg = - if e.InnerException = null then msg - else msg + "\nCaused by:\n" + e.InnerException.Message - + "\n" + e.InnerException.StackTrace + attaching the exception information:\n" + + e.ToString() Response.error msg main state From 6b6baf4b376f3efb8108ec78698f8d9df45e01a5 Mon Sep 17 00:00:00 2001 From: Robin Neatherway Date: Thu, 13 Aug 2015 17:57:53 +0100 Subject: [PATCH 06/10] Make a path with backslashes a verbatim string --- FsAutoComplete/CompilerLocationUtils.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FsAutoComplete/CompilerLocationUtils.fs b/FsAutoComplete/CompilerLocationUtils.fs index 8e093f024..ce012b222 100644 --- a/FsAutoComplete/CompilerLocationUtils.fs +++ b/FsAutoComplete/CompilerLocationUtils.fs @@ -62,8 +62,8 @@ module DotNetEnvironment = else findPath MSBuildPath "MSBuild.exe" let fsharpInstallationPath = - List.tryFind (fun v -> Directory.Exists (programFilesX86 @@ @"\Microsoft SDKs\F#\" @@ v @@ "\Framework\v4.0")) - ["4.0"; "3.1"; "3.0"] + ["4.0"; "3.1"; "3.0"] + |> List.tryFind (fun v -> Directory.Exists (programFilesX86 @@ @"\Microsoft SDKs\F#\" @@ v @@ @"\Framework\v4.0")) let fsi = if Utils.runningOnMono then "fsharpi" From 61e03689e74545a3ac7ce6bdd1a648f9c58a2baf Mon Sep 17 00:00:00 2001 From: Robin Neatherway Date: Thu, 13 Aug 2015 18:34:11 +0100 Subject: [PATCH 07/10] Fix F# installation path --- FsAutoComplete/CompilerLocationUtils.fs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/FsAutoComplete/CompilerLocationUtils.fs b/FsAutoComplete/CompilerLocationUtils.fs index ce012b222..5657b7a2e 100644 --- a/FsAutoComplete/CompilerLocationUtils.fs +++ b/FsAutoComplete/CompilerLocationUtils.fs @@ -63,7 +63,8 @@ module DotNetEnvironment = let fsharpInstallationPath = ["4.0"; "3.1"; "3.0"] - |> List.tryFind (fun v -> Directory.Exists (programFilesX86 @@ @"\Microsoft SDKs\F#\" @@ v @@ @"\Framework\v4.0")) + |> List.map (fun v -> programFilesX86 @@ @"\Microsoft SDKs\F#\" @@ v @@ @"\Framework\v4.0") + |> List.tryFind Directory.Exists let fsi = if Utils.runningOnMono then "fsharpi" From f07536fee0e1cb25f09fed3f5336f08393e6135e Mon Sep 17 00:00:00 2001 From: Robin Neatherway Date: Thu, 13 Aug 2015 23:50:03 +0100 Subject: [PATCH 08/10] Tidying up --- FsAutoComplete.Tests/Tests.fs | 10 +++++----- FsAutoComplete/CompilerServiceInterface.fs | 4 ++-- FsAutoComplete/Debug.fs | 6 ++++-- ...ompilerLocationUtils.fs => Environment.fs} | 20 +++++++++---------- FsAutoComplete/FsAutoComplete.fsproj | 5 ++--- FsAutoComplete/Program.fs | 2 +- FsAutoComplete/Utils.fs | 4 ++++ 7 files changed, 28 insertions(+), 23 deletions(-) rename FsAutoComplete/{CompilerLocationUtils.fs => Environment.fs} (86%) diff --git a/FsAutoComplete.Tests/Tests.fs b/FsAutoComplete.Tests/Tests.fs index 478b82f9a..b74d7a5eb 100644 --- a/FsAutoComplete.Tests/Tests.fs +++ b/FsAutoComplete.Tests/Tests.fs @@ -36,18 +36,18 @@ let ``normalCracking`` () = [] let ``should find FSharp.Core`` () = - match DotNetEnvironment.fsharpCoreOpt with + match Environment.fsharpCoreOpt with | None -> Assert.Fail() | Some fileName -> printfn "FSharp.Core found at '%s'" fileName; Assert.Pass() [] let ``should find fsc on Windows`` () = if not Utils.runningOnMono then - printfn "fsc.exe found at '%s'" DotNetEnvironment.fsc - Assert.That(DotNetEnvironment.fsc.Contains("Microsoft SDKs"), "fsc.exe resolution failed") + printfn "fsc.exe found at '%s'" Environment.fsc + Assert.That(Environment.fsc.Contains("Microsoft SDKs"), "fsc.exe resolution failed") [] let ``should find msbuild on Windows`` () = if not Utils.runningOnMono then - printfn "msbuild.exe found at '%s'" DotNetEnvironment.msBuildExe - Assert.That(DotNetEnvironment.msBuildExe.Length > "MSBuild.exe".Length, "MSBuild.exe resolution failed") + printfn "msbuild.exe found at '%s'" Environment.msbuild + Assert.That(Environment.msbuild.Length > "MSBuild.exe".Length, "MSBuild.exe resolution failed") diff --git a/FsAutoComplete/CompilerServiceInterface.fs b/FsAutoComplete/CompilerServiceInterface.fs index 48ab89342..5ec69af91 100644 --- a/FsAutoComplete/CompilerServiceInterface.fs +++ b/FsAutoComplete/CompilerServiceInterface.fs @@ -104,7 +104,7 @@ type FSharpCompilerServiceChecker() = do checker.BeforeBackgroundFileCheck.Add (fun _ -> ()) let ensureCorrectFSharpCore (options: string[]) = - DotNetEnvironment.fsharpCoreOpt + Environment.fsharpCoreOpt |> Option.map (fun path -> let fsharpCoreRef = sprintf "-r:%s" path [| yield fsharpCoreRef @@ -138,7 +138,7 @@ type FSharpCompilerServiceChecker() = let p = FSharpProjectFileInfo.Parse(file) let args, references = if not (Seq.exists (fun (s: string) -> s.Contains "FSharp.Core.dll") p.Options) then - ensureCorrectFSharpCore (Array.ofList p.Options), Option.toList DotNetEnvironment.fsharpCoreOpt @ p.References + ensureCorrectFSharpCore (Array.ofList p.Options), Option.toList Environment.fsharpCoreOpt @ p.References else Array.ofList p.Options, p.References diff --git a/FsAutoComplete/Debug.fs b/FsAutoComplete/Debug.fs index c6089f950..3afba8869 100644 --- a/FsAutoComplete/Debug.fs +++ b/FsAutoComplete/Debug.fs @@ -1,7 +1,9 @@ // -------------------------------------------------------------------------------------- // (c) Robin Neatherway // -------------------------------------------------------------------------------------- -module Debug +namespace FsAutoComplete + +module Debug = let verbose = ref false let categories : Ref>> = @@ -49,4 +51,4 @@ module Debug let inline flush () = if !verbose then - (!output).Flush() \ No newline at end of file + (!output).Flush() diff --git a/FsAutoComplete/CompilerLocationUtils.fs b/FsAutoComplete/Environment.fs similarity index 86% rename from FsAutoComplete/CompilerLocationUtils.fs rename to FsAutoComplete/Environment.fs index 5657b7a2e..6d3d95f38 100644 --- a/FsAutoComplete/CompilerLocationUtils.fs +++ b/FsAutoComplete/Environment.fs @@ -3,10 +3,10 @@ namespace FsAutoComplete open System open System.IO -module DotNetEnvironment = - let environVar v = Environment.GetEnvironmentVariable v +module Environment = + let private environVar v = Environment.GetEnvironmentVariable v - let programFilesX86 = + let private programFilesX86 = let wow64 = environVar "PROCESSOR_ARCHITEW6432" let globalArch = environVar "PROCESSOR_ARCHITECTURE" match wow64, globalArch with @@ -18,11 +18,11 @@ module DotNetEnvironment = // Below code slightly modified from FAKE MSBuildHelper.fs - let inline combinePaths path1 (path2 : string) = Path.Combine(path1, path2.TrimStart [| '\\'; '/' |]) + let inline private combinePaths path1 (path2 : string) = Path.Combine(path1, path2.TrimStart [| '\\'; '/' |]) - let inline (@@) path1 path2 = combinePaths path1 path2 + let inline private (@@) path1 path2 = combinePaths path1 path2 - let tryFindFile dirs file = + let private tryFindFile dirs file = let files = dirs |> Seq.map (fun (path : string) -> @@ -37,17 +37,17 @@ module DotNetEnvironment = if not (Seq.isEmpty files) then Some(Seq.head files) else None - let tryFindPath backupPaths tool = + let private tryFindPath backupPaths tool = let paths = Environment.GetEnvironmentVariable "PATH" + string Path.PathSeparator + backupPaths let paths = paths.Split(Path.PathSeparator) tryFindFile paths tool - let findPath backupPaths tool = + let private findPath backupPaths tool = match tryFindPath backupPaths tool with | Some file -> file | None -> tool - let msBuildExe = + let msbuild = if Utils.runningOnMono then "xbuild" else let MSBuildPath = @@ -61,7 +61,7 @@ module DotNetEnvironment = if not (String.IsNullOrEmpty ev) then ev else findPath MSBuildPath "MSBuild.exe" - let fsharpInstallationPath = + let private fsharpInstallationPath = ["4.0"; "3.1"; "3.0"] |> List.map (fun v -> programFilesX86 @@ @"\Microsoft SDKs\F#\" @@ v @@ @"\Framework\v4.0") |> List.tryFind Directory.Exists diff --git a/FsAutoComplete/FsAutoComplete.fsproj b/FsAutoComplete/FsAutoComplete.fsproj index 7dc04f151..ad07706fd 100644 --- a/FsAutoComplete/FsAutoComplete.fsproj +++ b/FsAutoComplete/FsAutoComplete.fsproj @@ -56,15 +56,14 @@ --> - - + + - diff --git a/FsAutoComplete/Program.fs b/FsAutoComplete/Program.fs index 54c7e5c0b..49da909cc 100644 --- a/FsAutoComplete/Program.fs +++ b/FsAutoComplete/Program.fs @@ -234,7 +234,7 @@ module internal Main = main state | CompilerLocation -> - Response.compilerLocation DotNetEnvironment.fsc DotNetEnvironment.fsi DotNetEnvironment.msBuildExe + Response.compilerLocation Environment.fsc Environment.fsi Environment.msbuild main state | Error(msg) -> diff --git a/FsAutoComplete/Utils.fs b/FsAutoComplete/Utils.fs index 4125056cb..753e5b894 100644 --- a/FsAutoComplete/Utils.fs +++ b/FsAutoComplete/Utils.fs @@ -2,6 +2,10 @@ namespace FsAutoComplete open System.IO +type Result<'a> = + | Success of 'a + | Failure of string + module Utils = let isAScript fileName = From 69cc868ac600ab01e3f3e1aadc898f47b4d74f54 Mon Sep 17 00:00:00 2001 From: Robin Neatherway Date: Fri, 14 Aug 2015 08:01:25 +0100 Subject: [PATCH 09/10] prod appveyor --- FsAutoComplete.Tests/Tests.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FsAutoComplete.Tests/Tests.fs b/FsAutoComplete.Tests/Tests.fs index b74d7a5eb..a8f693dc1 100644 --- a/FsAutoComplete.Tests/Tests.fs +++ b/FsAutoComplete.Tests/Tests.fs @@ -49,5 +49,5 @@ let ``should find fsc on Windows`` () = [] let ``should find msbuild on Windows`` () = if not Utils.runningOnMono then - printfn "msbuild.exe found at '%s'" Environment.msbuild + printfn "msbuild.exe found at '%s'" Environment.msbuild Assert.That(Environment.msbuild.Length > "MSBuild.exe".Length, "MSBuild.exe resolution failed") From 27cef0d8ac243dc978b2195566921d72934f93e6 Mon Sep 17 00:00:00 2001 From: Robin Neatherway Date: Fri, 14 Aug 2015 09:35:12 +0100 Subject: [PATCH 10/10] Remove test debug output --- FsAutoComplete.Tests/Tests.fs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/FsAutoComplete.Tests/Tests.fs b/FsAutoComplete.Tests/Tests.fs index a8f693dc1..e18db7777 100644 --- a/FsAutoComplete.Tests/Tests.fs +++ b/FsAutoComplete.Tests/Tests.fs @@ -36,18 +36,14 @@ let ``normalCracking`` () = [] let ``should find FSharp.Core`` () = - match Environment.fsharpCoreOpt with - | None -> Assert.Fail() - | Some fileName -> printfn "FSharp.Core found at '%s'" fileName; Assert.Pass() + Assert.That(Option.isSome Environment.fsharpCoreOpt, "FSharp.Core.dll resolution failed") [] let ``should find fsc on Windows`` () = if not Utils.runningOnMono then - printfn "fsc.exe found at '%s'" Environment.fsc Assert.That(Environment.fsc.Contains("Microsoft SDKs"), "fsc.exe resolution failed") [] let ``should find msbuild on Windows`` () = if not Utils.runningOnMono then - printfn "msbuild.exe found at '%s'" Environment.msbuild Assert.That(Environment.msbuild.Length > "MSBuild.exe".Length, "MSBuild.exe resolution failed")