From b7a3bf87971ef3d4aacdd94f269f0ab5c5b78e0f Mon Sep 17 00:00:00 2001 From: Will Smith Date: Mon, 20 Jan 2020 06:45:10 -0800 Subject: [PATCH 01/14] Remove Finalize on obj holder for RawByteMemory (#8237) * Remove Finalize on obj holder for RawByteMemory as memory mapped files use a safe handler. * Removed Finalize from SafeUnamanagedMemoryStream as it is an impl detail for viewing RawByteMemory as a stream * Remove new * Update bytes.fs --- src/absil/bytes.fs | 58 +++++++++++++-------------------------------- src/absil/bytes.fsi | 2 +- 2 files changed, 18 insertions(+), 42 deletions(-) diff --git a/src/absil/bytes.fs b/src/absil/bytes.fs index 89556fc9683..24159a728ca 100644 --- a/src/absil/bytes.fs +++ b/src/absil/bytes.fs @@ -120,34 +120,29 @@ type ByteArrayMemory(bytes: byte[], offset, length) = type SafeUnmanagedMemoryStream = inherit UnmanagedMemoryStream - val mutable private hold: obj + val mutable private holder: obj val mutable private isDisposed: bool - new (addr, length, hold) = + new (addr, length, holder) = { inherit UnmanagedMemoryStream(addr, length) - hold = hold + holder = holder isDisposed = false } - new (addr: nativeptr, length: int64, capacity: int64, access: FileAccess, hold) = + new (addr: nativeptr, length: int64, capacity: int64, access: FileAccess, holder) = { inherit UnmanagedMemoryStream(addr, length, capacity, access) - hold = hold + holder = holder isDisposed = false } - override x.Finalize() = - x.Dispose false - override x.Dispose disposing = base.Dispose disposing - if not x.isDisposed then - x.hold <- null // Null out so it can be collected. - x.isDisposed <- true + x.holder <- null // Null out so it can be collected. [] -type RawByteMemory(addr: nativeptr, length: int, hold: obj) = +type RawByteMemory(addr: nativeptr, length: int, holder: obj) = inherit ByteMemory () let check i = @@ -159,7 +154,7 @@ type RawByteMemory(addr: nativeptr, length: int, hold: obj) = raise (ArgumentOutOfRangeException("length")) override _.Item - with get i = + with get i = check i NativePtr.add addr i |> NativePtr.read @@ -174,7 +169,7 @@ type RawByteMemory(addr: nativeptr, length: int, hold: obj) = check (pos + count - 1) System.Text.Encoding.UTF8.GetString(NativePtr.add addr pos, count) - override _.ReadBytes(pos, count) = + override _.ReadBytes(pos, count) = check pos check (pos + count - 1) let res = Bytes.zeroCreate count @@ -194,7 +189,7 @@ type RawByteMemory(addr: nativeptr, length: int, hold: obj) = override _.Slice(pos, count) = check pos check (pos + count - 1) - RawByteMemory(NativePtr.add addr pos, count, hold) :> ByteMemory + RawByteMemory(NativePtr.add addr pos, count, holder) :> ByteMemory override x.CopyTo stream = use stream2 = x.AsStream() @@ -210,10 +205,10 @@ type RawByteMemory(addr: nativeptr, length: int, hold: obj) = res override _.AsStream() = - new SafeUnmanagedMemoryStream(addr, int64 length, hold) :> Stream + new SafeUnmanagedMemoryStream(addr, int64 length, holder) :> Stream override _.AsReadOnlyStream() = - new SafeUnmanagedMemoryStream(addr, int64 length, int64 length, FileAccess.Read, hold) :> Stream + new SafeUnmanagedMemoryStream(addr, int64 length, int64 length, FileAccess.Read, holder) :> Stream [] type ReadOnlyByteMemory(bytes: ByteMemory) = @@ -259,17 +254,7 @@ type ByteMemory with mmf let accessor = mmf.CreateViewAccessor(0L, length, MemoryMappedFileAccess.ReadWrite) - - let safeHolder = - { new obj() with - override x.Finalize() = - (x :?> IDisposable).Dispose() - interface IDisposable with - member x.Dispose() = - GC.SuppressFinalize x - accessor.Dispose() - mmf.Dispose() } - RawByteMemory.FromUnsafePointer(accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, safeHolder) + RawByteMemory.FromUnsafePointer(accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, (mmf, accessor)) static member FromFile(path, access, ?canShadowCopy: bool) = let canShadowCopy = defaultArg canShadowCopy false @@ -313,19 +298,10 @@ type ByteMemory with | FileAccess.ReadWrite when not accessor.CanRead || not accessor.CanWrite -> invalidOp "Cannot read or write file" | _ -> () - let safeHolder = - { new obj() with - override x.Finalize() = - (x :?> IDisposable).Dispose() - interface IDisposable with - member x.Dispose() = - GC.SuppressFinalize x - accessor.Dispose() - mmf.Dispose() } - RawByteMemory.FromUnsafePointer(accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, safeHolder) - - static member FromUnsafePointer(addr, length, hold: obj) = - RawByteMemory(NativePtr.ofNativeInt addr, length, hold) :> ByteMemory + RawByteMemory.FromUnsafePointer(accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), int length, (mmf, accessor)) + + static member FromUnsafePointer(addr, length, holder: obj) = + RawByteMemory(NativePtr.ofNativeInt addr, length, holder) :> ByteMemory static member FromArray(bytes, offset, length) = ByteArrayMemory(bytes, offset, length) :> ByteMemory diff --git a/src/absil/bytes.fsi b/src/absil/bytes.fsi index 11e7c9f58cc..46b30b6c5a4 100644 --- a/src/absil/bytes.fsi +++ b/src/absil/bytes.fsi @@ -95,7 +95,7 @@ type ByteMemory with /// Creates a ByteMemory object that is backed by a raw pointer. /// Use with care. - static member FromUnsafePointer: addr: nativeint * length: int * hold: obj -> ByteMemory + static member FromUnsafePointer: addr: nativeint * length: int * holder: obj -> ByteMemory /// Creates a ByteMemory object that is backed by a byte array with the specified offset and length. static member FromArray: bytes: byte[] * offset: int * length: int -> ByteMemory From e20fc26d0b68a540fd91286e2d8881c73164e991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Cie=C5=9Blak?= Date: Mon, 20 Jan 2020 15:53:43 +0100 Subject: [PATCH 02/14] Remove project cracker (#8288) * Remove ProjectCracker project * Remove Project Cracker tests * Remove ProjectCracker docs --- ...arp.Compiler.Service.ProjectCracker.fsproj | 33 - .../ProjectCracker.fs | 127 ---- .../App.config | 22 - ...rp.Compiler.Service.ProjectCracker.targets | 7 - ...Compiler.Service.ProjectCrackerTool.fsproj | 25 - .../Program.fs | 46 -- .../ProjectCrackerOptions.fs | 11 - .../ProjectCrackerTool.fs | 471 -------------- .../FSharp.Compiler.Service.Tests.fsproj | 7 - fcs/FSharp.Compiler.Service.sln | 38 +- fcs/README.md | 10 +- fcs/docsrc/content/devnotes.md | 2 +- fcs/docsrc/content/project.fsx | 56 -- tests/service/ExprTests.fs | 312 ---------- tests/service/MultiProjectAnalysisTests.fs | 2 - tests/service/ProjectOptionsTests.fs | 578 ------------------ .../LanguageServiceProfiling.fsproj | 1 - .../ProjectCracker.fs | 2 - .../UnitTests/VisualFSharp.UnitTests.fsproj | 4 - 19 files changed, 15 insertions(+), 1739 deletions(-) delete mode 100644 fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj delete mode 100644 fcs/FSharp.Compiler.Service.ProjectCracker/ProjectCracker.fs delete mode 100644 fcs/FSharp.Compiler.Service.ProjectCrackerTool/App.config delete mode 100644 fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCracker.targets delete mode 100644 fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj delete mode 100644 fcs/FSharp.Compiler.Service.ProjectCrackerTool/Program.fs delete mode 100644 fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerOptions.fs delete mode 100644 fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerTool.fs delete mode 100644 tests/service/ProjectOptionsTests.fs delete mode 100644 vsintegration/Utils/LanguageServiceProfiling/ProjectCracker.fs diff --git a/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj b/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj deleted file mode 100644 index b12fa10ee5b..00000000000 --- a/fcs/FSharp.Compiler.Service.ProjectCracker/FSharp.Compiler.Service.ProjectCracker.fsproj +++ /dev/null @@ -1,33 +0,0 @@ - - - - $(FcsTargetNetFxFramework) - true - - - Legacy project file cracker for the F# compiler service. - Legacy project file cracker for the F# compiler service. - false - Microsoft Corporation; F# community contributors - https://github.com/fsharp/FSharp.Compiler.Service/blob/master/LICENSE - https://github.com/fsharp/FSharp.Compiler.Service - logo.png - F#, compiler, msbuild - - - - - ProjectCrackerOptions.fs - - - - - - - - - - - - - \ No newline at end of file diff --git a/fcs/FSharp.Compiler.Service.ProjectCracker/ProjectCracker.fs b/fcs/FSharp.Compiler.Service.ProjectCracker/ProjectCracker.fs deleted file mode 100644 index 3a096cb5660..00000000000 --- a/fcs/FSharp.Compiler.Service.ProjectCracker/ProjectCracker.fs +++ /dev/null @@ -1,127 +0,0 @@ -namespace FSharp.Compiler.SourceCodeServices - -#if !NETSTANDARD -open System.Runtime.Serialization.Json -#endif -open System.Text -open System.IO -open System - -module Utils = - - let Convert loadedTimeStamp (originalOpts: ProjectCrackerTool.ProjectOptions) = - let logMap = ref Map.empty - - let rec convertProject (opts: ProjectCrackerTool.ProjectOptions) = - if not (isNull opts.Error) then failwith opts.Error - - let referencedProjects() = Array.map (fun (a, b) -> a,convertProject b) opts.ReferencedProjectOptions - - let sourceFiles, otherOptions = - opts.Options - |> Array.partition (fun x -> - let extension = Path.GetExtension(x).ToLower() - x.IndexOfAny(Path.GetInvalidPathChars()) = -1 - && (extension = ".fs" || extension = ".fsi")) - - let sepChar = Path.DirectorySeparatorChar - - let sourceFiles = sourceFiles |> Array.map (fun x -> - match sepChar with - | '\\' -> x.Replace('/', '\\') - | '/' -> x.Replace('\\', '/') - | _ -> x - ) - - logMap := Map.add opts.ProjectFile opts.LogOutput !logMap - { ProjectFileName = opts.ProjectFile - ProjectId = None - SourceFiles = sourceFiles - OtherOptions = otherOptions - ReferencedProjects = referencedProjects() - IsIncompleteTypeCheckEnvironment = false - UseScriptResolutionRules = false - LoadTime = loadedTimeStamp - UnresolvedReferences = None - OriginalLoadReferences = [] - ExtraProjectInfo = None - Stamp = None } - - convertProject originalOpts, !logMap - -type ProjectCracker = - - static member GetProjectOptionsFromProjectFileLogged(projectFileName : string, ?properties : (string * string) list, ?loadedTimeStamp, ?enableLogging) = - let loadedTimeStamp = defaultArg loadedTimeStamp DateTime.MaxValue // Not 'now', we don't want to force reloading - let properties = defaultArg properties [] - let enableLogging = defaultArg enableLogging true - - -#if NETSTANDARD - let arguments = [| - yield projectFileName - yield enableLogging.ToString() - for k, v in properties do - yield k - yield v - |] - - let ret, opts = FSharp.Compiler.SourceCodeServices.ProjectCrackerTool.ProjectCrackerTool.crackOpen arguments - ignore ret -#else - let arguments = new StringBuilder() - arguments.Append('"').Append(projectFileName).Append('"') |> ignore - arguments.Append(' ').Append(enableLogging.ToString()) |> ignore - for k, v in properties do - arguments.Append(' ').Append(k).Append(' ').Append(v) |> ignore - let codebase = Path.GetDirectoryName(Uri(typeof.Assembly.CodeBase).LocalPath) - - let crackerFilename = Path.Combine(codebase,"FSharp.Compiler.Service.ProjectCrackerTool.exe") - if not (File.Exists crackerFilename) then - failwithf "ProjectCracker exe not found at: %s it must be next to the ProjectCracker dll." crackerFilename - - let p = new System.Diagnostics.Process() - - p.StartInfo.FileName <- crackerFilename - p.StartInfo.Arguments <- arguments.ToString() - p.StartInfo.UseShellExecute <- false - p.StartInfo.CreateNoWindow <- true - p.StartInfo.RedirectStandardOutput <- true - p.StartInfo.RedirectStandardError <- true - - let sbOut = StringBuilder() - let sbErr = StringBuilder() - - p.ErrorDataReceived.AddHandler(fun _ a -> sbErr.AppendLine a.Data |> ignore) - p.OutputDataReceived.AddHandler(fun _ a -> sbOut.AppendLine a.Data |> ignore) - - ignore <| p.Start() - - p.EnableRaisingEvents <- true - p.BeginOutputReadLine() - p.BeginErrorReadLine() - - p.WaitForExit() - - let crackerOut = sbOut.ToString() - let crackerErr = sbErr.ToString() - - let opts = - try - let ser = new DataContractJsonSerializer(typeof) - let stringBytes = Encoding.Unicode.GetBytes crackerOut - use ms = new MemoryStream(stringBytes) - ser.ReadObject(ms) :?> ProjectCrackerTool.ProjectOptions - with - exn -> - raise (Exception(sprintf "error parsing ProjectCrackerTool output, stdoutput was:\n%s\n\nstderr was:\n%s" crackerOut crackerErr, exn)) -#endif - - Utils.Convert loadedTimeStamp opts - - static member GetProjectOptionsFromProjectFile(projectFileName : string, ?properties : (string * string) list, ?loadedTimeStamp) = - fst (ProjectCracker.GetProjectOptionsFromProjectFileLogged( - projectFileName, - ?properties=properties, - ?loadedTimeStamp=loadedTimeStamp, - enableLogging=false)) diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/App.config b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/App.config deleted file mode 100644 index fdab151af22..00000000000 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/App.config +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCracker.targets b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCracker.targets deleted file mode 100644 index ed01293adaf..00000000000 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCracker.targets +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj deleted file mode 100644 index 19789a96299..00000000000 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - Exe - $(FcsTargetNetFxFramework) - true - $(DefineConstants);CROSS_PLATFORM_COMPILER - $(DefineConstants);ENABLE_MONO_SUPPORT - $(OtherFlags) --staticlink:FSharp.Core - true - false - - - - - - - - - - - - - - diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/Program.fs b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/Program.fs deleted file mode 100644 index 5cc3fc8b1eb..00000000000 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/Program.fs +++ /dev/null @@ -1,46 +0,0 @@ -namespace FSharp.Compiler.SourceCodeServices.ProjectCrackerTool - -open System -open System.Reflection -open System.Runtime.Serialization.Json - -module Program = - -#if !NETCOREAPP - let addMSBuildv14BackupResolution () = - let onResolveEvent = new ResolveEventHandler(fun sender evArgs -> - let requestedAssembly = AssemblyName(evArgs.Name) - if requestedAssembly.Name.StartsWith("Microsoft.Build", StringComparison.Ordinal) && - not (requestedAssembly.Name.EndsWith(".resources", StringComparison.Ordinal)) && - not (requestedAssembly.Version.ToString().Contains("12.0.0.0")) - then - // If the version of MSBuild that we're using wasn't present on the machine, then - // just revert back to 12.0.0.0 since that's normally installed as part of the .NET - // Framework. - requestedAssembly.Version <- Version("12.0.0.0") - Assembly.Load requestedAssembly - else - null) - AppDomain.CurrentDomain.add_AssemblyResolve(onResolveEvent) -#endif - - let crackAndSendOutput asText argv = - let ret, opts = ProjectCrackerTool.crackOpen argv - - if asText then - printfn "%A" opts - else - let ser = new DataContractJsonSerializer(typeof) - ser.WriteObject(Console.OpenStandardOutput(), opts) - ret - - - [][] - let main argv = - let asText = Array.exists (fun (s: string) -> s = "--text") argv - let argv = Array.filter (fun (s: string) -> s <> "--text") argv - -#if !NETCOREAPP - addMSBuildv14BackupResolution () -#endif - crackAndSendOutput asText argv diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerOptions.fs b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerOptions.fs deleted file mode 100644 index a48bdc25aa7..00000000000 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerOptions.fs +++ /dev/null @@ -1,11 +0,0 @@ -namespace FSharp.Compiler.SourceCodeServices.ProjectCrackerTool - -[] -type ProjectOptions = - { - ProjectFile: string - Options: string[] - ReferencedProjectOptions: (string * ProjectOptions)[] - LogOutput: string - Error: string - } diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerTool.fs b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerTool.fs deleted file mode 100644 index 0f2d4ad056e..00000000000 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerTool.fs +++ /dev/null @@ -1,471 +0,0 @@ -namespace FSharp.Compiler.SourceCodeServices.ProjectCrackerTool - -open System -open System.IO -open System.Text -open Microsoft.Build.Framework -open Microsoft.Build.Utilities - -module internal ProjectCrackerTool = - open System.Collections.Generic - - let runningOnMono = -#if NETCOREAPP - false -#else - try match System.Type.GetType("Mono.Runtime") with null -> false | _ -> true - with e -> false -#endif - - type internal BasicStringLogger() = - inherit Logger() - - let sb = new StringBuilder() - - let log (e: BuildEventArgs) = - sb.Append(e.Message) |> ignore - sb.AppendLine() |> ignore - - override x.Initialize(eventSource:IEventSource) = - sb.Clear() |> ignore - eventSource.AnyEventRaised.Add(log) - - member x.Log = sb.ToString() - - type internal HostCompile() = - member th.Compile(_:obj, _:obj, _:obj) = 0 - interface ITaskHost - - let vs = - let programFiles = - let getEnv v = - let result = System.Environment.GetEnvironmentVariable(v) - match result with - | null -> None - | _ -> Some result - - match List.tryPick getEnv [ "ProgramFiles(x86)"; "ProgramFiles" ] with - | Some r -> r - | None -> "C:\\Program Files (x86)" - - let vsVersions = ["14.0"; "12.0"] - let msbuildBin v = IO.Path.Combine(programFiles, "MSBuild", v, "Bin", "MSBuild.exe") - List.tryFind (fun v -> IO.File.Exists(msbuildBin v)) vsVersions - - let mkAbsolute dir v = - if Path.IsPathRooted v then v - else Path.Combine(dir, v) - - let mkAbsoluteOpt dir v = Option.map (mkAbsolute dir) v - - let CrackProjectUsingNewBuildAPI fsprojFile properties logOpt = - let fsprojFullPath = try Path.GetFullPath(fsprojFile) with _ -> fsprojFile - let fsprojAbsDirectory = Path.GetDirectoryName fsprojFullPath - - use _pwd = - let dir = Directory.GetCurrentDirectory() - Directory.SetCurrentDirectory(fsprojAbsDirectory) - { new System.IDisposable with - member x.Dispose() = Directory.SetCurrentDirectory(dir) } - use engine = new Microsoft.Build.Evaluation.ProjectCollection() - let host = new HostCompile() - - engine.HostServices.RegisterHostObject(fsprojFullPath, "CoreCompile", "Fsc", host) - - let projectInstanceFromFullPath (fsprojFullPath: string) = - use file = new FileStream(fsprojFullPath, FileMode.Open, FileAccess.Read, FileShare.Read) - use stream = new StreamReader(file) - use xmlReader = System.Xml.XmlReader.Create(stream) - - let project = - try - engine.LoadProject(xmlReader, FullPath=fsprojFullPath) - with - | exn -> - let tools = engine.Toolsets |> Seq.map (fun x -> x.ToolsPath) |> Seq.toList - raise (new Exception(sprintf "Could not load project %s in ProjectCollection. Available tools: %A. Message: %s" fsprojFullPath tools exn.Message)) - - project.SetGlobalProperty("BuildingInsideVisualStudio", "true") |> ignore - if not (List.exists (fun (p,_) -> p = "VisualStudioVersion") properties) then - match vs with - | Some version -> project.SetGlobalProperty("VisualStudioVersion", version) |> ignore - | None -> () - project.SetGlobalProperty("ShouldUnsetParentConfigurationAndPlatform", "false") |> ignore - for (prop, value) in properties do - project.SetGlobalProperty(prop, value) |> ignore - - project.CreateProjectInstance() - - let project = projectInstanceFromFullPath fsprojFullPath - let directory = project.Directory - - let getprop (p: Microsoft.Build.Execution.ProjectInstance) s = - let v = p.GetPropertyValue s - if String.IsNullOrWhiteSpace v then None - else Some v - - let outFileOpt = getprop project "TargetPath" - - let log = match logOpt with - | None -> [] - | Some l -> [l :> ILogger] - - project.Build([| "Build" |], log) |> ignore - - let getItems s = [ for f in project.GetItems(s) -> mkAbsolute directory f.EvaluatedInclude ] - - let projectReferences = - [ for cp in project.GetItems("ProjectReference") do - yield cp.GetMetadataValue("FullPath") - ] - - let references = - [ for i in project.GetItems("ReferencePath") do - yield i.EvaluatedInclude - for i in project.GetItems("ChildProjectReferences") do - yield i.EvaluatedInclude ] - - outFileOpt, directory, getItems, references, projectReferences, getprop project, project.FullPath - -#if !NETCOREAPP - let CrackProjectUsingOldBuildAPI (fsprojFile:string) properties logOpt = - let engine = new Microsoft.Build.BuildEngine.Engine() - Option.iter (fun l -> engine.RegisterLogger(l)) logOpt - - let bpg = Microsoft.Build.BuildEngine.BuildPropertyGroup() - - bpg.SetProperty("BuildingInsideVisualStudio", "true") - for (prop, value) in properties do - bpg.SetProperty(prop, value) - - engine.GlobalProperties <- bpg - - let projectFromFile (fsprojFile:string) = - // We seem to need to pass 12.0/4.0 in here for some unknown reason - let project = new Microsoft.Build.BuildEngine.Project(engine, engine.DefaultToolsVersion) - do project.Load(fsprojFile) - project - - let project = projectFromFile fsprojFile - project.Build([| "ResolveReferences" |]) |> ignore - let directory = Path.GetDirectoryName project.FullFileName - - let getProp (p: Microsoft.Build.BuildEngine.Project) s = - let v = p.GetEvaluatedProperty s - if String.IsNullOrWhiteSpace v then None - else Some v - - let outFileOpt = - match mkAbsoluteOpt directory (getProp project "OutDir") with - | None -> None - | Some d -> mkAbsoluteOpt d (getProp project "TargetFileName") - - let getItems s = - let fs = project.GetEvaluatedItemsByName(s) - [ for f in fs -> mkAbsolute directory f.FinalItemSpec ] - - let projectReferences = - [ for i in project.GetEvaluatedItemsByName("ProjectReference") do - yield mkAbsolute directory i.FinalItemSpec - ] - - let references = - [ for i in project.GetEvaluatedItemsByName("ReferencePath") do - yield i.FinalItemSpec - for i in project.GetEvaluatedItemsByName("ChildProjectReferences") do - yield i.FinalItemSpec ] - // Duplicate slashes sometimes appear in the output here, which prevents - // them from matching keys used in FSharpProjectOptions.ReferencedProjects - |> List.map (fun (s: string) -> s.Replace("//","/")) - - outFileOpt, directory, getItems, references, projectReferences, getProp project, project.FullFileName - -#endif - - //---------------------------------------------------------------------------- - // FSharpProjectFileInfo - // - [] - type FSharpProjectFileInfo (fsprojFileName:string, ?properties, ?enableLogging) = - let properties = defaultArg properties [] - let enableLogging = defaultArg enableLogging false - - let logOpt = - if enableLogging then - let log = new BasicStringLogger() - do log.Verbosity <- Microsoft.Build.Framework.LoggerVerbosity.Diagnostic - Some log - else - None - - let outFileOpt, directory, getItems, references, projectReferences, getProp, fsprojFullPath = - try -#if NETCOREAPP - CrackProjectUsingNewBuildAPI fsprojFileName properties logOpt - with -#else - if runningOnMono then - CrackProjectUsingOldBuildAPI fsprojFileName properties logOpt - else - CrackProjectUsingNewBuildAPI fsprojFileName properties logOpt - with - | :? Microsoft.Build.BuildEngine.InvalidProjectFileException as e -> - raise (Microsoft.Build.Exceptions.InvalidProjectFileException( - e.ProjectFile, - e.LineNumber, - e.ColumnNumber, - e.EndLineNumber, - e.EndColumnNumber, - e.Message, - e.ErrorSubcategory, - e.ErrorCode, - e.HelpKeyword)) -#endif - | :? ArgumentException as e -> raise (IO.FileNotFoundException(e.Message)) - - let logOutput = match logOpt with None -> "" | Some l -> l.Log - let pages = getItems "Page" - let embeddedResources = getItems "EmbeddedResource" - let files = getItems "Compile" - let resources = getItems "Resource" - let noaction = getItems "None" - let content = getItems "Content" - - let split (s : string option) (cs : char []) = - match s with - | None -> [||] - | Some s -> - if String.IsNullOrWhiteSpace s then [||] - else s.Split(cs, StringSplitOptions.RemoveEmptyEntries) - - let getbool (s : string option) = - match s with - | None -> false - | Some s -> - match (Boolean.TryParse s) with - | (true, result) -> result - | (false, _) -> false - - let fxVer = getProp "TargetFrameworkVersion" - let optimize = getProp "Optimize" |> getbool - let assemblyNameOpt = getProp "AssemblyName" - let tailcalls = getProp "Tailcalls" |> getbool - let outputPathOpt = getProp "OutputPath" - let docFileOpt = getProp "DocumentationFile" - let outputTypeOpt = getProp "OutputType" - let debugTypeOpt = getProp "DebugType" - let baseAddressOpt = getProp "BaseAddress" - let sigFileOpt = getProp "GenerateSignatureFile" - let keyFileOpt = getProp "KeyFile" - let pdbFileOpt = getProp "PdbFile" - let platformOpt = getProp "Platform" - let targetTypeOpt = getProp "TargetType" - let versionFileOpt = getProp "VersionFile" - let targetProfileOpt = getProp "TargetProfile" - let warnLevelOpt = getProp "Warn" - let subsystemVersionOpt = getProp "SubsystemVersion" - let win32ResOpt = getProp "Win32ResourceFile" - let heOpt = getProp "HighEntropyVA" |> getbool - let win32ManifestOpt = getProp "Win32ManifestFile" - let debugSymbols = getProp "DebugSymbols" |> getbool - let prefer32bit = getProp "Prefer32Bit" |> getbool - let warnAsError = getProp "TreatWarningsAsErrors" |> getbool - let defines = split (getProp "DefineConstants") [| ';'; ','; ' ' |] - let nowarn = split (getProp "NoWarn") [| ';'; ','; ' ' |] - let warningsAsError = split (getProp "WarningsAsErrors") [| ';'; ','; ' ' |] - let libPaths = split (getProp "ReferencePath") [| ';'; ',' |] - let otherFlags = split (getProp "OtherFlags") [| ' ' |] - let isLib = (outputTypeOpt = Some "Library") - - let docFileOpt = - match docFileOpt with - | None -> None - | Some docFile -> Some(mkAbsolute directory docFile) - - - let options = - [ yield "--simpleresolution" - yield "--noframework" - match outFileOpt with - | None -> () - | Some outFile -> yield "--out:" + outFile - match docFileOpt with - | None -> () - | Some docFile -> yield "--doc:" + docFile - match baseAddressOpt with - | None -> () - | Some baseAddress -> yield "--baseaddress:" + baseAddress - match keyFileOpt with - | None -> () - | Some keyFile -> yield "--keyfile:" + keyFile - match sigFileOpt with - | None -> () - | Some sigFile -> yield "--sig:" + sigFile - match pdbFileOpt with - | None -> () - | Some pdbFile -> yield "--pdb:" + pdbFile - match versionFileOpt with - | None -> () - | Some versionFile -> yield "--versionfile:" + versionFile - match warnLevelOpt with - | None -> () - | Some warnLevel -> yield "--warn:" + warnLevel - match subsystemVersionOpt with - | None -> () - | Some s -> yield "--subsystemversion:" + s - if heOpt then yield "--highentropyva+" - match win32ResOpt with - | None -> () - | Some win32Res -> yield "--win32res:" + win32Res - match win32ManifestOpt with - | None -> () - | Some win32Manifest -> yield "--win32manifest:" + win32Manifest - match targetProfileOpt with - | None -> () - | Some targetProfile -> yield "--targetprofile:" + targetProfile - yield "--fullpaths" - yield "--flaterrors" - if warnAsError then yield "--warnaserror" - yield - if isLib then "--target:library" - else "--target:exe" - for symbol in defines do - if not (String.IsNullOrWhiteSpace symbol) then yield "--define:" + symbol - for nw in nowarn do - if not (String.IsNullOrWhiteSpace nw) then yield "--nowarn:" + nw - for nw in warningsAsError do - if not (String.IsNullOrWhiteSpace nw) then yield "--warnaserror:" + nw - yield if debugSymbols then "--debug+" - else "--debug-" - yield if optimize then "--optimize+" - else "--optimize-" - yield if tailcalls then "--tailcalls+" - else "--tailcalls-" - match debugTypeOpt with - | None -> () - | Some debugType -> - match debugType.ToUpperInvariant() with - | "NONE" -> () - | "PDBONLY" -> yield "--debug:pdbonly" - | "FULL" -> yield "--debug:full" - | _ -> () - match platformOpt |> Option.map (fun o -> o.ToUpperInvariant()), prefer32bit, - targetTypeOpt |> Option.map (fun o -> o.ToUpperInvariant()) with - | Some "ANYCPU", true, Some "EXE" | Some "ANYCPU", true, Some "WINEXE" -> yield "--platform:anycpu32bitpreferred" - | Some "ANYCPU", _, _ -> yield "--platform:anycpu" - | Some "X86", _, _ -> yield "--platform:x86" - | Some "X64", _, _ -> yield "--platform:x64" - | Some "ITANIUM", _, _ -> yield "--platform:Itanium" - | _ -> () - match targetTypeOpt |> Option.map (fun o -> o.ToUpperInvariant()) with - | Some "LIBRARY" -> yield "--target:library" - | Some "EXE" -> yield "--target:exe" - | Some "WINEXE" -> yield "--target:winexe" - | Some "MODULE" -> yield "--target:module" - | _ -> () - yield! otherFlags - for f in resources do - yield "--resource:" + f - for i in libPaths do - yield "--lib:" + mkAbsolute directory i - for r in references do - yield "-r:" + r - yield! files ] - - member x.Options = options - member x.FrameworkVersion = fxVer - member x.ProjectReferences = projectReferences - member x.References = references - member x.CompileFiles = files - member x.ResourceFiles = resources - member x.EmbeddedResourceFiles = embeddedResources - member x.ContentFiles = content - member x.OtherFiles = noaction - member x.PageFiles = pages - member x.OutputFile = outFileOpt - member x.Directory = directory - member x.AssemblyName = assemblyNameOpt - member x.OutputPath = outputPathOpt - member x.FullPath = fsprojFullPath - member x.LogOutput = logOutput - static member Parse(fsprojFileName:string, ?properties, ?enableLogging) = new FSharpProjectFileInfo(fsprojFileName, ?properties=properties, ?enableLogging=enableLogging) - - let getOptions file enableLogging properties = - let cache = new Dictionary<_,_>() - let rec getOptions file : Option * ProjectOptions = - match cache.TryGetValue file with - | true, option -> option - | _ -> - let parsedProject = FSharpProjectFileInfo.Parse(file, properties=properties, enableLogging=enableLogging) - - let referencedProjectOptions = - [| for file in parsedProject.ProjectReferences do - if Path.GetExtension(file) = ".fsproj" then - match getOptions file with - | Some outFile, opts -> yield outFile, opts - | None, _ -> () |] - - // Workaround for Mono 4.2, which doesn't populate the subproject - // details anymore outside of a solution context. See https://github.com/mono/mono/commit/76c6a08e730393927b6851709cdae1d397cbcc3a#diff-59afd196a55d61d5d1eaaef7bd49d1e5 - // and some explanation from the author at https://github.com/fsharp/FSharp.Compiler.Service/pull/455#issuecomment-154103963 - // - // In particular we want the output path, which we can get from - // fully parsing that project itself. We also have to specially parse - // C# referenced projects, as we don't look at them otherwise. - let referencedProjectOutputs = - if runningOnMono then - [ yield! Array.map (fun (s,_) -> "-r:" + s) referencedProjectOptions - for file in parsedProject.ProjectReferences do - let ext = Path.GetExtension(file) - if ext = ".csproj" || ext = ".vbproj" then - let parsedProject = FSharpProjectFileInfo.Parse(file, properties=properties, enableLogging=false) - match parsedProject.OutputFile with - | None -> () - | Some f -> yield "-r:" + f ] - else - [] - - // On some versions of Mono the referenced projects are already - // correctly included, so we make sure not to introduce duplicates - |> List.filter (fun r -> not (Set.contains r (set parsedProject.Options))) - - let options = { ProjectFile = file - Options = Array.ofSeq (parsedProject.Options @ referencedProjectOutputs) - ReferencedProjectOptions = referencedProjectOptions - LogOutput = parsedProject.LogOutput - Error = null } - - let result = parsedProject.OutputFile, options - cache.Add(file,result) - result - - snd (getOptions file) - - - let rec pairs l = - match l with - | [] | [_] -> [] - | x::y::rest -> (x,y) :: pairs rest - - let crackOpen (argv: string[])= - if argv.Length >= 2 then - let projectFile = argv.[0] - let enableLogging = match Boolean.TryParse(argv.[1]) with - | true, true -> true - | _ -> false - try - let props = pairs (List.ofArray argv.[2..]) - let opts = getOptions argv.[0] enableLogging props - 0, opts - with e -> - 2, { ProjectFile = projectFile; - Options = [||]; - ReferencedProjectOptions = [||]; - LogOutput = e.ToString() + " StackTrace: " + e.StackTrace - Error = e.Message + " StackTrace: " + e.StackTrace } - else - 1, { ProjectFile = ""; - Options = [||]; - ReferencedProjectOptions = [||]; - LogOutput = "At least two arguments required." - Error = null } diff --git a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index 0c32c068af2..072e2e0a589 100644 --- a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -11,9 +11,6 @@ true true - - $(DefineConstants);NO_PROJECTCRACKER - FsUnit.fs @@ -51,9 +48,6 @@ CSharpProjectAnalysis.fs - - ProjectOptionsTests.fs - StructureTests.fs @@ -100,6 +94,5 @@ - \ No newline at end of file diff --git a/fcs/FSharp.Compiler.Service.sln b/fcs/FSharp.Compiler.Service.sln index 192f8bd6242..af0ed390cb1 100644 --- a/fcs/FSharp.Compiler.Service.sln +++ b/fcs/FSharp.Compiler.Service.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26730.16 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29418.71 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "project", "project", "{B6B68AE6-E7A4-4D43-9B34-FFA74BFE192B}" ProjectSection(SolutionItems) = preProject @@ -9,7 +9,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "project", "project", "{B6B6 build.sh = build.sh nuget\FSharp.Compiler.Service.MSBuild.v12.nuspec = nuget\FSharp.Compiler.Service.MSBuild.v12.nuspec nuget\FSharp.Compiler.Service.nuspec = nuget\FSharp.Compiler.Service.nuspec - nuget\FSharp.Compiler.Service.ProjectCracker.nuspec = nuget\FSharp.Compiler.Service.ProjectCracker.nuspec paket.dependencies = paket.dependencies README.md = README.md RELEASE_NOTES.md = RELEASE_NOTES.md @@ -41,23 +40,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{0554567F EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{E396742E-B4E5-4584-A9E4-CC1A491F5BC1}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "EditorService", "samples\EditorService\EditorService.fsproj", "{A40507D6-FA48-43D3-B18A-AE3DAACE4020}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "EditorService", "samples\EditorService\EditorService.fsproj", "{A40507D6-FA48-43D3-B18A-AE3DAACE4020}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "InteractiveService", "samples\InteractiveService\InteractiveService.fsproj", "{067E95E5-E3DC-4CA7-813A-4D1E277D2D52}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "InteractiveService", "samples\InteractiveService\InteractiveService.fsproj", "{067E95E5-E3DC-4CA7-813A-4D1E277D2D52}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Tokenizer", "samples\Tokenizer\Tokenizer.fsproj", "{92793069-816F-4F69-84AC-0966F8275E65}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Tokenizer", "samples\Tokenizer\Tokenizer.fsproj", "{92793069-816F-4F69-84AC-0966F8275E65}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "UntypedTree", "samples\UntypedTree\UntypedTree.fsproj", "{C816728D-BBEA-472D-9F6C-E8913957A673}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "UntypedTree", "samples\UntypedTree\UntypedTree.fsproj", "{C816728D-BBEA-472D-9F6C-E8913957A673}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FscExe", "samples\FscExe\FscExe.fsproj", "{C94C257C-3C0A-4858-B5D8-D746498D1F08}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FscExe", "samples\FscExe\FscExe.fsproj", "{C94C257C-3C0A-4858-B5D8-D746498D1F08}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharp_Analysis", "FSharp.Compiler.Service.Tests\CSharp_Analysis\CSharp_Analysis.csproj", "{887630A3-4B1D-40EA-B8B3-2D842E9C40DB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharp_Analysis", "FSharp.Compiler.Service.Tests\CSharp_Analysis\CSharp_Analysis.csproj", "{887630A3-4B1D-40EA-B8B3-2D842E9C40DB}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FsiExe", "samples\FsiExe\FsiExe.fsproj", "{F9540CA8-1CE0-4546-A23A-A461E416E95B}" -EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Service.ProjectCrackerTool", "FSharp.Compiler.Service.ProjectCrackerTool\FSharp.Compiler.Service.ProjectCrackerTool.fsproj", "{B1BDD96D-47E1-4E65-8107-FBAE23A06DB4}" -EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Service.ProjectCracker", "FSharp.Compiler.Service.ProjectCracker\FSharp.Compiler.Service.ProjectCracker.fsproj", "{893C3CD9-5AF8-4027-A667-21E62FC2C703}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsiExe", "samples\FsiExe\FsiExe.fsproj", "{F9540CA8-1CE0-4546-A23A-A461E416E95B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "config", "config", "{098D1C35-D0FB-4720-83DD-8002293EA237}" ProjectSection(SolutionItems) = preProject @@ -71,14 +66,13 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "package", "package", "{9020E136-794A-473F-9B1B-9623C97B7161}" ProjectSection(SolutionItems) = preProject nuget\FSharp.Compiler.Service.template = nuget\FSharp.Compiler.Service.template - nuget\projectcracker.template = nuget\projectcracker.template EndProjectSection EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Service.MSBuild.v12", "FSharp.Compiler.Service.MSBuild.v12\FSharp.Compiler.Service.MSBuild.v12.fsproj", "{8157B50E-397D-4232-A4E0-1977AFC7076D}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Service.MSBuild.v12", "FSharp.Compiler.Service.MSBuild.v12\FSharp.Compiler.Service.MSBuild.v12.fsproj", "{8157B50E-397D-4232-A4E0-1977AFC7076D}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Service", "FSharp.Compiler.Service\FSharp.Compiler.Service.fsproj", "{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Service", "FSharp.Compiler.Service\FSharp.Compiler.Service.fsproj", "{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Service.Tests", "FSharp.Compiler.Service.Tests\FSharp.Compiler.Service.Tests.fsproj", "{EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Service.Tests", "FSharp.Compiler.Service.Tests\FSharp.Compiler.Service.Tests.fsproj", "{EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -114,14 +108,6 @@ Global {F9540CA8-1CE0-4546-A23A-A461E416E95B}.Debug|Any CPU.Build.0 = Debug|Any CPU {F9540CA8-1CE0-4546-A23A-A461E416E95B}.Release|Any CPU.ActiveCfg = Release|Any CPU {F9540CA8-1CE0-4546-A23A-A461E416E95B}.Release|Any CPU.Build.0 = Release|Any CPU - {B1BDD96D-47E1-4E65-8107-FBAE23A06DB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B1BDD96D-47E1-4E65-8107-FBAE23A06DB4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B1BDD96D-47E1-4E65-8107-FBAE23A06DB4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B1BDD96D-47E1-4E65-8107-FBAE23A06DB4}.Release|Any CPU.Build.0 = Release|Any CPU - {893C3CD9-5AF8-4027-A667-21E62FC2C703}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {893C3CD9-5AF8-4027-A667-21E62FC2C703}.Debug|Any CPU.Build.0 = Debug|Any CPU - {893C3CD9-5AF8-4027-A667-21E62FC2C703}.Release|Any CPU.ActiveCfg = Release|Any CPU - {893C3CD9-5AF8-4027-A667-21E62FC2C703}.Release|Any CPU.Build.0 = Release|Any CPU {8157B50E-397D-4232-A4E0-1977AFC7076D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8157B50E-397D-4232-A4E0-1977AFC7076D}.Debug|Any CPU.Build.0 = Debug|Any CPU {8157B50E-397D-4232-A4E0-1977AFC7076D}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/fcs/README.md b/fcs/README.md index 8a518f62198..54681c43e1f 100644 --- a/fcs/README.md +++ b/fcs/README.md @@ -17,8 +17,6 @@ There are subtle differences between FSharp.Compiler.Service and FSharp.Compiler - FCS has a .NET Standard 2.0 version in the nuget package -- FCS testing also tests the "Project Cracker" (see below) - - FCS doesn't add the System.ValueTuple.dll reference by default, see ``#if COMPILER_SERVICE_AS_DLL`` in compiler codebase ## Version Numbers @@ -29,7 +27,6 @@ To update the version number a global replace through fcs\... is currently neede Directory.Build.props nuget/FSharp.Compiler.Service.nuspec nuget/FSharp.Compiler.Service.MSBuild.v12.nuspec - nuget/FSharp.Compiler.Service.ProjectCracker.nuspec RELEASE_NOTES.md ## Building, Testing, Packaging, Releases @@ -64,7 +61,6 @@ You can push the packages if you have permissions, either automatically using `` set APIKEY=... ..\fsharp\.nuget\nuget.exe push %HOMEDRIVE%%HOMEPATH%\Downloads\FSharp.Compiler.Service.22.0.3.nupkg %APIKEY% -Source https://nuget.org ..\fsharp\.nuget\nuget.exe push %HOMEDRIVE%%HOMEPATH%\Downloads\FSharp.Compiler.Service.MSBuild.v12.22.0.3.nupkg %APIKEY% -Source https://nuget.org - ..\fsharp\.nuget\nuget.exe push %HOMEDRIVE%%HOMEPATH%\Downloads\FSharp.Compiler.Service.ProjectCracker.22.0.3.nupkg %APIKEY% -Source https://nuget.org ### Use of Paket and FAKE @@ -82,15 +78,13 @@ Testing reuses the test files from ..\tests\service which were are also FCS test Output is in ``docs``. In the ``FSharp.Compiler.Service`` repo this is checked in and hosted as . -## The two other NuGet packages +## Other NuGet packages It also contains both the source, build, packaging and test logic for - ``FSharp.Compiler.Service.MSBuild.v12`` adds legacy MSBuild v12 support to an instance of FSharp.Compiler.Service, if exact compatibility for scripting references such as ``#r "Foo, Version=1.3.4"`` is required. -- ``FSharp.Compiler.Service.ProjectCracker`` is part of ``FsAutoComplete`` and Ionide and is used to crack old-style project formats using MSBuild. It used to be part of the FCS API. - -Both of these components are gradually becoming obsolete +These components are gradually becoming obsolete ## Engineering road map diff --git a/fcs/docsrc/content/devnotes.md b/fcs/docsrc/content/devnotes.md index 7f80660f364..98684f9f358 100644 --- a/fcs/docsrc/content/devnotes.md +++ b/fcs/docsrc/content/devnotes.md @@ -54,4 +54,4 @@ Release checklist to publish a new version on nuget.org 1. Update `RELEASE_NOTES.md` 2. Check the version numbers are correct across the source (some files duplicate them) 3. Commit and add the necessary tag to the repo -4. Publish the nupkgs for `FSharp.Compiler.Service` and `FSharp.Compiler.Service.ProjectCracker` once they appear in AppVeyor artifacts +4. Publish the nupkgs for `FSharp.Compiler.Service` once it appears in AppVeyor artifacts diff --git a/fcs/docsrc/content/project.fsx b/fcs/docsrc/content/project.fsx index a537000435e..7573b7f9bab 100644 --- a/fcs/docsrc/content/project.fsx +++ b/fcs/docsrc/content/project.fsx @@ -23,7 +23,6 @@ of `InteractiveChecker`: *) // Reference F# compiler API #r "FSharp.Compiler.Service.dll" -#r "FSharp.Compiler.Service.ProjectCracker.dll" open System open System.Collections.Generic @@ -306,61 +305,6 @@ correctly and then analyze each project in turn. *) -(** -Cracking a legacy project file ------------------------------ - -F# projects normally use the '.fsproj' project file format. -A project cracking facility for legacy old-style .fsproj is provided as a separate NuGet package: -FSharp.Compiler.Service.ProjectCracker. - -Project cracking for modern project files should be done using a library such as DotNetProjInfo. -See FsAutoComplete for example code. - -The legacy NuGet package `FSharp.Compiler.Service.ProjectCracker` contains a -library `FSharp.Compiler.Service.ProjectCracker.dll`, which should be -referenced by your application directly, and an executable -`FSharp.Compiler.Service.ProjectCrackerTool.exe`, which should be copied -into the output folder of your application by the build process. If -you install using Paket or NuGet, then this will be configured for you -automatically. If not, you should reference the provided `.targets` -file manually in your application. This can be found in the NuGet -package at `build/net461/FSharp.Compiler.Service.ProjectCrackerTool.targets`. - -The reason for this split was so the analysis of an F# project -file is performed out of process, in order that the necessary assembly -binding redirects can be applied without requiring the caller to -arrange this. In this way MSBuild versions from 4 up to 14 can be -accommodated transparently. - -In this example we get the project options for one of the -project files in the F# Compiler Service project itself - you should also be able to use this technique -for any project that builds cleanly using the command line tools 'xbuild' or 'msbuild'. - - -*) - -let projectFile = __SOURCE_DIRECTORY__ + @"/../../src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj" - -ProjectCracker.GetProjectOptionsFromProjectFile(projectFile) - - -(** - -You can also request RELEASE mode and set other build configuration parameters: - -*) - -ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, [("Configuration", "Release")]) - -(** - -For debugging purposes it is also possible to obtain a detailed log from the assembly resolution process. - -*) - -let options, logs = ProjectCracker.GetProjectOptionsFromProjectFileLogged(projectFile, [("Configuration", "Release")]) - (** Summary ------- diff --git a/tests/service/ExprTests.fs b/tests/service/ExprTests.fs index 284bc72e482..b039632af09 100644 --- a/tests/service/ExprTests.fs +++ b/tests/service/ExprTests.fs @@ -1,7 +1,6 @@  #if INTERACTIVE #r "../../artifacts/bin/fcs/net461/FSharp.Compiler.Service.dll" // note, build FSharp.Compiler.Service.Tests.fsproj to generate this, this DLL has a public API so can be used from F# Interactive -#r "../../artifacts/bin/fcs/net461/FSharp.Compiler.Service.ProjectCracker.dll" #r "../../artifacts/bin/fcs/net461/nunit.framework.dll" #load "FsUnit.fs" #load "Common.fs" @@ -2956,315 +2955,4 @@ let ``Test expressions of optimized declarations stress big expressions`` () = printDeclarations None (List.ofSeq file1.Declarations) |> Seq.toList |> ignore -#if NOT_YET_ENABLED - -#if !NO_PROJECTCRACKER && !NETCOREAPP - -[] -let ``Check use of type provider that provides calls to F# code`` () = - let config = -#if DEBUG - ["Configuration", "Debug"] -#else - ["Configuration", "Release"] -#endif - let options = - ProjectCracker.GetProjectOptionsFromProjectFile (Path.Combine(Path.Combine(Path.Combine(__SOURCE_DIRECTORY__, "data"),"TestProject"),"TestProject.fsproj"), config) - - let res = - options - |> exprChecker.ParseAndCheckProject - |> Async.RunSynchronously - - Assert.AreEqual ([||], res.Errors, sprintf "Should not be errors, but: %A" res.Errors) - - let results = - [ for f in res.AssemblyContents.ImplementationFiles do - for d in f.Declarations do - for line in d |> printDeclaration None do - yield line ] - - results |> List.iter (printfn "%s") - - results |> shouldEqual - ["type TestProject"; "type AssemblyInfo"; "type TestProject"; "type T"; - """type Class1"""; - """member .ctor(unitVar0) = (new Object(); ()) @ (5,5--5,11)"""; - """member get_X1(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.doNothing () @ (6,21--6,36)""" - """member get_X2(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.doNothingGeneric (3) @ (7,21--7,43)""" - """member get_X3(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.doNothingOneArg (3) @ (8,21--8,42)""" - """member get_X4(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in C.DoNothing () @ (9,21--9,41)""" - """member get_X5(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in C.DoNothingGeneric (3) @ (10,21--10,48)""" - """member get_X6(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in C.DoNothingOneArg (3) @ (11,21--11,47)""" - """member get_X7(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in C.DoNothingTwoArg (new C(),3) @ (12,21--12,47)""" - """member get_X8(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new C().InstanceDoNothing() @ (13,21--13,49)""" - """member get_X9(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new C().InstanceDoNothingGeneric(3) @ (14,21--14,56)""" - """member get_X10(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new C().InstanceDoNothingOneArg(3) @ (15,22--15,56)""" - """member get_X11(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new C().InstanceDoNothingTwoArg(new C(),3) @ (16,22--16,56)""" - """member get_X12(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in G`1.DoNothing () @ (17,22--17,49)""" - """member get_X13(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in G`1.DoNothingOneArg (3) @ (18,22--18,55)""" - """member get_X14(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in G`1.DoNothingTwoArg (new C(),3) @ (19,22--19,55)""" - """member get_X15(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in let matchValue: Microsoft.FSharp.Core.Option = FSharpOption`1.Some (1) in (if Operators.op_Equality (matchValue.Tag,1) then let x: Microsoft.FSharp.Core.int = matchValue.get_Value() in x else 0) @ (20,22--20,54)""" - """member get_X16(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in let matchValue: Microsoft.FSharp.Core.Choice = Choice1Of2(1) in (if Operators.op_Equality (matchValue.Tag,0) then 1 else 0) @ (21,22--21,54)""" - """member get_X17(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in let r: TestTP.Helper.R = {A = 1; B = 0} in (r.B <- 1; r.A) @ (22,22--22,60)""" - """member get_X18(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.doNothingTwoArg (3,4) @ (23,22--23,43)""" - """member get_X19(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.doNothingTwoArgCurried (3,4) @ (24,22--24,50)""" - """member get_X21(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in (fun arg00 -> fun arg10 -> C.DoNothingTwoArgCurried (arg00,arg10) new C()) 3 @ (25,22--25,55)""" - """member get_X23(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in (let objectArg: TestTP.Helper.C = new C() in fun arg00 -> fun arg10 -> objectArg.InstanceDoNothingTwoArgCurried(arg00,arg10) new C()) 3 @ (26,22--26,63)""" - """member get_X24(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.doNothingGenericWithConstraint (3) @ (27,22--27,58)""" - """member get_X25(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.doNothingGenericWithTypeConstraint,Microsoft.FSharp.Core.int> (FSharpList`1.Cons (3,FSharpList`1.get_Empty ())) @ (28,22--28,62)""" - """member get_X26(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.doNothingGenericWithTypeConstraint,Microsoft.FSharp.Core.int> (FSharpList`1.Cons (3,FSharpList`1.get_Empty ())) @ (29,22--29,62)""" - """member get_X27(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Helper.DoNothingReally () @ (30,22--30,53)""" - """member get_X28(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new CSharpClass(0).Method("x") :> Microsoft.FSharp.Core.Unit @ (31,22--31,40)""" - """member get_X29(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in Operators.op_Addition (new CSharpClass(0).Method2("x"),new CSharpClass(0).Method2("empty")) :> Microsoft.FSharp.Core.Unit @ (32,22--32,53)""" - """member get_X30(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new CSharpClass(0).Method3([|"x"; "y"|]) :> Microsoft.FSharp.Core.Unit @ (33,22--33,50)""" - """member get_X31(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new CSharpClass(0).GenericMethod(2) @ (34,22--34,47)""" - """member get_X32(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new CSharpClass(0).GenericMethod2(new Object()) @ (35,22--35,61)""" - """member get_X33(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new CSharpClass(0).GenericMethod3(3) @ (36,22--36,65)""" - """member get_X34(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in C.DoNothingReally () @ (37,22--37,58)""" - """member get_X35(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new C().DoNothingReallyInst() @ (38,22--38,66)""" - """member get_X36(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in (new CSharpClass(0) :> FSharp.Compiler.Service.Tests.ICSharpExplicitInterface).ExplicitMethod("x") :> Microsoft.FSharp.Core.Unit @ (39,22--39,62)""" - """member get_X37(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in (new C() :> TestTP.Helper.I).DoNothing() @ (40,22--40,46)""" - """member get_X38(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in new C().VirtualDoNothing() @ (41,22--41,45)""" - """member get_X39(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in let t: Microsoft.FSharp.Core.int * Microsoft.FSharp.Core.int * Microsoft.FSharp.Core.int = (1,2,3) in let i: Microsoft.FSharp.Core.int = t.Item1 in i @ (42,22--42,51)""" - """member get_X40(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in (moduleValue <- 1; moduleValue) @ (43,22--43,39)""" - """member get_X41(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in let x: TestTP.Helper.C = new C() in (x.set_Property(1); x.get_Property()) @ (44,22--44,41)""" - """member get_X42(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in let x: TestTP.Helper.C = new C() in (x.set_AutoProperty(1); x.get_AutoProperty()) @ (45,22--45,45)""" - """member get_X43(this) (unitVar1) = let this: Microsoft.FSharp.Core.obj = ("My internal state" :> Microsoft.FSharp.Core.obj) :> ErasedWithConstructor.Provided.MyType in (C.set_StaticAutoProperty (1); C.get_StaticAutoProperty ()) @ (46,22--46,51)""" - ] - - let members = - [ for f in res.AssemblyContents.ImplementationFiles do yield! printMembersOfDeclatations f.Declarations ] - - members |> List.iter (printfn "%s") - - members |> shouldEqual - [ - ".ctor: Microsoft.FSharp.Core.unit -> TestProject.Class1" - ".ctor: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X1: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "doNothing: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X2: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "doNothingGeneric<'T>: 'T -> Microsoft.FSharp.Core.unit" - "get_X3: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "doNothingOneArg: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "get_X4: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothing: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X5: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothingGeneric<'T>: 'T -> Microsoft.FSharp.Core.unit" - "get_X6: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothingOneArg: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "get_X7: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothingTwoArg: TestTP.Helper.C * Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "get_X8: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "InstanceDoNothing: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X9: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "InstanceDoNothingGeneric<'T>: 'T -> Microsoft.FSharp.Core.unit" - "get_X10: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "InstanceDoNothingOneArg: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "get_X11: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "InstanceDoNothingTwoArg: TestTP.Helper.C * Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "get_X12: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothing: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X13: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothingOneArg: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "get_X14: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothingTwoArg: TestTP.Helper.C * Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "get_X15: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - "Some: 'T -> 'T Microsoft.FSharp.Core.option" - "op_Equality<'T when 'T : equality>: 'T -> 'T -> Microsoft.FSharp.Core.bool" - "matchValue: Microsoft.FSharp.Core.Option" - "matchValue: Microsoft.FSharp.Core.Option" - "get_Value: Microsoft.FSharp.Core.unit -> 'T" - "x: Microsoft.FSharp.Core.int" - "get_X16: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - "op_Equality<'T when 'T : equality>: 'T -> 'T -> Microsoft.FSharp.Core.bool" - "matchValue: Microsoft.FSharp.Core.Choice" - "get_X17: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - "r: TestTP.Helper.R" - "r: TestTP.Helper.R" - "get_X18: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "doNothingTwoArg: Microsoft.FSharp.Core.int * Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "get_X19: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "doNothingTwoArgCurried: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "get_X21: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothingTwoArgCurried: TestTP.Helper.C -> Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "arg00: TestTP.Helper.C" - "arg10: Microsoft.FSharp.Core.int" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "get_X23: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "objectArg: TestTP.Helper.C" - "InstanceDoNothingTwoArgCurried: TestTP.Helper.C -> Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "arg00: TestTP.Helper.C" - "arg10: Microsoft.FSharp.Core.int" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "get_X24: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "doNothingGenericWithConstraint<'T when 'T : equality>: 'T -> Microsoft.FSharp.Core.unit" - "get_X25: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "doNothingGenericWithTypeConstraint<'T, _ when 'T :> Microsoft.FSharp.Collections.seq<'a>>: 'T -> Microsoft.FSharp.Core.unit" - "Cons: 'T * 'T Microsoft.FSharp.Collections.list -> 'T Microsoft.FSharp.Collections.list" - "get_Empty: Microsoft.FSharp.Core.unit -> 'T Microsoft.FSharp.Collections.list" - "get_X26: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "doNothingGenericWithTypeConstraint<'T, _ when 'T :> Microsoft.FSharp.Collections.seq<'a>>: 'T -> Microsoft.FSharp.Core.unit" - "Cons: 'T * 'T Microsoft.FSharp.Collections.list -> 'T Microsoft.FSharp.Collections.list" - "get_Empty: Microsoft.FSharp.Core.unit -> 'T Microsoft.FSharp.Collections.list" - "get_X27: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothingReally: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X28: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "Method: Microsoft.FSharp.Core.string -> Microsoft.FSharp.Core.int" - "get_X29: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "op_Addition<^T1, ^T2, ^T3>: ^T1 -> ^T2 -> ^T3" - ".ctor: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "Method2: Microsoft.FSharp.Core.string -> Microsoft.FSharp.Core.int" - ".ctor: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "Method2: Microsoft.FSharp.Core.string -> Microsoft.FSharp.Core.int" - "get_X30: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "Method3: Microsoft.FSharp.Core.string Microsoft.FSharp.Core.[] -> Microsoft.FSharp.Core.int" - "get_X31: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "GenericMethod<'T>: 'T -> Microsoft.FSharp.Core.unit" - "get_X32: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "GenericMethod2<'T when 'T : class>: 'T -> Microsoft.FSharp.Core.unit" - ".ctor: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X33: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "GenericMethod3<'T when 'T :> System.IComparable<'T>>: 'T -> Microsoft.FSharp.Core.unit" - "get_X34: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - "DoNothingReally: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X35: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "DoNothingReallyInst: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X36: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "ExplicitMethod: Microsoft.FSharp.Core.string -> Microsoft.FSharp.Core.int" - "get_X37: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "DoNothing: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X38: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.Unit" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "VirtualDoNothing: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.unit" - "get_X39: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - "t: Microsoft.FSharp.Core.int * Microsoft.FSharp.Core.int * Microsoft.FSharp.Core.int" - "i: Microsoft.FSharp.Core.int" - "get_X40: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - "moduleValue: Microsoft.FSharp.Core.int" - "moduleValue: Microsoft.FSharp.Core.int" - "get_X41: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "x: TestTP.Helper.C" - "set_Property: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "x: TestTP.Helper.C" - "get_Property: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - "get_X42: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - ".ctor: Microsoft.FSharp.Core.unit -> TestTP.Helper.C" - "x: TestTP.Helper.C" - "set_AutoProperty: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "x: TestTP.Helper.C" - "get_AutoProperty: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - "get_X43: TestProject.Class1 -> Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - "set_StaticAutoProperty: Microsoft.FSharp.Core.int -> Microsoft.FSharp.Core.unit" - "get_StaticAutoProperty: Microsoft.FSharp.Core.unit -> Microsoft.FSharp.Core.int" - ] - -#endif -#endif - - -#if SELF_HOST_STRESS - - -[] -let ``Test Declarations selfhost`` () = - let projectFile = __SOURCE_DIRECTORY__ + @"/FSharp.Compiler.Service.Tests.fsproj" - // Check with Configuration = Release - let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, [("Configuration", "Debug")]) - let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunSynchronously - - wholeProjectResults.Errors.Length |> shouldEqual 0 - - wholeProjectResults.AssemblyContents.ImplementationFiles.Length |> shouldEqual 13 - - let textOfAll = [ for file in wholeProjectResults.AssemblyContents.ImplementationFiles -> Array.ofSeq (printDeclarations None (List.ofSeq file.Declarations)) ] - - () - - -[] -let ``Test Declarations selfhost whole compiler`` () = - - Directory.SetCurrentDirectory(__SOURCE_DIRECTORY__ + @"/../../src/fsharp/FSharp.Compiler.Service") - let projectFile = __SOURCE_DIRECTORY__ + @"/../../src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj" - - //let v = FSharpProjectFileInfo.Parse(projectFile, [("Configuration", "Debug"); ("NoFsSrGenTask", "true")],enableLogging=true) - let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, [("Configuration", "Debug"); ("NoFsSrGenTask", "true")]) - - // For subsets of the compiler: - //let options = { options with OtherOptions = options.OtherOptions.[0..51] } - - //for x in options.OtherOptions do printfn "%s" x - - let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunSynchronously - - (wholeProjectResults.Errors |> Array.filter (fun x -> x.Severity = FSharpErrorSeverity.Error)).Length |> shouldEqual 0 - - for file in (wholeProjectResults.AssemblyContents.ImplementationFiles |> List.toArray) do - for d in file.Declarations do - for s in printDeclaration None d do - () //printfn "%s" s - - // Very Quick (1 sec - expressions are computed on demand) - for file in (wholeProjectResults.AssemblyContents.ImplementationFiles |> List.toArray) do - for d in file.Declarations do - for s in exprsOfDecl d do - () - - // Quickish (~4.5 seconds for all of FSharp.Compiler.Service.dll) - #time "on" - for file in (wholeProjectResults.AssemblyContents.ImplementationFiles |> List.toArray) do - for d in file.Declarations do - for (e,m) in exprsOfDecl d do - // This forces the computation of the expression - match e with - | BasicPatterns.Const _ -> () //printfn "%s" s - | _ -> () //printfn "%s" s - -[] -let ``Test Declarations selfhost FSharp.Core`` () = - - Directory.SetCurrentDirectory(__SOURCE_DIRECTORY__ + @"/../../../fsharp/src/fsharp/FSharp.Core") - let projectFile = __SOURCE_DIRECTORY__ + @"/../../../fsharp/src/fsharp/FSharp.Core/FSharp.Core.fsproj" - - let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, [("Configuration", "Debug")]) - - let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunSynchronously - - //(wholeProjectResults.Errors |> Array.filter (fun x -> x.Severity = FSharpErrorSeverity.Error)).Length |> shouldEqual 0 - - for file in (wholeProjectResults.AssemblyContents.ImplementationFiles |> List.toArray) do - for d in file.Declarations do - for s in printDeclaration (Some (HashSet [])) d do - printfn "%s" s - - #time "on" - - for file in (wholeProjectResults.AssemblyContents.ImplementationFiles |> List.toArray) do - for d in file.Declarations do - for (e,m) in exprsOfDecl d do - // This forces the computation of the expression - match e with - | BasicPatterns.Const _ -> () - | _ -> () - -#endif diff --git a/tests/service/MultiProjectAnalysisTests.fs b/tests/service/MultiProjectAnalysisTests.fs index a4ba694cfa8..ac5df3f1c7c 100644 --- a/tests/service/MultiProjectAnalysisTests.fs +++ b/tests/service/MultiProjectAnalysisTests.fs @@ -823,7 +823,6 @@ let ``Test max memory gets triggered`` () = [] #endif let ``Type provider project references should not throw exceptions`` () = - //let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, [("Configuration", "Debug")]) let options = {ProjectFileName = __SOURCE_DIRECTORY__ + @"/data/TypeProviderConsole/TypeProviderConsole.fsproj"; ProjectId = None @@ -915,7 +914,6 @@ let ``Type provider project references should not throw exceptions`` () = [] #endif let ``Projects creating generated types should not utilize cross-project-references but should still analyze oK once project is built`` () = - //let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, [("Configuration", "Debug")]) let options = {ProjectFileName = __SOURCE_DIRECTORY__ + @"/data/TypeProvidersBug/TestConsole/TestConsole.fsproj"; diff --git a/tests/service/ProjectOptionsTests.fs b/tests/service/ProjectOptionsTests.fs deleted file mode 100644 index ed30de97dc3..00000000000 --- a/tests/service/ProjectOptionsTests.fs +++ /dev/null @@ -1,578 +0,0 @@ -#if INTERACTIVE -#r "../../artifacts/bin/fcs/net461/FSharp.Compiler.Service.dll" // note, build FSharp.Compiler.Service.Tests.fsproj to generate this, this DLL has a public API so can be used from F# Interactive -#r "../../artifacts/bin/fcs/net461/FSharp.Compiler.Service.ProjectCracker.dll" -#r "../../artifacts/bin/fcs/net461/nunit.framework.dll" -#load "FsUnit.fs" -#load "Common.fs" -#else -module FSharp.Compiler.Service.Tests.ProjectOptionsTests -#endif - -let runningOnMono = try System.Type.GetType("Mono.Runtime") <> null with e -> false - -open System.IO -open NUnit.Framework -open FsUnit -open FSharp.Compiler.Ast -open FSharp.Compiler.SourceCodeServices - -open FSharp.Compiler.Service.Tests.Common - -#if !NO_PROJECTCRACKER && DISABLED // Disabled tests because of MSBuild API dependencies. The ProjectCracker is basically deprecated in any case - -let hasMSBuild14 = - use engine = new Microsoft.Build.Evaluation.ProjectCollection() - engine.Toolsets |> Seq.exists (fun x -> x.ToolsPath.Contains "v14.0") - -let normalizePath s = (new Uri(s)).LocalPath - -let checkOption (opts:string[]) s = - let found = "Found '"+s+"'" - (if opts |> Array.exists (fun o -> o.EndsWith(s)) then found else "Failed to find '"+s+"'") - |> shouldEqual found - -let checkOptionNotPresent (opts:string[]) s = - let found = "Found '"+s+"'" - let notFound = "Did not expect to find '"+s+"'" - (if opts |> Array.exists (fun o -> o.EndsWith(s)) then found else notFound) - |> shouldEqual notFound - -let getReferencedFilenames = Array.choose (fun (o:string) -> if o.StartsWith("-r:") then o.[3..] |> (Path.GetFileName >> Some) else None) -let getReferencedFilenamesAndContainingFolders = Array.choose (fun (o:string) -> if o.StartsWith("-r:") then o.[3..] |> (fun r -> ((r |> Path.GetFileName), (r |> Path.GetDirectoryName |> Path.GetFileName)) |> Some) else None) -let getOutputFile = Array.pick (fun (o:string) -> if o.StartsWith("--out:") then o.[6..] |> Some else None) - -let getCompiledFilenames = - Array.choose (fun (opt: string) -> - if opt.EndsWith ".fs" then - opt |> Path.GetFileName |> Some - else None) - >> Array.distinct - -(* -[] - let ``Project file parsing example 1 Default Configuration`` () = - let projectFile = __SOURCE_DIRECTORY__ + @"/FSharp.Compiler.Service.Tests.fsproj" - let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile) - - checkOption options.SourceFiles "FileSystemTests.fs" - - checkOption options.OtherOptions "FSharp.Compiler.Service.dll" - checkOption options.OtherOptions "--define:TRACE" - checkOption options.OtherOptions "--define:DEBUG" - checkOption options.OtherOptions "--flaterrors" - checkOption options.OtherOptions "--simpleresolution" - checkOption options.OtherOptions "--noframework" - -[] -let ``Project file parsing example 1 Release Configuration`` () = - let projectFile = __SOURCE_DIRECTORY__ + @"/FSharp.Compiler.Service.Tests.fsproj" - // Check with Configuration = Release - let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, [("Configuration", "Release")]) - - checkOption options.SourceFiles "FileSystemTests.fs" - - checkOption options.OtherOptions "FSharp.Compiler.Service.dll" - checkOption options.OtherOptions "--define:TRACE" - checkOptionNotPresent options.OtherOptions "--define:DEBUG" - checkOption options.OtherOptions "--debug:pdbonly" - -[] -let ``Project file parsing example 1 Default configuration relative path`` () = - let projectFile = "FSharp.Compiler.Service.Tests.fsproj" - Directory.SetCurrentDirectory(__SOURCE_DIRECTORY__) - let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile) - - checkOption options.SourceFiles "FileSystemTests.fs" - - checkOption options.OtherOptions "FSharp.Compiler.Service.dll" - checkOption options.OtherOptions "--define:TRACE" - checkOption options.OtherOptions "--define:DEBUG" - checkOption options.OtherOptions "--flaterrors" - checkOption options.OtherOptions "--simpleresolution" - checkOption options.OtherOptions "--noframework" -*) - -[] -let ``Project file parsing VS2013_FSharp_Portable_Library_net45``() = - if (not hasMSBuild14) || runningOnMono then () else // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok - - let projectFile = __SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net45/Sample_VS2013_FSharp_Portable_Library_net45.fsproj" - let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, []) - - checkOption options.OtherOptions "--targetprofile:netcore" - checkOption options.OtherOptions "--tailcalls-" - - checkOption options.OtherOptions "FSharp.Core.dll" - checkOption options.OtherOptions "Microsoft.CSharp.dll" - checkOption options.OtherOptions "System.Runtime.dll" - checkOption options.OtherOptions "System.Net.Requests.dll" - checkOption options.OtherOptions "System.Xml.XmlSerializer.dll" - -[] -let ``Project file parsing Sample_VS2013_FSharp_Portable_Library_net451_adjusted_to_profile78``() = - if (not hasMSBuild14) || runningOnMono then () else // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok - - let projectFile = __SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net451_adjusted_to_profile78/Sample_VS2013_FSharp_Portable_Library_net451.fsproj" - Directory.SetCurrentDirectory(__SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net451_adjusted_to_profile78/") - let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, []) - - checkOption options.OtherOptions "--targetprofile:netcore" - checkOption options.OtherOptions "--tailcalls-" - - checkOption options.OtherOptions "FSharp.Core.dll" - checkOption options.OtherOptions "Microsoft.CSharp.dll" - checkOption options.OtherOptions "System.Runtime.dll" - checkOption options.OtherOptions "System.Net.Requests.dll" - checkOption options.OtherOptions "System.Xml.XmlSerializer.dll" - -[] -let ``Project file parsing -- compile files 1``() = - let opts = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/Test1.fsproj") - CollectionAssert.AreEqual (["Test1File2.fs"; "Test1File1.fs"], opts.SourceFiles |> Array.map Path.GetFileName) - CollectionAssert.IsEmpty (getCompiledFilenames opts.OtherOptions) - -[] -let ``Project file parsing -- compile files 2``() = - let opts = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/Test2.fsproj") - - CollectionAssert.AreEqual (["Test2File2.fs"; "Test2File1.fs"], opts.SourceFiles |> Array.map Path.GetFileName) - CollectionAssert.IsEmpty (getCompiledFilenames opts.OtherOptions) - -[] -let ``Project file parsing -- bad project file``() = - let f = normalizePath (__SOURCE_DIRECTORY__ + @"/data/Malformed.fsproj") - try - ProjectCracker.GetProjectOptionsFromProjectFileLogged(f) |> ignore - failwith "Expected exception" - with e -> - Assert.That(e.Message, Contains.Substring "Could not load project") - Assert.That(e.Message, Contains.Substring "Malformed.fsproj") - -[] -let ``Project file parsing -- non-existent project file``() = - let f = normalizePath (__SOURCE_DIRECTORY__ + @"/data/DoesNotExist.fsproj") - try - ProjectCracker.GetProjectOptionsFromProjectFileLogged(f, enableLogging=true) |> ignore - with e -> - Assert.That(e.Message, Contains.Substring "DoesNotExist.fsproj") - -[] -let ``Project file parsing -- output file``() = - let p = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/Test1.fsproj") - - let expectedOutputPath = - normalizePath (__SOURCE_DIRECTORY__ + "/data/bin/Debug/Test1.dll") - - p.OtherOptions - |> getOutputFile - |> should equal expectedOutputPath - -[] -let ``Project file parsing -- references``() = - let p = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/Test1.fsproj") - - let references = getReferencedFilenames p.OtherOptions - checkOption references "FSharp.Core.dll" - checkOption references "mscorlib.dll" - checkOption references "System.Core.dll" - checkOption references "System.dll" - printfn "Project file parsing -- references: references = %A" references - references |> should haveLength 4 - p.ReferencedProjects |> should be Empty - -[] -let ``Project file parsing -- no project references``() = - let p = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/Test3.fsproj") - - let references = getReferencedFilenames p.OtherOptions - checkOption references "FSharp.Core.dll" - checkOption references "mscorlib.dll" - checkOption references "System.Core.dll" - checkOption references "System.dll" - p.ReferencedProjects |> should haveLength 0 - -[] -let ``Project file parsing -- 2nd level references``() = - let p,_ = ProjectCracker.GetProjectOptionsFromProjectFileLogged(__SOURCE_DIRECTORY__ + @"/data/Test2.fsproj", enableLogging=true) - - let references = getReferencedFilenames p.OtherOptions - checkOption references "FSharp.Core.dll" - checkOption references "mscorlib.dll" - checkOption references "System.Core.dll" - checkOption references "System.dll" - checkOption references "Test1.dll" - printfn "Project file parsing -- references: references = %A" references - references |> should haveLength 5 - p.ReferencedProjects |> should haveLength 1 - (snd p.ReferencedProjects.[0]).ProjectFileName |> should contain (normalizePath (__SOURCE_DIRECTORY__ + @"/data/Test1.fsproj")) - - -[] -let ``Project file parsing -- reference project output file``() = - let p = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/DifferingOutputDir/Dir2/Test2.fsproj") - - let expectedOutputPath = - normalizePath (__SOURCE_DIRECTORY__ + "/data/DifferingOutputDir/Dir2/OutputDir2/Test2.exe") - - p.OtherOptions - |> getOutputFile - |> should equal expectedOutputPath - - p.OtherOptions - |> Array.choose (fun (o:string) -> if o.StartsWith("-r:") then o.[3..] |> Some else None) - |> should contain (normalizePath (__SOURCE_DIRECTORY__ + @"/data/DifferingOutputDir/Dir1/OutputDir1/Test1.dll")) - -[] -let ``Project file parsing -- Tools Version 12``() = - if not hasMSBuild14 then () else - let opts = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/ToolsVersion12.fsproj") - checkOption (getReferencedFilenames opts.OtherOptions) "System.Core.dll" - -[] -let ``Project file parsing -- Logging``() = - if not hasMSBuild14 then () else - let projectFileName = normalizePath (__SOURCE_DIRECTORY__ + @"/data/ToolsVersion12.fsproj") - let _, logMap = ProjectCracker.GetProjectOptionsFromProjectFileLogged(projectFileName, enableLogging=true) - let log = logMap.[projectFileName] - - Assert.That(log, Does.Contain("ResolveAssemblyReference")) - if runningOnMono then - Assert.That(log, Does.Contain("System.Core")) - Assert.That(log, Does.Contain("Microsoft.Build.Tasks.ResolveAssemblyReference")) - else - Assert.That(log, Does.Contain("Microsoft.Build.Tasks.Core")) - -[] -let ``Project file parsing -- FSharpProjectOptions.SourceFiles contains both fs and fsi files``() = - let projectFileName = normalizePath (__SOURCE_DIRECTORY__ + @"/data/FsAndFsiFiles.fsproj") - let options, log = ProjectCracker.GetProjectOptionsFromProjectFileLogged(projectFileName, enableLogging=true) - printfn "%A" log - let expectedSourceFiles = - [| "Test1File2.fsi" - "Test1File2.fs" - "Test1File1.fs" - "Test1File0.fsi" - "Test1File0.fs" |] - Assert.That(options.SourceFiles |> Array.map Path.GetFileName, Is.EqualTo expectedSourceFiles, "source files") - -[] -let ``Project file parsing -- Full path``() = - if not hasMSBuild14 then () else - let f = normalizePath (__SOURCE_DIRECTORY__ + @"/data/ToolsVersion12.fsproj") - let p = ProjectCracker.GetProjectOptionsFromProjectFile(f) - p.ProjectFileName |> should equal f - -[] -let ``Project file parsing -- project references``() = - let f1 = normalizePath (__SOURCE_DIRECTORY__ + @"/data/Test1.fsproj") - let f2 = normalizePath (__SOURCE_DIRECTORY__ + @"/data/Test2.fsproj") - let options = ProjectCracker.GetProjectOptionsFromProjectFile(f2) - - options.ReferencedProjects |> should haveLength 1 - fst options.ReferencedProjects.[0] |> should endWith "Test1.dll" - snd options.ReferencedProjects.[0] |> should equal (ProjectCracker.GetProjectOptionsFromProjectFile(f1)) - -[] -let ``Project file parsing -- multi language project``() = - if not hasMSBuild14 then () else - let f = normalizePath (__SOURCE_DIRECTORY__ + @"/data/MultiLanguageProject/ConsoleApplication1.fsproj") - - let options = ProjectCracker.GetProjectOptionsFromProjectFile(f) - - options.ReferencedProjects |> should haveLength 1 - options.ReferencedProjects.[0] |> fst |> should endWith "ConsoleApplication2.exe" - - checkOption options.OtherOptions "ConsoleApplication2.exe" - checkOption options.OtherOptions "ConsoleApplication3.exe" - -[] -let ``Project file parsing -- PCL profile7 project``() = - if (not hasMSBuild14) || runningOnMono then () else // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok - - let f = normalizePath (__SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net45/Sample_VS2013_FSharp_Portable_Library_net45.fsproj") - - let options = ProjectCracker.GetProjectOptionsFromProjectFile(f) - let references = - options.OtherOptions - |> getReferencedFilenames - |> Set.ofArray - references - |> shouldEqual - (set [|"FSharp.Core.dll"; "Microsoft.CSharp.dll"; "Microsoft.VisualBasic.dll"; - "System.Collections.Concurrent.dll"; "System.Collections.dll"; - "System.ComponentModel.Annotations.dll"; - "System.ComponentModel.DataAnnotations.dll"; - "System.ComponentModel.EventBasedAsync.dll"; "System.ComponentModel.dll"; - "System.Core.dll"; "System.Diagnostics.Contracts.dll"; - "System.Diagnostics.Debug.dll"; "System.Diagnostics.Tools.dll"; - "System.Diagnostics.Tracing.dll"; "System.Dynamic.Runtime.dll"; - "System.Globalization.dll"; "System.IO.Compression.dll"; "System.IO.dll"; - "System.Linq.Expressions.dll"; "System.Linq.Parallel.dll"; - "System.Linq.Queryable.dll"; "System.Linq.dll"; "System.Net.Http.dll"; - "System.Net.NetworkInformation.dll"; "System.Net.Primitives.dll"; - "System.Net.Requests.dll"; "System.Net.dll"; "System.Numerics.dll"; - "System.ObjectModel.dll"; "System.Reflection.Context.dll"; - "System.Reflection.Extensions.dll"; "System.Reflection.Primitives.dll"; - "System.Reflection.dll"; "System.Resources.ResourceManager.dll"; - "System.Runtime.Extensions.dll"; - "System.Runtime.InteropServices.WindowsRuntime.dll"; - "System.Runtime.InteropServices.dll"; "System.Runtime.Numerics.dll"; - "System.Runtime.Serialization.Json.dll"; - "System.Runtime.Serialization.Primitives.dll"; - "System.Runtime.Serialization.Xml.dll"; "System.Runtime.Serialization.dll"; - "System.Runtime.dll"; "System.Security.Principal.dll"; - "System.ServiceModel.Duplex.dll"; "System.ServiceModel.Http.dll"; - "System.ServiceModel.NetTcp.dll"; "System.ServiceModel.Primitives.dll"; - "System.ServiceModel.Security.dll"; "System.ServiceModel.Web.dll"; - "System.ServiceModel.dll"; "System.Text.Encoding.Extensions.dll"; - "System.Text.Encoding.dll"; "System.Text.RegularExpressions.dll"; - "System.Threading.Tasks.Parallel.dll"; "System.Threading.Tasks.dll"; - "System.Threading.dll"; "System.Windows.dll"; "System.Xml.Linq.dll"; - "System.Xml.ReaderWriter.dll"; "System.Xml.Serialization.dll"; - "System.Xml.XDocument.dll"; "System.Xml.XmlSerializer.dll"; "System.Xml.dll"; - "System.dll"; "mscorlib.dll"|]) - - checkOption options.OtherOptions "--targetprofile:netcore" - -[] -let ``Project file parsing -- PCL profile78 project``() = - if (not hasMSBuild14) || runningOnMono then () else // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok - - let f = normalizePath (__SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net451_adjusted_to_profile78/Sample_VS2013_FSharp_Portable_Library_net451.fsproj") - - let options = ProjectCracker.GetProjectOptionsFromProjectFile(f) - let references = - options.OtherOptions - |> getReferencedFilenames - |> Set.ofArray - references - |> shouldEqual - (set [|"FSharp.Core.dll"; "Microsoft.CSharp.dll"; "System.Collections.dll"; - "System.ComponentModel.EventBasedAsync.dll"; "System.ComponentModel.dll"; - "System.Core.dll"; "System.Diagnostics.Contracts.dll"; - "System.Diagnostics.Debug.dll"; "System.Diagnostics.Tools.dll"; - "System.Dynamic.Runtime.dll"; "System.Globalization.dll"; "System.IO.dll"; - "System.Linq.Expressions.dll"; "System.Linq.Queryable.dll"; "System.Linq.dll"; - "System.Net.NetworkInformation.dll"; "System.Net.Primitives.dll"; - "System.Net.Requests.dll"; "System.Net.dll"; "System.ObjectModel.dll"; - "System.Reflection.Extensions.dll"; "System.Reflection.Primitives.dll"; - "System.Reflection.dll"; "System.Resources.ResourceManager.dll"; - "System.Runtime.Extensions.dll"; - "System.Runtime.InteropServices.WindowsRuntime.dll"; - "System.Runtime.Serialization.Json.dll"; - "System.Runtime.Serialization.Primitives.dll"; - "System.Runtime.Serialization.Xml.dll"; "System.Runtime.Serialization.dll"; - "System.Runtime.dll"; "System.Security.Principal.dll"; - "System.ServiceModel.Http.dll"; "System.ServiceModel.Primitives.dll"; - "System.ServiceModel.Security.dll"; "System.ServiceModel.Web.dll"; - "System.ServiceModel.dll"; "System.Text.Encoding.Extensions.dll"; - "System.Text.Encoding.dll"; "System.Text.RegularExpressions.dll"; - "System.Threading.Tasks.dll"; "System.Threading.dll"; "System.Windows.dll"; - "System.Xml.Linq.dll"; "System.Xml.ReaderWriter.dll"; - "System.Xml.Serialization.dll"; "System.Xml.XDocument.dll"; - "System.Xml.XmlSerializer.dll"; "System.Xml.dll"; "System.dll"; "mscorlib.dll"|]) - - checkOption options.OtherOptions "--targetprofile:netcore" - -[] -let ``Project file parsing -- PCL profile259 project``() = - if (not hasMSBuild14) || runningOnMono then () else // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok - let f = normalizePath (__SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net451_adjusted_to_profile259/Sample_VS2013_FSharp_Portable_Library_net451.fsproj") - - let options = ProjectCracker.GetProjectOptionsFromProjectFile(f) - let references = - options.OtherOptions - |> getReferencedFilenames - |> Set.ofArray - references - |> shouldEqual - (set [|"FSharp.Core.dll"; "Microsoft.CSharp.dll"; "System.Collections.dll"; - "System.ComponentModel.EventBasedAsync.dll"; "System.ComponentModel.dll"; - "System.Core.dll"; "System.Diagnostics.Contracts.dll"; - "System.Diagnostics.Debug.dll"; "System.Diagnostics.Tools.dll"; - "System.Dynamic.Runtime.dll"; "System.Globalization.dll"; "System.IO.dll"; - "System.Linq.Expressions.dll"; "System.Linq.Queryable.dll"; "System.Linq.dll"; - "System.Net.NetworkInformation.dll"; "System.Net.Primitives.dll"; - "System.Net.Requests.dll"; "System.Net.dll"; "System.ObjectModel.dll"; - "System.Reflection.Extensions.dll"; "System.Reflection.Primitives.dll"; - "System.Reflection.dll"; "System.Resources.ResourceManager.dll"; - "System.Runtime.Extensions.dll"; - "System.Runtime.InteropServices.WindowsRuntime.dll"; - "System.Runtime.Serialization.Json.dll"; - "System.Runtime.Serialization.Primitives.dll"; - "System.Runtime.Serialization.Xml.dll"; "System.Runtime.Serialization.dll"; - "System.Runtime.dll"; "System.Security.Principal.dll"; - "System.ServiceModel.Web.dll"; "System.Text.Encoding.Extensions.dll"; - "System.Text.Encoding.dll"; "System.Text.RegularExpressions.dll"; - "System.Threading.Tasks.dll"; "System.Threading.dll"; "System.Windows.dll"; - "System.Xml.Linq.dll"; "System.Xml.ReaderWriter.dll"; - "System.Xml.Serialization.dll"; "System.Xml.XDocument.dll"; - "System.Xml.XmlSerializer.dll"; "System.Xml.dll"; "System.dll"; "mscorlib.dll"|]) - - checkOption options.OtherOptions "--targetprofile:netcore" - -(* -[] -let ``Project file parsing -- Exe with a PCL reference``() = - - let f = normalizePath(__SOURCE_DIRECTORY__ + @"/data/sqlite-net-spike/sqlite-net-spike.fsproj") - - let p = ProjectCracker.GetProjectOptionsFromProjectFile(f) - let references = getReferencedFilenames p.OtherOptions |> set - references |> should contain "FSharp.Core.dll" - references |> should contain "SQLite.Net.Platform.Generic.dll" - references |> should contain "SQLite.Net.Platform.Win32.dll" - references |> should contain "SQLite.Net.dll" - references |> should contain "System.Collections.Concurrent.dll" - references |> should contain "System.Linq.Queryable.dll" - references |> should contain "System.Resources.ResourceManager.dll" - references |> should contain "System.Threading.dll" - references |> should contain "System.dll" - references |> should contain "mscorlib.dll" - references |> should contain "System.Reflection.dll" - references |> should contain "System.Reflection.Emit.Lightweight.dll" -*) - -[] -let ``Project file parsing -- project file contains project reference to out-of-solution project and is used in release mode``() = - let projectFileName = normalizePath(__SOURCE_DIRECTORY__ + @"/data/Test2.fsproj") - let opts = ProjectCracker.GetProjectOptionsFromProjectFile(projectFileName,[("Configuration","Release")]) - let references = getReferencedFilenamesAndContainingFolders opts.OtherOptions |> set - // Check the reference is to a release DLL - references |> should contain ("Test1.dll", "Release") - -[] -let ``Project file parsing -- project file contains project reference to out-of-solution project and is used in debug mode``() = - - let projectFileName = normalizePath(__SOURCE_DIRECTORY__ + @"/data/Test2.fsproj") - let opts = ProjectCracker.GetProjectOptionsFromProjectFile(projectFileName,[("Configuration","Debug")]) - let references = getReferencedFilenamesAndContainingFolders opts.OtherOptions |> set - // Check the reference is to a debug DLL - references |> should contain ("Test1.dll", "Debug") - -[] -let ``Project file parsing -- space in file name``() = - let opts = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/Space in name.fsproj") - CollectionAssert.AreEqual (["Test2File2.fs"; "Test2File1.fs"], opts.SourceFiles |> Array.map Path.GetFileName) - CollectionAssert.IsEmpty (getCompiledFilenames opts.OtherOptions) - -[] -let ``Project file parsing -- report files``() = - let programFilesx86Folder = System.Environment.GetEnvironmentVariable("PROGRAMFILES(X86)") - if not runningOnMono then - - let dirRefs = programFilesx86Folder + @"\Reference Assemblies\Microsoft\FSharp\" - printfn "Enumerating %s" dirRefs - if Directory.Exists(dirRefs) then - for f in Directory.EnumerateFiles(dirRefs,"*",SearchOption.AllDirectories) do - printfn "File: %s" f - - let dir40 = programFilesx86Folder + @"\Microsoft SDKs\F#\4.0\" - printfn "Enumerating %s" dir40 - if Directory.Exists(dir40) then - for f in Directory.EnumerateFiles(dir40,"*",SearchOption.AllDirectories) do - printfn "File: %s" f - - let dir41 = programFilesx86Folder + @"\Microsoft SDKs\F#\4.1\" - printfn "Enumerating %s" dir41 - if Directory.Exists(dir41) then - for f in Directory.EnumerateFiles(dir41,"*",SearchOption.AllDirectories) do - printfn "File: %s" f - -[] -let ``Test OtherOptions order for GetProjectOptionsFromScript`` () = - let test scriptName expected2 = - let scriptPath = __SOURCE_DIRECTORY__ + @"/data/ScriptProject/" + scriptName + ".fsx" - let scriptSource = File.ReadAllText scriptPath - let projOpts, _diagnostics = checker.GetProjectOptionsFromScript(scriptPath, scriptSource) |> Async.RunSynchronously - projOpts.OtherOptions - |> Array.map (fun s -> if s.StartsWith "--" then s else Path.GetFileNameWithoutExtension s) - |> Array.forall (fun s -> Set.contains s expected2) - |> shouldEqual true - - let otherArgs = [|"--noframework"; "--warn:3"; "System.Numerics"; "System.ValueTuple"; "mscorlib"; "FSharp.Core"; "System"; "System.Xml"; "System.Runtime.Remoting"; "System.Runtime.Serialization.Formatters.Soap"; "System.Data"; "System.Drawing"; "System.Core"; "System.Runtime"; "System.Linq"; "System.Reflection"; "System.Linq.Expressions"; "System.Threading.Tasks"; "System.IO"; "System.Net.Requests"; "System.Collections"; "System.Runtime.Numerics"; "System.Threading"; "System.Web"; "System.Web.Services"; "System.Windows.Forms"; "FSharp.Compiler.Interactive.Settings"|] |> Set.ofArray - - test "Main1" otherArgs - test "Main2" otherArgs - test "Main3" otherArgs - test "Main4" otherArgs - test "MainBad" otherArgs - - -#endif - -[] -let ``Test SourceFiles order for GetProjectOptionsFromScript`` () = // See #594 - let test scriptName expected = - let scriptPath = __SOURCE_DIRECTORY__ + @"/data/ScriptProject/" + scriptName + ".fsx" - let scriptSource = File.ReadAllText scriptPath - let projOpts, _diagnostics = - checker.GetProjectOptionsFromScript(scriptPath, FSharp.Compiler.Text.SourceText.ofString scriptSource) - |> Async.RunSynchronously - projOpts.SourceFiles - |> Array.map Path.GetFileNameWithoutExtension - |> shouldEqual expected - test "Main1" [|"BaseLib1"; "Lib1"; "Lib2"; "Main1"|] - test "Main2" [|"BaseLib1"; "Lib1"; "Lib2"; "Lib3"; "Main2"|] - test "Main3" [|"Lib3"; "Lib4"; "Main3"|] - test "Main4" [|"BaseLib2"; "Lib5"; "BaseLib1"; "Lib1"; "Lib2"; "Main4"|] - test "MainBad" [|"MainBad"|] - -[] -#if NETCOREAPP -[] -#endif -let ``Script load closure project`` () = - let fileName1 = Path.GetTempPath() + Path.DirectorySeparatorChar.ToString() + "Impl.fs" - let fileName2 = Path.ChangeExtension(Path.GetTempFileName(), ".fsx") - - let fileSource1Text = """ -module ImplFile - -#if INTERACTIVE -let x = 42 -#endif -""" - let fileSource1 = FSharp.Compiler.Text.SourceText.ofString fileSource1Text - let fileSource2Text = """ -#load "Impl.fs" -ImplFile.x -""" - let fileSource2 = FSharp.Compiler.Text.SourceText.ofString fileSource2Text - File.WriteAllText(fileName1, fileSource1Text) - File.WriteAllText(fileName2, fileSource2Text) - - printfn "------Starting Script load closure project----" - printfn "Getting project options..." - let projectOptions, diagnostics = - checker.GetProjectOptionsFromScript(fileName2, fileSource2, useFsiAuxLib=false) |> Async.RunSynchronously - for d in diagnostics do - printfn "ERROR: %A" d - diagnostics.IsEmpty |> shouldEqual true - - printfn "Parse and check..." - let _, checkResults = - checker.ParseAndCheckFileInProject(fileName2, 0, fileSource2, projectOptions) |> Async.RunSynchronously - - match checkResults with - | FSharpCheckFileAnswer.Succeeded results -> - results.Errors |> shouldEqual [| |] - | _ -> failwith "type check was aborted" - - printfn "Getting parsing options..." - let parsingOptions, diagnostics = checker.GetParsingOptionsFromProjectOptions(projectOptions) - for d in diagnostics do - printfn "ERROR: %A" d - diagnostics.IsEmpty |> shouldEqual true - - printfn "Parsing file..." - let parseResults = checker.ParseFile(fileName1, fileSource1, parsingOptions) |> Async.RunSynchronously - printfn "Checking parsetree..." - parseResults.ParseTree.IsSome |> shouldEqual true - printfn "Checking decls..." - match parseResults.ParseTree.Value with - | ParsedInput.ImplFile (ParsedImplFileInput (_, _, _, _, _, modules, _)) -> - let (SynModuleOrNamespace (_, _, _, decls, _, _, _, _)) = modules.Head - decls.Length |> shouldEqual 1 - | _ -> failwith "got sig file" - printfn "------Finished Script load closure project----" diff --git a/vsintegration/Utils/LanguageServiceProfiling/LanguageServiceProfiling.fsproj b/vsintegration/Utils/LanguageServiceProfiling/LanguageServiceProfiling.fsproj index 1b2f4b81dde..256f7a68947 100644 --- a/vsintegration/Utils/LanguageServiceProfiling/LanguageServiceProfiling.fsproj +++ b/vsintegration/Utils/LanguageServiceProfiling/LanguageServiceProfiling.fsproj @@ -11,7 +11,6 @@ - diff --git a/vsintegration/Utils/LanguageServiceProfiling/ProjectCracker.fs b/vsintegration/Utils/LanguageServiceProfiling/ProjectCracker.fs deleted file mode 100644 index 787527bbe95..00000000000 --- a/vsintegration/Utils/LanguageServiceProfiling/ProjectCracker.fs +++ /dev/null @@ -1,2 +0,0 @@ -namespace FSharp.Compiler.SourceCodeServices.ProjectCrackerTool - diff --git a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj index 9598b23b5c2..3692a280de6 100644 --- a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj +++ b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj @@ -7,7 +7,6 @@ x86 Library $(NoWarn);44;58;75;3005 - NO_PROJECTCRACKER;$(DefineConstants) true true $(SystemValueTupleVersion) @@ -92,9 +91,6 @@ CompilerService\CSharpProjectAnalysis.fs - - CompilerService\ProjectOptionsTests.fs - CompilerService\StructureTests.fs From b328e208c9d1b7fede214df8bde208a5a2da1138 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Mon, 20 Jan 2020 17:38:07 +0100 Subject: [PATCH 03/14] cleanup begin / end (#8290) --- src/fsharp/IlxGen.fs | 50 +++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index c39fad857fe..6b0228ea024 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -2786,32 +2786,30 @@ and GenNewArray cenv cgbuf eenv (elems: Expr list, elemTy, m) sequel = GenNewArraySimple cenv cgbuf eenv (elems, elemTy, m) sequel and GenCoerce cenv cgbuf eenv (e, tgty, m, srcty) sequel = - let g = cenv.g - // Is this an upcast? - if TypeRelations.TypeDefinitelySubsumesTypeNoCoercion 0 g cenv.amap m tgty srcty && - // Do an extra check - should not be needed - TypeRelations.TypeFeasiblySubsumesType 0 g cenv.amap m tgty TypeRelations.NoCoerce srcty then - begin - if (isInterfaceTy g tgty) then ( - GenExpr cenv cgbuf eenv SPSuppress e Continue - let ilToTy = GenType cenv.amap m eenv.tyenv tgty - // Section "III.1.8.1.3 Merging stack states" of ECMA-335 implies that no unboxing - // is required, but we still push the coerced type on to the code gen buffer. - CG.EmitInstrs cgbuf (pop 1) (Push [ilToTy]) [] - GenSequel cenv eenv.cloc cgbuf sequel - ) else ( - GenExpr cenv cgbuf eenv SPSuppress e sequel - ) - end - else - GenExpr cenv cgbuf eenv SPSuppress e Continue - if not (isObjTy g srcty) then - let ilFromTy = GenType cenv.amap m eenv.tyenv srcty - CG.EmitInstrs cgbuf (pop 1) (Push [g.ilg.typ_Object]) [ I_box ilFromTy ] - if not (isObjTy g tgty) then - let ilToTy = GenType cenv.amap m eenv.tyenv tgty - CG.EmitInstrs cgbuf (pop 1) (Push [ilToTy]) [ I_unbox_any ilToTy ] - GenSequel cenv eenv.cloc cgbuf sequel + let g = cenv.g + // Is this an upcast? + if TypeRelations.TypeDefinitelySubsumesTypeNoCoercion 0 g cenv.amap m tgty srcty && + // Do an extra check - should not be needed + TypeRelations.TypeFeasiblySubsumesType 0 g cenv.amap m tgty TypeRelations.NoCoerce srcty + then + if isInterfaceTy g tgty then + GenExpr cenv cgbuf eenv SPSuppress e Continue + let ilToTy = GenType cenv.amap m eenv.tyenv tgty + // Section "III.1.8.1.3 Merging stack states" of ECMA-335 implies that no unboxing + // is required, but we still push the coerced type on to the code gen buffer. + CG.EmitInstrs cgbuf (pop 1) (Push [ilToTy]) [] + GenSequel cenv eenv.cloc cgbuf sequel + else + GenExpr cenv cgbuf eenv SPSuppress e sequel + else + GenExpr cenv cgbuf eenv SPSuppress e Continue + if not (isObjTy g srcty) then + let ilFromTy = GenType cenv.amap m eenv.tyenv srcty + CG.EmitInstrs cgbuf (pop 1) (Push [g.ilg.typ_Object]) [ I_box ilFromTy ] + if not (isObjTy g tgty) then + let ilToTy = GenType cenv.amap m eenv.tyenv tgty + CG.EmitInstrs cgbuf (pop 1) (Push [ilToTy]) [ I_unbox_any ilToTy ] + GenSequel cenv eenv.cloc cgbuf sequel and GenReraise cenv cgbuf eenv (rtnty, m) sequel = let ilReturnTy = GenType cenv.amap m eenv.tyenv rtnty From 06e0ed450a6ed8ba91b13dd9bcaf7ca119fa09d1 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Mon, 20 Jan 2020 17:41:27 +0100 Subject: [PATCH 04/14] Calculate final only when needed (#8284) --- src/fsharp/AugmentWithHashCompare.fs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/fsharp/AugmentWithHashCompare.fs b/src/fsharp/AugmentWithHashCompare.fs index ce562dedaa4..03ea427a06d 100644 --- a/src/fsharp/AugmentWithHashCompare.fs +++ b/src/fsharp/AugmentWithHashCompare.fs @@ -883,11 +883,15 @@ let nonVirtualMethod c : ValMemberInfo = let unitArg = ValReprInfo.unitArgData let unaryArg = [ ValReprInfo.unnamedTopArg ] let tupArg = [ [ ValReprInfo.unnamedTopArg1; ValReprInfo.unnamedTopArg1 ] ] -let mkValSpec g (tcref: TyconRef) tmty vis slotsig methn ty argData = +let mkValSpec g (tcref: TyconRef) tmty vis slotsig methn ty argData = let m = tcref.Range let tps = tcref.Typars m - let final = isUnionTy g tmty || isRecdTy g tmty || isStructTy g tmty - let membInfo = match slotsig with None -> nonVirtualMethod tcref | Some slotsig -> slotImplMethod(final, tcref, slotsig) + let membInfo = + match slotsig with + | None -> nonVirtualMethod tcref + | Some slotsig -> + let final = isUnionTy g tmty || isRecdTy g tmty || isStructTy g tmty + slotImplMethod(final, tcref, slotsig) let inl = ValInline.Optional let args = ValReprInfo.unnamedTopArg :: argData let topValInfo = Some (ValReprInfo (ValReprInfo.InferTyparInfo tps, args, ValReprInfo.unnamedRetVal)) @@ -899,8 +903,8 @@ let MakeValsForCompareAugmentation g (tcref: TyconRef) = let tps = tcref.Typars m let vis = tcref.TypeReprAccessibility - mkValSpec g tcref tmty vis (Some(mkIComparableCompareToSlotSig g)) "CompareTo" (tps +-> (mkCompareObjTy g tmty)) unaryArg, - mkValSpec g tcref tmty vis (Some(mkGenericIComparableCompareToSlotSig g tmty)) "CompareTo" (tps +-> (mkCompareTy g tmty)) unaryArg + mkValSpec g tcref tmty vis (Some(mkIComparableCompareToSlotSig g)) "CompareTo" (tps +-> (mkCompareObjTy g tmty)) unaryArg, + mkValSpec g tcref tmty vis (Some(mkGenericIComparableCompareToSlotSig g tmty)) "CompareTo" (tps +-> (mkCompareTy g tmty)) unaryArg let MakeValsForCompareWithComparerAugmentation g (tcref: TyconRef) = let m = tcref.Range @@ -915,15 +919,15 @@ let MakeValsForEqualsAugmentation g (tcref: TyconRef) = let vis = tcref.TypeReprAccessibility let tps = tcref.Typars m - let objEqualsVal = mkValSpec g tcref tmty vis (Some(mkEqualsSlotSig g)) "Equals" (tps +-> (mkEqualsObjTy g tmty)) unaryArg - let nocEqualsVal = mkValSpec g tcref tmty vis (if tcref.Deref.IsExceptionDecl then None else Some(mkGenericIEquatableEqualsSlotSig g tmty)) "Equals" (tps +-> (mkEqualsTy g tmty)) unaryArg + let objEqualsVal = mkValSpec g tcref tmty vis (Some(mkEqualsSlotSig g)) "Equals" (tps +-> (mkEqualsObjTy g tmty)) unaryArg + let nocEqualsVal = mkValSpec g tcref tmty vis (if tcref.Deref.IsExceptionDecl then None else Some(mkGenericIEquatableEqualsSlotSig g tmty)) "Equals" (tps +-> (mkEqualsTy g tmty)) unaryArg objEqualsVal, nocEqualsVal let MakeValsForEqualityWithComparerAugmentation g (tcref: TyconRef) = let _, tmty = mkMinimalTy g tcref let vis = tcref.TypeReprAccessibility let tps = tcref.Typars tcref.Range - let objGetHashCodeVal = mkValSpec g tcref tmty vis (Some(mkGetHashCodeSlotSig g)) "GetHashCode" (tps +-> (mkHashTy g tmty)) unitArg + let objGetHashCodeVal = mkValSpec g tcref tmty vis (Some(mkGetHashCodeSlotSig g)) "GetHashCode" (tps +-> (mkHashTy g tmty)) unitArg let withcGetHashCodeVal = mkValSpec g tcref tmty vis (Some(mkIStructuralEquatableGetHashCodeSlotSig g)) "GetHashCode" (tps +-> (mkHashWithComparerTy g tmty)) unaryArg let withcEqualsVal = mkValSpec g tcref tmty vis (Some(mkIStructuralEquatableEqualsSlotSig g)) "Equals" (tps +-> (mkEqualsWithComparerTy g tmty)) tupArg objGetHashCodeVal, withcGetHashCodeVal, withcEqualsVal From 6b189042e9402ea604b4a3910926b00ab07cc1ff Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Mon, 20 Jan 2020 18:10:36 +0100 Subject: [PATCH 05/14] tryDestAppTy instead of isAppTy (#8285) --- src/fsharp/NameResolution.fs | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index 10e330f2070..a63c8e6e138 100644 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -536,11 +536,11 @@ let ExtensionPropInfosOfTypeInScope collectionSettings (infoReader:InfoReader) ( let extMemsFromHierarchy = infoReader.GetEntireTypeHierarchy(AllowMultiIntfInstantiations.Yes, m, ty) |> List.collect (fun ty -> - if isAppTy g ty then - let tcref = tcrefOfAppTy g ty + match tryDestAppTy g ty with + | ValueSome tcref -> let extMemInfos = nenv.eIndexedExtensionMembers.Find tcref SelectPropInfosFromExtMembers infoReader ad optFilter ty m extMemInfos - else []) + | _ -> []) extMemsDangling @ extMemsFromHierarchy @@ -606,11 +606,11 @@ let ExtensionMethInfosOfTypeInScope (collectionSettings: ResultCollectionSetting infoReader.GetEntireTypeHierarchy(AllowMultiIntfInstantiations.Yes, m, ty) |> List.collect (fun ty -> let g = infoReader.g - if isAppTy g ty then - let tcref = tcrefOfAppTy g ty + match tryDestAppTy g ty with + | ValueSome tcref -> let extValRefs = nenv.eIndexedExtensionMembers.Find tcref SelectMethInfosFromExtMembers infoReader optFilter ty m extValRefs - else []) + | _ -> []) extMemsDangling @ extMemsFromHierarchy /// Get all the available methods of a type (both intrinsic and extension) @@ -2352,10 +2352,11 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf match lookupKind with | LookupKind.Expr | LookupKind.Pattern -> - if isAppTy g ty then - let tcref = tcrefOfAppTy g ty + match tryDestAppTy g ty with + | ValueSome tcref -> for uc in tcref.UnionCasesArray do addToBuffer uc.DisplayName + | _ -> () | _ -> () raze (UndefinedName (depth, FSComp.SR.undefinedNameFieldConstructorOrMember, id, suggestMembers)) @@ -2363,7 +2364,12 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf and ResolveLongIdentInNestedTypes (ncenv: NameResolver) nenv lookupKind resInfo depth id m ad (id2: Ident) (rest: Ident list) findFlag typeNameResInfo tys = tys |> CollectAtMostOneResult (fun ty -> - let resInfo = if isAppTy ncenv.g ty then resInfo.AddEntity(id.idRange, tcrefOfAppTy ncenv.g ty) else resInfo + let resInfo = + match tryDestAppTy ncenv.g ty with + | ValueSome tcref -> + resInfo.AddEntity(id.idRange, tcref) + | _ -> + resInfo ResolveLongIdentInTypePrim ncenv nenv lookupKind resInfo depth m ad id2 rest findFlag typeNameResInfo ty |> AtMostOneResult m) @@ -2878,8 +2884,10 @@ let ResolvePatternLongIdent sink (ncenv: NameResolver) warnOnUpper newDef m ad n // X.ListEnumerator // does not resolve // let ResolveNestedTypeThroughAbbreviation (ncenv: NameResolver) (tcref: TyconRef) m = - if tcref.IsTypeAbbrev && tcref.Typars(m).IsEmpty && isAppTy ncenv.g tcref.TypeAbbrev.Value && isNil (argsOfAppTy ncenv.g tcref.TypeAbbrev.Value) then - tcrefOfAppTy ncenv.g tcref.TypeAbbrev.Value + if tcref.IsTypeAbbrev && tcref.Typars(m).IsEmpty then + match tryAppTy ncenv.g tcref.TypeAbbrev.Value with + | ValueSome (abbrevTcref, []) -> abbrevTcref + | _ -> tcref else tcref @@ -3527,7 +3535,10 @@ let ItemOfTyconRef ncenv m (x: TyconRef) = Item.Types (x.DisplayName, [FreshenTycon ncenv m x]) let ItemOfTy g x = - let nm = if isAppTy g x then (tcrefOfAppTy g x).DisplayName else "?" + let nm = + match tryDestAppTy g x with + | ValueSome tcref -> tcref.DisplayName + | _ -> "?" Item.Types (nm, [x]) // Filter out 'PrivateImplementationDetail' classes From 6839169d45c110c8683f50119ad585ce510e9c27 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 20 Jan 2020 17:24:28 +0000 Subject: [PATCH 06/14] clarify language feature list (#8289) --- src/fsharp/LanguageFeatures.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/LanguageFeatures.fs b/src/fsharp/LanguageFeatures.fs index eeac561751a..2170cee8f75 100644 --- a/src/fsharp/LanguageFeatures.fs +++ b/src/fsharp/LanguageFeatures.fs @@ -55,11 +55,11 @@ type LanguageVersion (specifiedVersionAsString) = // F# 5.0 LanguageFeature.FixedIndexSlice3d4d, languageVersion50 LanguageFeature.FromEndSlicing, languageVersion50 + LanguageFeature.DotlessFloat32Literal, languageVersion50 // F# preview LanguageFeature.NameOf, previewVersion LanguageFeature.OpenStaticClasses, previewVersion - LanguageFeature.DotlessFloat32Literal, languageVersion50 LanguageFeature.PackageManagement, previewVersion ] From 1069553d1ebb5e335f1a58f75727126263e93d2c Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Mon, 20 Jan 2020 19:51:02 +0100 Subject: [PATCH 07/14] cleanup begin / end (#8292) --- src/absil/ilread.fs | 40 ++++---- src/fsharp/IlxGen.fs | 211 ++++++++++++++++++++----------------------- 2 files changed, 117 insertions(+), 134 deletions(-) diff --git a/src/absil/ilread.fs b/src/absil/ilread.fs index aa4438cedfa..d016c2423ea 100644 --- a/src/absil/ilread.fs +++ b/src/absil/ilread.fs @@ -761,37 +761,33 @@ let seekReadIndexedRows (numRows, rowReader, keyFunc, keyComparer, binaryChop, r // now read off rows, forward and backwards let mid = (low + high) / 2 // read forward - begin - let mutable fin = false - let mutable curr = mid - while not fin do - if curr > numRows then - fin <- true - else - let currrow = rowReader curr - if keyComparer (keyFunc currrow) = 0 then - res <- rowConverter currrow :: res - else - fin <- true - curr <- curr + 1 - done - end + let mutable fin = false + let mutable curr = mid + while not fin do + if curr > numRows then + fin <- true + else + let currrow = rowReader curr + if keyComparer (keyFunc currrow) = 0 then + res <- rowConverter currrow :: res + else + fin <- true + curr <- curr + 1 + res <- List.rev res // read backwards - begin - let mutable fin = false - let mutable curr = mid - 1 - while not fin do - if curr = 0 then + let mutable fin = false + let mutable curr = mid - 1 + while not fin do + if curr = 0 then fin <- true - else + else let currrow = rowReader curr if keyComparer (keyFunc currrow) = 0 then res <- rowConverter currrow :: res else fin <- true curr <- curr - 1 - end // sanity check #if CHECKING if checking then diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 6b0228ea024..bae42ad081f 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -3396,65 +3396,63 @@ and GenTryCatch cenv cgbuf eenv (e1, vf: Val, ef, vh: Val, eh, m, resty, spTry, let startOfFilter = CG.GenerateMark cgbuf "startOfFilter" let afterFilter = CG.GenerateDelayMark cgbuf "afterFilter" let (sequelOnBranches, afterJoin, stackAfterJoin, sequelAfterJoin) = GenJoinPoint cenv cgbuf "filter" eenv g.int_ty m EndFilter - begin - // We emit the sequence point for the 'with' keyword span on the start of the filter - // block. However the targets of the filter block pattern matching should not get any - // sequence points (they will be 'true'/'false' values indicating if the exception has been - // caught or not). - // - // The targets of the handler block DO get sequence points. Thus the expected behaviour - // for a try/with with a complex pattern is that we hit the "with" before the filter is run - // and then jump to the handler for the successful catch (or continue with exception handling - // if the filter fails) - match spWith with - | SequencePointAtWith m -> CG.EmitSeqPoint cgbuf m - | NoSequencePointAtWith -> () - - - CG.SetStack cgbuf [g.ilg.typ_Object] - let _, eenvinner = AllocLocalVal cenv cgbuf vf eenvinner None (startOfFilter, afterFilter) - CG.EmitInstr cgbuf (pop 1) (Push [g.iltyp_Exception]) (I_castclass g.iltyp_Exception) - - GenStoreVal cenv cgbuf eenvinner vf.Range vf - - // Why SPSuppress? Because we do not emit a sequence point at the start of the List.filter - we've already put one on - // the 'with' keyword above - GenExpr cenv cgbuf eenvinner SPSuppress ef sequelOnBranches - CG.SetMarkToHere cgbuf afterJoin - CG.SetStack cgbuf stackAfterJoin - GenSequel cenv eenv.cloc cgbuf sequelAfterJoin - end + // We emit the sequence point for the 'with' keyword span on the start of the filter + // block. However the targets of the filter block pattern matching should not get any + // sequence points (they will be 'true'/'false' values indicating if the exception has been + // caught or not). + // + // The targets of the handler block DO get sequence points. Thus the expected behaviour + // for a try/with with a complex pattern is that we hit the "with" before the filter is run + // and then jump to the handler for the successful catch (or continue with exception handling + // if the filter fails) + match spWith with + | SequencePointAtWith m -> CG.EmitSeqPoint cgbuf m + | NoSequencePointAtWith -> () + + + CG.SetStack cgbuf [g.ilg.typ_Object] + let _, eenvinner = AllocLocalVal cenv cgbuf vf eenvinner None (startOfFilter, afterFilter) + CG.EmitInstr cgbuf (pop 1) (Push [g.iltyp_Exception]) (I_castclass g.iltyp_Exception) + + GenStoreVal cenv cgbuf eenvinner vf.Range vf + + // Why SPSuppress? Because we do not emit a sequence point at the start of the List.filter - we've already put one on + // the 'with' keyword above + GenExpr cenv cgbuf eenvinner SPSuppress ef sequelOnBranches + CG.SetMarkToHere cgbuf afterJoin + CG.SetStack cgbuf stackAfterJoin + GenSequel cenv eenv.cloc cgbuf sequelAfterJoin let endOfFilter = CG.GenerateMark cgbuf "endOfFilter" let filterMarks = (startOfFilter.CodeLabel, endOfFilter.CodeLabel) CG.SetMarkToHere cgbuf afterFilter let startOfHandler = CG.GenerateMark cgbuf "startOfHandler" - begin - CG.SetStack cgbuf [g.ilg.typ_Object] - let _, eenvinner = AllocLocalVal cenv cgbuf vh eenvinner None (startOfHandler, afterHandler) - CG.EmitInstr cgbuf (pop 1) (Push [g.iltyp_Exception]) (I_castclass g.iltyp_Exception) - GenStoreVal cenv cgbuf eenvinner vh.Range vh - - GenExpr cenv cgbuf eenvinner SPAlways eh (LeaveHandler (false, whereToSave, afterHandler)) - end + + CG.SetStack cgbuf [g.ilg.typ_Object] + let _, eenvinner = AllocLocalVal cenv cgbuf vh eenvinner None (startOfHandler, afterHandler) + CG.EmitInstr cgbuf (pop 1) (Push [g.iltyp_Exception]) (I_castclass g.iltyp_Exception) + GenStoreVal cenv cgbuf eenvinner vh.Range vh + + GenExpr cenv cgbuf eenvinner SPAlways eh (LeaveHandler (false, whereToSave, afterHandler)) + let endOfHandler = CG.GenerateMark cgbuf "endOfHandler" let handlerMarks = (startOfHandler.CodeLabel, endOfHandler.CodeLabel) ILExceptionClause.FilterCatch(filterMarks, handlerMarks) else let startOfHandler = CG.GenerateMark cgbuf "startOfHandler" - begin - match spWith with - | SequencePointAtWith m -> CG.EmitSeqPoint cgbuf m - | NoSequencePointAtWith -> () + + match spWith with + | SequencePointAtWith m -> CG.EmitSeqPoint cgbuf m + | NoSequencePointAtWith -> () - CG.SetStack cgbuf [g.ilg.typ_Object] - let _, eenvinner = AllocLocalVal cenv cgbuf vh eenvinner None (startOfHandler, afterHandler) - CG.EmitInstr cgbuf (pop 1) (Push [g.iltyp_Exception]) (I_castclass g.iltyp_Exception) + CG.SetStack cgbuf [g.ilg.typ_Object] + let _, eenvinner = AllocLocalVal cenv cgbuf vh eenvinner None (startOfHandler, afterHandler) + CG.EmitInstr cgbuf (pop 1) (Push [g.iltyp_Exception]) (I_castclass g.iltyp_Exception) - GenStoreVal cenv cgbuf eenvinner m vh + GenStoreVal cenv cgbuf eenvinner m vh - GenExpr cenv cgbuf eenvinner SPAlways eh (LeaveHandler (false, whereToSave, afterHandler)) - end + GenExpr cenv cgbuf eenvinner SPAlways eh (LeaveHandler (false, whereToSave, afterHandler)) + let endOfHandler = CG.GenerateMark cgbuf "endOfHandler" let handlerMarks = (startOfHandler.CodeLabel, endOfHandler.CodeLabel) ILExceptionClause.TypeCatch(g.ilg.typ_Object, handlerMarks) @@ -6591,56 +6589,47 @@ and GenTopImpl cenv (mgbuf: AssemblyBuilder) mainInfoOpt eenv (TImplFile (qname, else [], [] - begin - - match mainInfoOpt with - - // Final file in .EXE - | Some mainInfo -> - - // Generate an explicit main method. If necessary, make a class constructor as - // well for the bindings earlier in the file containing the entry point. - match mgbuf.GetExplicitEntryPointInfo() with - - // Final file, explicit entry point: place the code in a .cctor, and add code to main that forces the .cctor (if topCode has initialization effect). - | Some tref -> - if doesSomething then - lazyInitInfo.Add (fun fspec feefee seqpt -> - // This adds the explicit init of the .cctor to the explicit entry point main method - mgbuf.AddExplicitInitToSpecificMethodDef((fun md -> md.IsEntryPoint), tref, fspec, GenPossibleILSourceMarker cenv m, feefee, seqpt)) - - let cctorMethDef = mkILClassCtor (MethodBody.IL topCode) - mgbuf.AddMethodDef(initClassTy.TypeRef, cctorMethDef) - // Final file, implicit entry point. We generate no .cctor. - // void main@() { - // - // } - | None -> - - let ilAttrs = mkILCustomAttrs (GenAttrs cenv eenv mainInfo) - if not cenv.opts.isInteractive && not doesSomething then - let errorM = m.EndRange - warning (Error(FSComp.SR.ilMainModuleEmpty(), errorM)) - - // generate main@ - let ilMainMethodDef = - let mdef = mkILNonGenericStaticMethod(mainMethName, ILMemberAccess.Public, [], mkILReturn ILType.Void, MethodBody.IL topCode) - mdef.With(isEntryPoint= true, customAttrs = ilAttrs) - - mgbuf.AddMethodDef(initClassTy.TypeRef, ilMainMethodDef) - - - // Library file: generate an optional .cctor if topCode has initialization effect - | None -> + match mainInfoOpt with + // Final file in .EXE + | Some mainInfo -> + // Generate an explicit main method. If necessary, make a class constructor as + // well for the bindings earlier in the file containing the entry point. + match mgbuf.GetExplicitEntryPointInfo() with + // Final file, explicit entry point: place the code in a .cctor, and add code to main that forces the .cctor (if topCode has initialization effect). + | Some tref -> if doesSomething then + lazyInitInfo.Add (fun fspec feefee seqpt -> + // This adds the explicit init of the .cctor to the explicit entry point main method + mgbuf.AddExplicitInitToSpecificMethodDef((fun md -> md.IsEntryPoint), tref, fspec, GenPossibleILSourceMarker cenv m, feefee, seqpt)) - // Add the cctor let cctorMethDef = mkILClassCtor (MethodBody.IL topCode) mgbuf.AddMethodDef(initClassTy.TypeRef, cctorMethDef) + // Final file, implicit entry point. We generate no .cctor. + // void main@() { + // + // } + | None -> + let ilAttrs = mkILCustomAttrs (GenAttrs cenv eenv mainInfo) + if not cenv.opts.isInteractive && not doesSomething then + let errorM = m.EndRange + warning (Error(FSComp.SR.ilMainModuleEmpty(), errorM)) + + // generate main@ + let ilMainMethodDef = + let mdef = mkILNonGenericStaticMethod(mainMethName, ILMemberAccess.Public, [], mkILReturn ILType.Void, MethodBody.IL topCode) + mdef.With(isEntryPoint= true, customAttrs = ilAttrs) - end + mgbuf.AddMethodDef(initClassTy.TypeRef, ilMainMethodDef) + + + // Library file: generate an optional .cctor if topCode has initialization effect + | None -> + if doesSomething then + // Add the cctor + let cctorMethDef = mkILClassCtor (MethodBody.IL topCode) + mgbuf.AddMethodDef(initClassTy.TypeRef, cctorMethDef) // Commit the directed initializations if doesSomething then @@ -7511,29 +7500,27 @@ and GenExnDef cenv mgbuf eenv m (exnc: Tycon) = let CodegenAssembly cenv eenv mgbuf fileImpls = if not (isNil fileImpls) then - let a, b = List.frontAndBack fileImpls - let eenv = List.fold (GenTopImpl cenv mgbuf None) eenv a - let eenv = GenTopImpl cenv mgbuf cenv.opts.mainMethodInfo eenv b - - // Some constructs generate residue types and bindings. Generate these now. They don't result in any - // top-level initialization code. - begin - let extraBindings = mgbuf.GrabExtraBindingsToGenerate() - //printfn "#extraBindings = %d" extraBindings.Length - if extraBindings.Length > 0 then - let mexpr = TMDefs [ for b in extraBindings -> TMDefLet(b, range0) ] - let _emptyTopInstrs, _emptyTopCode = - CodeGenMethod cenv mgbuf ([], "unused", eenv, 0, (fun cgbuf eenv -> - let lazyInitInfo = ResizeArray() - let qname = QualifiedNameOfFile(mkSynId range0 "unused") - LocalScope "module" cgbuf (fun scopeMarks -> - let eenv = AddBindingsForModuleDef (fun cloc v -> AllocTopValWithinExpr cenv cgbuf cloc scopeMarks v) eenv.cloc eenv mexpr - GenModuleDef cenv cgbuf qname lazyInitInfo eenv mexpr)), range0) - //printfn "#_emptyTopInstrs = %d" _emptyTopInstrs.Length - () - end - - mgbuf.AddInitializeScriptsInOrderToEntryPoint() + let a, b = List.frontAndBack fileImpls + let eenv = List.fold (GenTopImpl cenv mgbuf None) eenv a + let eenv = GenTopImpl cenv mgbuf cenv.opts.mainMethodInfo eenv b + + // Some constructs generate residue types and bindings. Generate these now. They don't result in any + // top-level initialization code. + let extraBindings = mgbuf.GrabExtraBindingsToGenerate() + //printfn "#extraBindings = %d" extraBindings.Length + if extraBindings.Length > 0 then + let mexpr = TMDefs [ for b in extraBindings -> TMDefLet(b, range0) ] + let _emptyTopInstrs, _emptyTopCode = + CodeGenMethod cenv mgbuf ([], "unused", eenv, 0, (fun cgbuf eenv -> + let lazyInitInfo = ResizeArray() + let qname = QualifiedNameOfFile(mkSynId range0 "unused") + LocalScope "module" cgbuf (fun scopeMarks -> + let eenv = AddBindingsForModuleDef (fun cloc v -> AllocTopValWithinExpr cenv cgbuf cloc scopeMarks v) eenv.cloc eenv mexpr + GenModuleDef cenv cgbuf qname lazyInitInfo eenv mexpr)), range0) + //printfn "#_emptyTopInstrs = %d" _emptyTopInstrs.Length + () + + mgbuf.AddInitializeScriptsInOrderToEntryPoint() //------------------------------------------------------------------------- // When generating a module we just write into mutable From fbf60bcaeb191492ff9a8ea29d986dd92c9bba30 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Mon, 20 Jan 2020 23:12:47 +0100 Subject: [PATCH 08/14] Remove tryRawToLabel (#8293) --- src/absil/ilread.fs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/absil/ilread.fs b/src/absil/ilread.fs index d016c2423ea..b9994f6418b 100644 --- a/src/absil/ilread.fs +++ b/src/absil/ilread.fs @@ -2459,15 +2459,11 @@ and seekReadImplMap (ctxt: ILMetadataReader) nm midx = and seekReadTopCode (ctxt: ILMetadataReader) pev mdv numtypars (sz: int) start seqpoints = let labelsOfRawOffsets = new Dictionary<_, _>(sz/2) let ilOffsetsOfLabels = new Dictionary<_, _>(sz/2) - let tryRawToLabel rawOffset = - match labelsOfRawOffsets.TryGetValue rawOffset with - | true, v -> Some v - | _ -> None - + let rawToLabel rawOffset = - match tryRawToLabel rawOffset with - | Some l -> l - | None -> + match labelsOfRawOffsets.TryGetValue rawOffset with + | true, l -> l + | _ -> let lab = generateCodeLabel() labelsOfRawOffsets.[rawOffset] <- lab lab @@ -2696,9 +2692,9 @@ and seekReadTopCode (ctxt: ILMetadataReader) pev mdv numtypars (sz: int) start s // the start of the next instruction referred to by the raw offset. let raw2nextLab rawOffset = let isInstrStart x = - match tryRawToLabel x with - | None -> false - | Some lab -> ilOffsetsOfLabels.ContainsKey lab + match labelsOfRawOffsets.TryGetValue x with + | true, lab -> ilOffsetsOfLabels.ContainsKey lab + | _ -> false if isInstrStart rawOffset then rawToLabel rawOffset elif isInstrStart (rawOffset+1) then rawToLabel (rawOffset+1) else failwith ("the bytecode raw offset "+string rawOffset+" did not refer either to the start or end of an instruction") From be70bd97e8ca4ce4313c9b626ad88e31ebb9c185 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 21 Jan 2020 23:44:21 +0100 Subject: [PATCH 09/14] Reduce Number of isAppTy calls (#8275) --- src/fsharp/symbols/SymbolHelpers.fs | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/fsharp/symbols/SymbolHelpers.fs b/src/fsharp/symbols/SymbolHelpers.fs index cec9bfaf52f..48a44c8abbf 100644 --- a/src/fsharp/symbols/SymbolHelpers.fs +++ b/src/fsharp/symbols/SymbolHelpers.fs @@ -839,19 +839,22 @@ module internal SymbolHelpers = // This may explore assemblies that are not in the reference set. // In this case just assume the item is not suppressed. protectAssemblyExploration true (fun () -> - match item with - | Item.Types(it, [ty]) -> - isAppTy g ty && - g.suppressed_types - |> List.exists (fun supp -> - let generalizedSupp = generalizedTyconRef supp - // check the display name is precisely the one we're suppressing - isAppTy g generalizedSupp && it = supp.DisplayName && - // check if they are the same logical type (after removing all abbreviations) - let tcr1 = tcrefOfAppTy g ty - let tcr2 = tcrefOfAppTy g generalizedSupp - tyconRefEq g tcr1 tcr2) - | _ -> false) + match item with + | Item.Types(it, [ty]) -> + match tryDestAppTy g ty with + | ValueSome tcr1 -> + g.suppressed_types + |> List.exists (fun supp -> + let generalizedSupp = generalizedTyconRef supp + // check the display name is precisely the one we're suppressing + match tryDestAppTy g generalizedSupp with + | ValueSome tcr2 -> + it = supp.DisplayName && + // check if they are the same logical type (after removing all abbreviations) + tyconRefEq g tcr1 tcr2 + | _ -> false) + | _ -> false + | _ -> false) /// Filter types that are explicitly suppressed from the IntelliSense (such as uppercase "FSharpList", "Option", etc.) let RemoveExplicitlySuppressed (g: TcGlobals) (items: ItemWithInst list) = From bb46e3788de820f53eb2b854868ebc061fda7a5e Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 21 Jan 2020 23:52:19 +0100 Subject: [PATCH 10/14] Reduce isAppTy calls in TypeDefinitelyHasEquality (#8286) --- src/fsharp/AugmentWithHashCompare.fs | 43 ++++++++++++++++------------ 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/fsharp/AugmentWithHashCompare.fs b/src/fsharp/AugmentWithHashCompare.fs index 03ea427a06d..87917c29502 100644 --- a/src/fsharp/AugmentWithHashCompare.fs +++ b/src/fsharp/AugmentWithHashCompare.fs @@ -1075,23 +1075,28 @@ let MakeBindingsForEqualsAugmentation (g: TcGlobals) (tycon: Tycon) = elif tycon.IsRecordTycon || tycon.IsStructOrEnumTycon then mkEquals mkRecdEquality else [] -let rec TypeDefinitelyHasEquality g ty = - if isAppTy g ty && HasFSharpAttribute g g.attrib_NoEqualityAttribute (tcrefOfAppTy g ty).Attribs then +let rec TypeDefinitelyHasEquality g ty = + let appTy = tryAppTy g ty + match appTy with + | ValueSome(tcref,_) when HasFSharpAttribute g g.attrib_NoEqualityAttribute tcref.Attribs -> false - elif isTyparTy g ty && - (destTyparTy g ty).Constraints |> List.exists (function TyparConstraint.SupportsEquality _ -> true | _ -> false) then - true - else - match ty with - | SpecialEquatableHeadType g tinst -> - tinst |> List.forall (TypeDefinitelyHasEquality g) - | SpecialNotEquatableHeadType g _ -> - false - | _ -> - // The type is equatable because it has Object.Equals(...) - isAppTy g ty && - let tcref, tinst = destAppTy g ty - // Give a good error for structural types excluded from the equality relation because of their fields - not (TyconIsCandidateForAugmentationWithEquals g tcref.Deref && Option.isNone tcref.GeneratedHashAndEqualsWithComparerValues) && - // Check the (possibly inferred) structural dependencies - (tinst, tcref.TyparsNoRange) ||> List.lengthsEqAndForall2 (fun ty tp -> not tp.EqualityConditionalOn || TypeDefinitelyHasEquality g ty) + | _ -> + if isTyparTy g ty && + (destTyparTy g ty).Constraints |> List.exists (function TyparConstraint.SupportsEquality _ -> true | _ -> false) then + true + else + match ty with + | SpecialEquatableHeadType g tinst -> + tinst |> List.forall (TypeDefinitelyHasEquality g) + | SpecialNotEquatableHeadType g _ -> + false + | _ -> + // The type is equatable because it has Object.Equals(...) + match appTy with + | ValueSome(tcref,tinst) -> + // Give a good error for structural types excluded from the equality relation because of their fields + not (TyconIsCandidateForAugmentationWithEquals g tcref.Deref && Option.isNone tcref.GeneratedHashAndEqualsWithComparerValues) && + // Check the (possibly inferred) structural dependencies + (tinst, tcref.TyparsNoRange) + ||> List.lengthsEqAndForall2 (fun ty tp -> not tp.EqualityConditionalOn || TypeDefinitelyHasEquality g ty) + | _ -> false From a373efb222c5ea8649e2282e9d57b903f32619c2 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Tue, 21 Jan 2020 14:56:06 -0800 Subject: [PATCH 11/14] Fixed consuming CSharp interface with an inref parameter (#8287) * Added inref interop test * Fixed inref interop when creating a slot sig * 3.1 to 3.0 --- src/fsharp/infos.fs | 2 +- tests/fsharp/Compiler/CompilerAssert.fs | 21 +++++++++- tests/fsharp/Compiler/Language/ByrefTests.fs | 41 ++++++++++++++++++++ tests/fsharp/Compiler/Utilities.fs | 4 +- 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index 1db4e36b356..63db80bae85 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -1536,7 +1536,7 @@ type MethInfo = let formalRetTy = ImportReturnTypeFromMetadata amap m ilminfo.RawMetadata.Return.Type ilminfo.RawMetadata.Return.CustomAttrs ftinfo.ILScopeRef ftinfo.TypeInstOfRawMetadata formalMethTyparTys let formalParams = [ [ for p in ilminfo.RawMetadata.Parameters do - let paramType = ImportILTypeFromMetadata amap m ftinfo.ILScopeRef ftinfo.TypeInstOfRawMetadata formalMethTyparTys p.Type + let paramType = ImportILTypeFromMetadataWithAttributes amap m ftinfo.ILScopeRef ftinfo.TypeInstOfRawMetadata formalMethTyparTys p.Type p.CustomAttrs yield TSlotParam(p.Name, paramType, p.IsIn, p.IsOut, p.IsOptional, []) ] ] formalRetTy, formalParams #if !NO_EXTENSIONTYPING diff --git a/tests/fsharp/Compiler/CompilerAssert.fs b/tests/fsharp/Compiler/CompilerAssert.fs index 9f0bc09553b..ef0e591a0c1 100644 --- a/tests/fsharp/Compiler/CompilerAssert.fs +++ b/tests/fsharp/Compiler/CompilerAssert.fs @@ -8,6 +8,7 @@ open System.Diagnostics open System.IO open System.Text open System.Diagnostics +open System.Collections.Generic open System.Reflection open FSharp.Compiler.Text open FSharp.Compiler.SourceCodeServices @@ -17,6 +18,9 @@ open System.Runtime.Loader #endif open NUnit.Framework open System.Reflection.Emit +open Microsoft.CodeAnalysis +open Microsoft.CodeAnalysis.CSharp +open FSharp.Compiler.UnitTests.Utilities [] type ILVerifier (dllFilePath: string) = @@ -52,12 +56,18 @@ type CompileOutput = | Library | Exe -type CompilationReference = private CompilationReference of Compilation * staticLink: bool with +type CompilationReference = + private + | CompilationReference of Compilation * staticLink: bool + | TestCompilationReference of TestCompilation static member CreateFSharp(cmpl: Compilation, ?staticLink) = let staticLink = defaultArg staticLink false CompilationReference(cmpl, staticLink) + static member Create(cmpl: TestCompilation) = + TestCompilationReference cmpl + and Compilation = private Compilation of string * SourceKind * CompileOutput * options: string[] * CompilationReference list with static member Create(source, sourceKind, output, ?options, ?cmplRefs) = @@ -257,7 +267,14 @@ let main argv = 0""" |> List.map (fun cmpl -> match cmpl with | CompilationReference (cmpl, staticLink) -> - compileCompilationAux disposals ignoreWarnings cmpl, staticLink) + compileCompilationAux disposals ignoreWarnings cmpl, staticLink + | TestCompilationReference (cmpl) -> + let tmp = Path.GetTempFileName() + disposals.Add({ new IDisposable with + member _.Dispose() = + try File.Delete tmp with | _ -> () }) + cmpl.EmitAsFile tmp + (([||], tmp), []), false) let compilationRefs = compiledRefs diff --git a/tests/fsharp/Compiler/Language/ByrefTests.fs b/tests/fsharp/Compiler/Language/ByrefTests.fs index 2797125d791..d09f9f4cf24 100644 --- a/tests/fsharp/Compiler/Language/ByrefTests.fs +++ b/tests/fsharp/Compiler/Language/ByrefTests.fs @@ -4,6 +4,7 @@ namespace FSharp.Compiler.UnitTests open NUnit.Framework open FSharp.Compiler.SourceCodeServices +open FSharp.Compiler.UnitTests.Utilities [] module ByrefTests = @@ -195,4 +196,44 @@ let test1 () = "The value has been copied to ensure the original is not mutated by this operation or because the copy is implicit when returning a struct from a member and another member is then accessed" ) |] +#endif + +#if NETCOREAPP + [] + let ``Consume CSharp interface with a method that has a readonly byref`` () = + let cs = + """ +using System; +using System.Buffers; + +namespace Example +{ + public interface IMessageReader + { + bool TryParseMessage(in byte input); + } +} + """ + let fs = + """ +module Module1 + +open Example + +type MyClass() = + + interface IMessageReader with + member this.TryParseMessage(input: inref): bool = + failwith "Not Implemented" + """ + + let csCmpl = + CompilationUtil.CreateCSharpCompilation(cs, CSharpLanguageVersion.CSharp8, TargetFramework.NetCoreApp30) + |> CompilationReference.Create + + let fsCmpl = + Compilation.Create(fs, Fsx, Library, cmplRefs = [csCmpl]) + + CompilerAssert.Compile fsCmpl + #endif \ No newline at end of file diff --git a/tests/fsharp/Compiler/Utilities.fs b/tests/fsharp/Compiler/Utilities.fs index 29de21ad3e3..b55707fdb4e 100644 --- a/tests/fsharp/Compiler/Utilities.fs +++ b/tests/fsharp/Compiler/Utilities.fs @@ -120,7 +120,7 @@ type CompilationUtil private () = [ CSharpSyntaxTree.ParseText (source, CSharpParseOptions lv) ], references.As().AddRange additionalReferences, CSharpCompilationOptions (OutputKind.DynamicallyLinkedLibrary)) - Some (TestCompilation.CSharp (c, flags)) + TestCompilation.CSharp (c, flags) static member CreateILCompilation (source: string) = let compute = @@ -139,4 +139,4 @@ type CompilationUtil private () = try File.Delete ilFilePath with | _ -> () try File.Delete tmp with | _ -> () try File.Delete dllFilePath with | _ -> () - Some (TestCompilation.IL (source, compute)) \ No newline at end of file + TestCompilation.IL (source, compute) \ No newline at end of file From d3d5e30852454146876dc3af1f3e6ff21fdd67da Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Tue, 21 Jan 2020 14:57:41 -0800 Subject: [PATCH 12/14] Merge dependency manager and fsi script testing (#8276) * Merge dependency manager and fsi script testing * Don't forget Linux Duh!!! --- FSharp.sln | 15 ----------- VisualFSharp.sln | 15 ----------- eng/Build.ps1 | 12 --------- eng/build.sh | 1 - .../DependencyManagerInteractiveTests.fs | 0 .../DependencyManagerLineParserTests.fs | 0 ...ompiler.Private.Scripting.UnitTests.fsproj | 2 ++ .../Directory.Build.props | 9 ------- .../FSharp.DependencyManager.UnitTests.fsproj | 25 ------------------- 9 files changed, 2 insertions(+), 77 deletions(-) rename tests/{FSharp.DependencyManager.UnitTests => FSharp.Compiler.Private.Scripting.UnitTests}/DependencyManagerInteractiveTests.fs (100%) rename tests/{FSharp.DependencyManager.UnitTests => FSharp.Compiler.Private.Scripting.UnitTests}/DependencyManagerLineParserTests.fs (100%) delete mode 100644 tests/FSharp.DependencyManager.UnitTests/Directory.Build.props delete mode 100644 tests/FSharp.DependencyManager.UnitTests/FSharp.DependencyManager.UnitTests.fsproj diff --git a/FSharp.sln b/FSharp.sln index 23375be628e..57620c78647 100644 --- a/FSharp.sln +++ b/FSharp.sln @@ -52,8 +52,6 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Private.Scr EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Private.Scripting.UnitTests", "tests\FSharp.Compiler.Private.Scripting.UnitTests\FSharp.Compiler.Private.Scripting.UnitTests.fsproj", "{4FEDF286-0252-4EBC-9E75-879CCA3B85DC}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.DependencyManager.UnitTests", "tests\FSharp.DependencyManager.UnitTests\FSharp.DependencyManager.UnitTests.fsproj", "{388FFDAE-A659-422E-9407-6A9062E1986E}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -280,18 +278,6 @@ Global {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Release|Any CPU.Build.0 = Release|Any CPU {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Release|x86.ActiveCfg = Release|Any CPU {4FEDF286-0252-4EBC-9E75-879CCA3B85DC}.Release|x86.Build.0 = Release|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Debug|x86.ActiveCfg = Debug|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Debug|x86.Build.0 = Debug|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Proto|Any CPU.ActiveCfg = Debug|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Proto|Any CPU.Build.0 = Debug|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Proto|x86.ActiveCfg = Debug|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Proto|x86.Build.0 = Debug|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Release|Any CPU.Build.0 = Release|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Release|x86.ActiveCfg = Release|Any CPU - {388FFDAE-A659-422E-9407-6A9062E1986E}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -314,7 +300,6 @@ Global {8B7BF62E-7D8C-4928-BE40-4E392A9EE851} = {3881429D-A97A-49EB-B7AE-A82BA5FE9C77} {6771860A-614D-4FDD-A655-4C70EBCC91B0} = {B8DDA694-7939-42E3-95E5-265C2217C142} {4FEDF286-0252-4EBC-9E75-879CCA3B85DC} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} - {388FFDAE-A659-422E-9407-6A9062E1986E} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BD5177C7-1380-40E7-94D2-7768E1A8B1B8} diff --git a/VisualFSharp.sln b/VisualFSharp.sln index 76bcf8369e7..d46221b17b7 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -156,8 +156,6 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Private.Scr EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.DependencyManager", "src\fsharp\FSharp.DependencyManager\FSharp.DependencyManager.fsproj", "{DFA30881-C0B1-4813-B087-C21B5AF9B77F}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.DependencyManager.UnitTests", "tests\FSharp.DependencyManager.UnitTests\FSharp.DependencyManager.UnitTests.fsproj", "{AF7AE565-E1C4-4A24-BD4B-D7983FC84768}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VisualFSharpTemplates", "vsintegration\Vsix\VisualFSharpTemplates\VisualFSharpTemplates.csproj", "{AA259A37-418F-4E18-87B2-C7D5F8C26CC4}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ProjectTemplates", "ProjectTemplates", "{12EF27FD-A34B-4373-860A-F9FCE9651859}" @@ -922,18 +920,6 @@ Global {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Release|Any CPU.Build.0 = Release|Any CPU {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Release|x86.ActiveCfg = Release|Any CPU {DFA30881-C0B1-4813-B087-C21B5AF9B77F}.Release|x86.Build.0 = Release|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Debug|x86.ActiveCfg = Debug|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Debug|x86.Build.0 = Debug|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Proto|Any CPU.ActiveCfg = Debug|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Proto|Any CPU.Build.0 = Debug|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Proto|x86.ActiveCfg = Debug|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Proto|x86.Build.0 = Debug|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Release|Any CPU.Build.0 = Release|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Release|x86.ActiveCfg = Release|Any CPU - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768}.Release|x86.Build.0 = Release|Any CPU {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Debug|Any CPU.Build.0 = Debug|Any CPU {AA259A37-418F-4E18-87B2-C7D5F8C26CC4}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -1055,7 +1041,6 @@ Global {20B7BC36-CF51-4D75-9E13-66681C07977F} = {B8DDA694-7939-42E3-95E5-265C2217C142} {09F56540-AFA5-4694-B7A6-0DBF6D4618C2} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {DFA30881-C0B1-4813-B087-C21B5AF9B77F} = {3881429D-A97A-49EB-B7AE-A82BA5FE9C77} - {AF7AE565-E1C4-4A24-BD4B-D7983FC84768} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {AA259A37-418F-4E18-87B2-C7D5F8C26CC4} = {4C7B48D7-19AF-4AE7-9D1D-3BB289D5480D} {12EF27FD-A34B-4373-860A-F9FCE9651859} = {4C7B48D7-19AF-4AE7-9D1D-3BB289D5480D} {44155269-9B30-43DA-B97F-4F36F887B211} = {12EF27FD-A34B-4373-860A-F9FCE9651859} diff --git a/eng/Build.ps1 b/eng/Build.ps1 index cf7ce0413c0..72ea53f1467 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -48,7 +48,6 @@ param ( [switch]$testCoreClr, [switch]$testCambridge, [switch]$testCompiler, - [switch]$testDependencyManager, [switch]$testFSharpCore, [switch]$testFSharpQA, [switch]$testScripting, @@ -86,7 +85,6 @@ function Print-Usage() { Write-Host " -testAll Run all tests" Write-Host " -testCambridge Run Cambridge tests" Write-Host " -testCompiler Run FSharpCompiler unit tests" - Write-Host " -testDependencyManager Run FSharp.DependencyManager.UnitTests" Write-Host " -testDesktop Run tests against full .NET Framework" Write-Host " -testCoreClr Run tests against CoreCLR" Write-Host " -testFSharpCore Run FSharpCore unit tests" @@ -128,7 +126,6 @@ function Process-Arguments() { $script:testAll = $False $script:testCambridge = $False $script:testCompiler = $False - $script:testDependencyManager = $False $script:testDesktop = $False $script:testCoreClr = $False $script:testFSharpCore = $False @@ -348,7 +345,6 @@ try { TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.UnitTests\FSharp.Compiler.UnitTests.fsproj" -targetFramework $desktopTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.LanguageServer.UnitTests\FSharp.Compiler.LanguageServer.UnitTests.fsproj" -targetFramework $desktopTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.Private.Scripting.UnitTests\FSharp.Compiler.Private.Scripting.UnitTests.fsproj" -targetFramework $desktopTargetFramework - TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.DependencyManager.UnitTests\FSharp.DependencyManager.UnitTests.fsproj" -targetFramework $desktopTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Build.UnitTests\FSharp.Build.UnitTests.fsproj" -targetFramework $desktopTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Core.UnitTests\FSharp.Core.UnitTests.fsproj" -targetFramework $desktopTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\fsharp\FSharpSuite.Tests.fsproj" -targetFramework $desktopTargetFramework @@ -358,7 +354,6 @@ try { TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.UnitTests\FSharp.Compiler.UnitTests.fsproj" -targetFramework $coreclrTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.LanguageServer.UnitTests\FSharp.Compiler.LanguageServer.UnitTests.fsproj" -targetFramework $coreclrTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.Private.Scripting.UnitTests\FSharp.Compiler.Private.Scripting.UnitTests.fsproj" -targetFramework $coreclrTargetFramework - TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.DependencyManager.UnitTests\FSharp.DependencyManager.UnitTests.fsproj" -targetFramework $coreclrTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Build.UnitTests\FSharp.Build.UnitTests.fsproj" -targetFramework $coreclrTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Core.UnitTests\FSharp.Core.UnitTests.fsproj" -targetFramework $coreclrTargetFramework TestUsingNUnit -testProject "$RepoRoot\tests\fsharp\FSharpSuite.Tests.fsproj" -targetFramework $coreclrTargetFramework @@ -398,13 +393,6 @@ try { TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.Compiler.UnitTests\FSharp.Compiler.UnitTests.fsproj" -targetFramework $coreclrTargetFramework } - if ($testDependencyManager) { - if (-not $noVisualStudio) { - TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.DependencyManager.UnitTests\FSharp.DependencyManager.UnitTests.fsproj" -targetFramework $desktopTargetFramework - } - TestUsingNUnit -testProject "$RepoRoot\tests\FSharp.DependencyManager.UnitTests\FSharp.DependencyManager.UnitTests.fsproj" -targetFramework $coreclrTargetFramework - } - if ($testCambridge) { if (-not $noVisualStudio) { TestUsingNUnit -testProject "$RepoRoot\tests\fsharp\FSharpSuite.Tests.fsproj" -targetFramework $desktopTargetFramework diff --git a/eng/build.sh b/eng/build.sh index 6340d557466..218f4ef977f 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -292,7 +292,6 @@ if [[ "$test_core_clr" == true ]]; then TestUsingNUnit --testproject "$repo_root/tests/FSharp.Compiler.UnitTests/FSharp.Compiler.UnitTests.fsproj" --targetframework $coreclrtestframework TestUsingNUnit --testproject "$repo_root/tests/FSharp.Compiler.LanguageServer.UnitTests/FSharp.Compiler.LanguageServer.UnitTests.fsproj" --targetframework $coreclrtestframework TestUsingNUnit --testproject "$repo_root/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharp.Compiler.Private.Scripting.UnitTests.fsproj" --targetframework $coreclrtestframework - TestUsingNUnit --testproject "$repo_root/tests/FSharp.DependencyManager.UnitTests/FSharp.DependencyManager.UnitTests.fsproj" --targetframework $coreclrtestframework TestUsingNUnit --testproject "$repo_root/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj" --targetframework $coreclrtestframework TestUsingNUnit --testproject "$repo_root/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj" --targetframework $coreclrtestframework fi diff --git a/tests/FSharp.DependencyManager.UnitTests/DependencyManagerInteractiveTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs similarity index 100% rename from tests/FSharp.DependencyManager.UnitTests/DependencyManagerInteractiveTests.fs rename to tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs diff --git a/tests/FSharp.DependencyManager.UnitTests/DependencyManagerLineParserTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerLineParserTests.fs similarity index 100% rename from tests/FSharp.DependencyManager.UnitTests/DependencyManagerLineParserTests.fs rename to tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerLineParserTests.fs diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharp.Compiler.Private.Scripting.UnitTests.fsproj b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharp.Compiler.Private.Scripting.UnitTests.fsproj index a16969af734..39a3ca4e684 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharp.Compiler.Private.Scripting.UnitTests.fsproj +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharp.Compiler.Private.Scripting.UnitTests.fsproj @@ -13,6 +13,8 @@ + + diff --git a/tests/FSharp.DependencyManager.UnitTests/Directory.Build.props b/tests/FSharp.DependencyManager.UnitTests/Directory.Build.props deleted file mode 100644 index 7cd41381b5d..00000000000 --- a/tests/FSharp.DependencyManager.UnitTests/Directory.Build.props +++ /dev/null @@ -1,9 +0,0 @@ - - - - true - - - - - diff --git a/tests/FSharp.DependencyManager.UnitTests/FSharp.DependencyManager.UnitTests.fsproj b/tests/FSharp.DependencyManager.UnitTests/FSharp.DependencyManager.UnitTests.fsproj deleted file mode 100644 index 042986e8ada..00000000000 --- a/tests/FSharp.DependencyManager.UnitTests/FSharp.DependencyManager.UnitTests.fsproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - - net472;netcoreapp3.0 - netcoreapp3.0 - Library - true - nunit - true - - - - - - - - - - - - - - - From db2ba9ea52560fac9f37a27016f82af830a39383 Mon Sep 17 00:00:00 2001 From: Phillip Carter Date: Tue, 21 Jan 2020 15:39:56 -0800 Subject: [PATCH 13/14] [RFC 1082] - uint type abbreviation (#8185) * Add uint type abbreviation * Add uint casting function and test * Update surface area tests * update --- src/fsharp/FSharp.Core/prim-types-prelude.fs | 1 + src/fsharp/FSharp.Core/prim-types-prelude.fsi | 3 +++ src/fsharp/FSharp.Core/prim-types.fs | 5 ++++- src/fsharp/FSharp.Core/prim-types.fsi | 9 +++++++++ tests/FSharp.Core.UnitTests/FSharp.Core/PrimTypes.fs | 6 ++++++ tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs | 1 + tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs | 1 + tests/fsharp/Compiler/Language/UIntTests.fs | 10 ++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 1 + 9 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/fsharp/Compiler/Language/UIntTests.fs diff --git a/src/fsharp/FSharp.Core/prim-types-prelude.fs b/src/fsharp/FSharp.Core/prim-types-prelude.fs index 74c84101707..b95933a7aa3 100644 --- a/src/fsharp/FSharp.Core/prim-types-prelude.fs +++ b/src/fsharp/FSharp.Core/prim-types-prelude.fs @@ -28,6 +28,7 @@ namespace Microsoft.FSharp.Core type bool = System.Boolean type decimal = System.Decimal type int = int32 + type uint = uint32 type ``[]``<'T> = (# "!0[]" #) type ``[,]``<'T> = (# "!0[0 ...,0 ...]" #) diff --git a/src/fsharp/FSharp.Core/prim-types-prelude.fsi b/src/fsharp/FSharp.Core/prim-types-prelude.fsi index ed68965bf28..f4dd023159b 100644 --- a/src/fsharp/FSharp.Core/prim-types-prelude.fsi +++ b/src/fsharp/FSharp.Core/prim-types-prelude.fsi @@ -78,6 +78,9 @@ namespace Microsoft.FSharp.Core /// An abbreviation for the CLI type System.Int32. type int = int32 + /// An abbreviation for the CLI type System.UInt32. + type uint = uint32 + /// Single dimensional, zero-based arrays, written int[], string[] etc. /// Use the values in the Array module to manipulate values /// of this type, or the notation arr.[x] to get/set array diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 51c38a9642c..4bff05856c9 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -3731,7 +3731,10 @@ namespace Microsoft.FSharp.Core when ^T : byte = (# "conv.i4" value : int32 #) [] - let inline int value = int32 value + let inline int value = int32 value + + [] + let inline uint value = uint32 value [] let inline enum< ^T when ^T : enum > (value:int32) : ^T = EnumOfValue value diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index fd6c7557ef1..afa0719602c 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -2639,6 +2639,15 @@ namespace Microsoft.FSharp.Core [] val inline int : value:^T -> int when ^T : (static member op_Explicit : ^T -> int) and default ^T : int + /// Converts the argument to an unsigned 32-bit integer. This is a direct conversion for all + /// primitive numeric types. For strings, the input is converted using UInt32.Parse() + /// with InvariantCulture settings. Otherwise the operation requires an appropriate + /// static conversion method on the input type. + /// The input value. + /// The converted int + [] + val inline uint: value:^T -> uint when ^T: (static member op_Explicit: ^T -> uint) and default ^T: uint + /// Converts the argument to a particular enum type. /// The input value. /// The converted enum type. diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/PrimTypes.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/PrimTypes.fs index 9d92d474cff..4470df289d4 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/PrimTypes.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/PrimTypes.fs @@ -16,6 +16,12 @@ type m [] type LanguagePrimitivesModule() = + [] + member _.CastingUint () = + let expected = 12u + let actual = uint 12 + Assert.AreEqual(expected, actual) + [] member this.CastingUnits() = let f = 2.5 diff --git a/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs b/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs index 5e179041377..896e7629da0 100644 --- a/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs +++ b/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs @@ -2077,6 +2077,7 @@ Microsoft.FSharp.Core.Operators: Int32 Sign[T](T) Microsoft.FSharp.Core.Operators: Int32 SizeOf[T]() Microsoft.FSharp.Core.Operators: Int32 ToInt32[T](T) Microsoft.FSharp.Core.Operators: Int32 ToInt[T](T) +Microsoft.FSharp.Core.Operators: UInt32 ToUInt[T](T) Microsoft.FSharp.Core.Operators: Int32 limitedHash[T](Int32, T) Microsoft.FSharp.Core.Operators: Int64 ToInt64[T](T) Microsoft.FSharp.Core.Operators: IntPtr ToIntPtr[T](T) diff --git a/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs b/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs index 42984aa8315..82141617d93 100644 --- a/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs +++ b/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs @@ -2077,6 +2077,7 @@ Microsoft.FSharp.Core.Operators: Int32 Sign[T](T) Microsoft.FSharp.Core.Operators: Int32 SizeOf[T]() Microsoft.FSharp.Core.Operators: Int32 ToInt32[T](T) Microsoft.FSharp.Core.Operators: Int32 ToInt[T](T) +Microsoft.FSharp.Core.Operators: UInt32 ToUInt[T](T) Microsoft.FSharp.Core.Operators: Int32 limitedHash[T](Int32, T) Microsoft.FSharp.Core.Operators: Int64 ToInt64[T](T) Microsoft.FSharp.Core.Operators: IntPtr ToIntPtr[T](T) diff --git a/tests/fsharp/Compiler/Language/UIntTests.fs b/tests/fsharp/Compiler/Language/UIntTests.fs new file mode 100644 index 00000000000..c317f96e02f --- /dev/null +++ b/tests/fsharp/Compiler/Language/UIntTests.fs @@ -0,0 +1,10 @@ +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework + +[] +module UIntTests = + let ``uint type abbreviation works`` () = + let src = "let x = uint 12" + let expectedErrors = [||] + CompilerAssert.TypeCheckWithErrors src expectedErrors \ No newline at end of file diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 0daec217daa..66ae7d66b0b 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -59,6 +59,7 @@ + From 1a695c9d3ec9c0cb777aabf52703a603de695712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Cie=C5=9Blak?= Date: Wed, 22 Jan 2020 00:56:04 +0100 Subject: [PATCH 14/14] Expose more services (#8291) * Expose simplify name analyzer * Move IsPrivateToFile to the FSharpSymbolUse from extensions * Expose Unused Declarations analyzer * Update src/fsharp/symbols/Symbols.fsi Co-Authored-By: Phillip Carter * Apply feedback Co-authored-by: Phillip Carter --- src/fsharp/service/ServiceAnalysis.fs | 111 ++++++++++++++++++ src/fsharp/service/ServiceAnalysis.fsi | 18 ++- src/fsharp/symbols/Symbols.fs | 25 ++++ src/fsharp/symbols/Symbols.fsi | 2 + .../SimplifyNameDiagnosticAnalyzer.fs | 68 ++--------- .../Diagnostics/UnusedDeclarationsAnalyzer.fs | 65 +--------- .../FSharp.Editor/LanguageService/Symbols.fs | 26 ---- 7 files changed, 167 insertions(+), 148 deletions(-) diff --git a/src/fsharp/service/ServiceAnalysis.fs b/src/fsharp/service/ServiceAnalysis.fs index e568767a1e8..33c5a457759 100644 --- a/src/fsharp/service/ServiceAnalysis.fs +++ b/src/fsharp/service/ServiceAnalysis.fs @@ -226,4 +226,115 @@ module UnusedOpens = let symbolUses = splitSymbolUses symbolUses let openStatements = getOpenStatements checkFileResults.OpenDeclarations return! filterOpenStatements symbolUses openStatements + } + +module SimplifyNames = + type SimplifiableRange = { + Range: range + RelativeName: string + } + + let getPlidLength (plid: string list) = (plid |> List.sumBy String.length) + plid.Length + + let getSimplifiableNames (checkFileResults: FSharpCheckFileResults, getSourceLineStr: int -> string) : Async = + async { + let result = ResizeArray() + let! symbolUses = checkFileResults.GetAllUsesOfAllSymbolsInFile() + let symbolUses = + symbolUses + |> Array.filter (fun symbolUse -> not symbolUse.IsFromOpenStatement) + |> Array.Parallel.map (fun symbolUse -> + let lineStr = getSourceLineStr symbolUse.RangeAlternate.StartLine + // for `System.DateTime.Now` it returns ([|"System"; "DateTime"|], "Now") + let partialName = QuickParse.GetPartialLongNameEx(lineStr, symbolUse.RangeAlternate.EndColumn - 1) + // `symbolUse.RangeAlternate.Start` does not point to the start of plid, it points to start of `name`, + // so we have to calculate plid's start ourselves. + let plidStartCol = symbolUse.RangeAlternate.EndColumn - partialName.PartialIdent.Length - (getPlidLength partialName.QualifyingIdents) + symbolUse, partialName.QualifyingIdents, plidStartCol, partialName.PartialIdent) + |> Array.filter (fun (_, plid, _, name) -> name <> "" && not (List.isEmpty plid)) + |> Array.groupBy (fun (symbolUse, _, plidStartCol, _) -> symbolUse.RangeAlternate.StartLine, plidStartCol) + |> Array.map (fun (_, xs) -> xs |> Array.maxBy (fun (symbolUse, _, _, _) -> symbolUse.RangeAlternate.EndColumn)) + + for symbolUse, plid, plidStartCol, name in symbolUses do + if not symbolUse.IsFromDefinition then + let posAtStartOfName = + let r = symbolUse.RangeAlternate + if r.StartLine = r.EndLine then Range.mkPos r.StartLine (r.EndColumn - name.Length) + else r.Start + + let getNecessaryPlid (plid: string list) : Async = + let rec loop (rest: string list) (current: string list) = + async { + match rest with + | [] -> return current + | headIdent :: restPlid -> + let! res = checkFileResults.IsRelativeNameResolvableFromSymbol(posAtStartOfName, current, symbolUse.Symbol) + if res then return current + else return! loop restPlid (headIdent :: current) + } + loop (List.rev plid) [] + + let! necessaryPlid = getNecessaryPlid plid + + match necessaryPlid with + | necessaryPlid when necessaryPlid = plid -> () + | necessaryPlid -> + let r = symbolUse.RangeAlternate + let necessaryPlidStartCol = r.EndColumn - name.Length - (getPlidLength necessaryPlid) + + let unnecessaryRange = + Range.mkRange r.FileName (Range.mkPos r.StartLine plidStartCol) (Range.mkPos r.EndLine necessaryPlidStartCol) + + let relativeName = (String.concat "." plid) + "." + name + result.Add({Range = unnecessaryRange; RelativeName = relativeName}) + + return List.ofSeq result + } + +module UnusedDeclarations = + let isPotentiallyUnusedDeclaration (symbol: FSharpSymbol) : bool = + match symbol with + // Determining that a record, DU or module is used anywhere requires inspecting all their enclosed entities (fields, cases and func / vals) + // for usages, which is too expensive to do. Hence we never gray them out. + | :? FSharpEntity as e when e.IsFSharpRecord || e.IsFSharpUnion || e.IsInterface || e.IsFSharpModule || e.IsClass || e.IsNamespace -> false + // FCS returns inconsistent results for override members; we're skipping these symbols. + | :? FSharpMemberOrFunctionOrValue as f when + f.IsOverrideOrExplicitInterfaceImplementation || + f.IsBaseValue || + f.IsConstructor -> false + // Usage of DU case parameters does not give any meaningful feedback; we never gray them out. + | :? FSharpParameter -> false + | _ -> true + + let getUnusedDeclarationRanges (symbolsUses: FSharpSymbolUse[]) (isScript: bool) = + let definitions = + symbolsUses + |> Array.filter (fun su -> + su.IsFromDefinition && + su.Symbol.DeclarationLocation.IsSome && + (isScript || su.IsPrivateToFile) && + not (su.Symbol.DisplayName.StartsWith "_") && + isPotentiallyUnusedDeclaration su.Symbol) + + let usages = + let usages = + symbolsUses + |> Array.filter (fun su -> not su.IsFromDefinition) + |> Array.choose (fun su -> su.Symbol.DeclarationLocation) + HashSet(usages) + + let unusedRanges = + definitions + |> Array.map (fun defSu -> defSu, usages.Contains defSu.Symbol.DeclarationLocation.Value) + |> Array.groupBy (fun (defSu, _) -> defSu.RangeAlternate) + |> Array.filter (fun (_, defSus) -> defSus |> Array.forall (fun (_, isUsed) -> not isUsed)) + |> Array.map (fun (m, _) -> m) + + Array.toList unusedRanges + + let getUnusedDeclarations(checkFileResults: FSharpCheckFileResults, isScriptFile: bool) : Async = + async { + let! allSymbolUsesInFile = checkFileResults.GetAllUsesOfAllSymbolsInFile() + let unusedRanges = getUnusedDeclarationRanges allSymbolUsesInFile isScriptFile + return unusedRanges } \ No newline at end of file diff --git a/src/fsharp/service/ServiceAnalysis.fsi b/src/fsharp/service/ServiceAnalysis.fsi index 8d976443890..eb277269abb 100644 --- a/src/fsharp/service/ServiceAnalysis.fsi +++ b/src/fsharp/service/ServiceAnalysis.fsi @@ -8,4 +8,20 @@ open FSharp.Compiler.Range module public UnusedOpens = /// Get all unused open declarations in a file - val getUnusedOpens : checkFileResults: FSharpCheckFileResults * getSourceLineStr: (int -> string) -> Async \ No newline at end of file + val getUnusedOpens : checkFileResults: FSharpCheckFileResults * getSourceLineStr: (int -> string) -> Async + +module public SimplifyNames = + /// Data for use in finding unnecessarily-qualified names and generating diagnostics to simplify them + type SimplifiableRange = { + /// The range of a name that can be simplified + Range: range + /// The relative name that can be applied to a simplifiable name + RelativeName: string + } + + /// Get all ranges that can be simplified in a file + val getSimplifiableNames : checkFileResults: FSharpCheckFileResults * getSourceLineStr: (int -> string) -> Async + +module public UnusedDeclarations = + /// Get all unused declarations in a file + val getUnusedDeclarations : checkFileResults: FSharpCheckFileResults * isScriptFile: bool -> Async \ No newline at end of file diff --git a/src/fsharp/symbols/Symbols.fs b/src/fsharp/symbols/Symbols.fs index 295e42b02cb..f4b2f6babe6 100644 --- a/src/fsharp/symbols/Symbols.fs +++ b/src/fsharp/symbols/Symbols.fs @@ -2518,5 +2518,30 @@ type FSharpSymbolUse(g:TcGlobals, denv: DisplayEnv, symbol:FSharpSymbol, itemOcc member __.Range = Range.toZ range member __.RangeAlternate = range + + member this.IsPrivateToFile = + let isPrivate = + match this.Symbol with + | :? FSharpMemberOrFunctionOrValue as m -> not m.IsModuleValueOrMember || m.Accessibility.IsPrivate + | :? FSharpEntity as m -> m.Accessibility.IsPrivate + | :? FSharpGenericParameter -> true + | :? FSharpUnionCase as m -> m.Accessibility.IsPrivate + | :? FSharpField as m -> m.Accessibility.IsPrivate + | _ -> false + + let declarationLocation = + match this.Symbol.SignatureLocation with + | Some x -> Some x + | _ -> + match this.Symbol.DeclarationLocation with + | Some x -> Some x + | _ -> this.Symbol.ImplementationLocation + + let declaredInTheFile = + match declarationLocation with + | Some declRange -> declRange.FileName = this.RangeAlternate.FileName + | _ -> false + + isPrivate && declaredInTheFile override __.ToString() = sprintf "%O, %O, %O" symbol itemOcc range diff --git a/src/fsharp/symbols/Symbols.fsi b/src/fsharp/symbols/Symbols.fsi index 6893097ed94..ad402418c6c 100644 --- a/src/fsharp/symbols/Symbols.fsi +++ b/src/fsharp/symbols/Symbols.fsi @@ -1101,3 +1101,5 @@ type public FSharpSymbolUse = /// The range of text representing the reference to the symbol member RangeAlternate: range + /// Indicates if the FSharpSymbolUse is declared as private + member IsPrivateToFile : bool diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs index f90717522a5..09ee9cc2390 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs @@ -16,6 +16,7 @@ open FSharp.Compiler.Range open System.Runtime.Caching open Microsoft.CodeAnalysis.Host.Mef open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Diagnostics +open FSharp.Compiler.SourceCodeServices type private TextVersionHash = int type private PerDocumentSavedData = { Hash: int; Diagnostics: ImmutableArray } @@ -26,7 +27,7 @@ type internal SimplifyNameDiagnosticAnalyzer [] () = static let userOpName = "SimplifyNameDiagnosticAnalyzer" let getProjectInfoManager (document: Document) = document.Project.Solution.Workspace.Services.GetService().FSharpProjectOptionsManager let getChecker (document: Document) = document.Project.Solution.Workspace.Services.GetService().Checker - let getPlidLength (plid: string list) = (plid |> List.sumBy String.length) + plid.Length + static let cache = new MemoryCache("FSharp.Editor." + userOpName) // Make sure only one document is being analyzed at a time, to be nice static let guard = new SemaphoreSlim(1) @@ -52,62 +53,15 @@ type internal SimplifyNameDiagnosticAnalyzer [] () = let! sourceText = document.GetTextAsync() let checker = getChecker document let! _, _, checkResults = checker.ParseAndCheckDocument(document, projectOptions, sourceText = sourceText, userOpName=userOpName) - let! symbolUses = checkResults.GetAllUsesOfAllSymbolsInFile() |> liftAsync - let mutable result = ResizeArray() - let symbolUses = - symbolUses - |> Array.filter (fun symbolUse -> not symbolUse.IsFromOpenStatement) - |> Array.Parallel.map (fun symbolUse -> - let lineStr = sourceText.Lines.[Line.toZ symbolUse.RangeAlternate.StartLine].ToString() - // for `System.DateTime.Now` it returns ([|"System"; "DateTime"|], "Now") - let partialName = QuickParse.GetPartialLongNameEx(lineStr, symbolUse.RangeAlternate.EndColumn - 1) - // `symbolUse.RangeAlternate.Start` does not point to the start of plid, it points to start of `name`, - // so we have to calculate plid's start ourselves. - let plidStartCol = symbolUse.RangeAlternate.EndColumn - partialName.PartialIdent.Length - (getPlidLength partialName.QualifyingIdents) - symbolUse, partialName.QualifyingIdents, plidStartCol, partialName.PartialIdent) - |> Array.filter (fun (_, plid, _, name) -> name <> "" && not (List.isEmpty plid)) - |> Array.groupBy (fun (symbolUse, _, plidStartCol, _) -> symbolUse.RangeAlternate.StartLine, plidStartCol) - |> Array.map (fun (_, xs) -> xs |> Array.maxBy (fun (symbolUse, _, _, _) -> symbolUse.RangeAlternate.EndColumn)) - - for symbolUse, plid, plidStartCol, name in symbolUses do - if not symbolUse.IsFromDefinition then - let posAtStartOfName = - let r = symbolUse.RangeAlternate - if r.StartLine = r.EndLine then Range.mkPos r.StartLine (r.EndColumn - name.Length) - else r.Start - - let getNecessaryPlid (plid: string list) : Async = - let rec loop (rest: string list) (current: string list) = - async { - match rest with - | [] -> return current - | headIdent :: restPlid -> - let! res = checkResults.IsRelativeNameResolvableFromSymbol(posAtStartOfName, current, symbolUse.Symbol, userOpName=userOpName) - if res then return current - else return! loop restPlid (headIdent :: current) - } - loop (List.rev plid) [] - - do! Async.Sleep DefaultTuning.SimplifyNameEachItemDelay |> liftAsync // be less intrusive, give other work priority most of the time - let! necessaryPlid = getNecessaryPlid plid |> liftAsync - - match necessaryPlid with - | necessaryPlid when necessaryPlid = plid -> () - | necessaryPlid -> - let r = symbolUse.RangeAlternate - let necessaryPlidStartCol = r.EndColumn - name.Length - (getPlidLength necessaryPlid) - - let unnecessaryRange = - Range.mkRange r.FileName (Range.mkPos r.StartLine plidStartCol) (Range.mkPos r.EndLine necessaryPlidStartCol) - - let relativeName = (String.concat "." plid) + "." + name - result.Add( - Diagnostic.Create( - descriptor, - RoslynHelpers.RangeToLocation(unnecessaryRange, sourceText, document.FilePath), - properties = (dict [SimplifyNameDiagnosticAnalyzer.LongIdentPropertyKey, relativeName]).ToImmutableDictionary())) - - let diagnostics = result.ToImmutableArray() + let! result = SimplifyNames.getSimplifiableNames(checkResults, fun lineNumber -> sourceText.Lines.[Line.toZ lineNumber].ToString()) |> liftAsync + let mutable diag = ResizeArray() + for r in result do + diag.Add( + Diagnostic.Create( + descriptor, + RoslynHelpers.RangeToLocation(r.Range, sourceText, document.FilePath), + properties = (dict [SimplifyNameDiagnosticAnalyzer.LongIdentPropertyKey, r.RelativeName]).ToImmutableDictionary())) + let diagnostics = diag.ToImmutableArray() cache.Remove(key) |> ignore let data = { Hash = textVersionHash; Diagnostics=diagnostics } let cacheItem = CacheItem(key, data) diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs index ff7c43839d0..28f1b1f9c4f 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/UnusedDeclarationsAnalyzer.fs @@ -22,68 +22,6 @@ type internal UnusedDeclarationsAnalyzer [] () = let getProjectInfoManager (document: Document) = document.Project.Solution.Workspace.Services.GetService().FSharpProjectOptionsManager let getChecker (document: Document) = document.Project.Solution.Workspace.Services.GetService().Checker - let isPotentiallyUnusedDeclaration (symbol: FSharpSymbol) : bool = - match symbol with - // Determining that a record, DU or module is used anywhere requires inspecting all their enclosed entities (fields, cases and func / vals) - // for usages, which is too expensive to do. Hence we never gray them out. - | :? FSharpEntity as e when e.IsFSharpRecord || e.IsFSharpUnion || e.IsInterface || e.IsFSharpModule || e.IsClass || e.IsNamespace -> false - // FCS returns inconsistent results for override members; we're skipping these symbols. - | :? FSharpMemberOrFunctionOrValue as f when - f.IsOverrideOrExplicitInterfaceImplementation || - f.IsBaseValue || - f.IsConstructor -> false - // Usage of DU case parameters does not give any meaningful feedback; we never gray them out. - | :? FSharpParameter -> false - | _ -> true - - let getUnusedDeclarationRanges (symbolsUses: FSharpSymbolUse[]) (isScript: bool) = - let definitions = - symbolsUses - |> Array.filter (fun su -> - su.IsFromDefinition && - su.Symbol.DeclarationLocation.IsSome && - (isScript || su.IsPrivateToFile) && - not (su.Symbol.DisplayName.StartsWith "_") && - isPotentiallyUnusedDeclaration su.Symbol) - - let usages = - let usages = - symbolsUses - |> Array.filter (fun su -> not su.IsFromDefinition) - |> Array.choose (fun su -> su.Symbol.DeclarationLocation) - HashSet(usages) - - let unusedRanges = - definitions - |> Array.map (fun defSu -> defSu, usages.Contains defSu.Symbol.DeclarationLocation.Value) - |> Array.groupBy (fun (defSu, _) -> defSu.RangeAlternate) - |> Array.filter (fun (_, defSus) -> defSus |> Array.forall (fun (_, isUsed) -> not isUsed)) - |> Array.map (fun (m, _) -> m) - - //#if DEBUG - //let formatRange (x: FSharp.Compiler.Range.range) = sprintf "(%d, %d) - (%d, %d)" x.StartLine x.StartColumn x.EndLine x.EndColumn - - //symbolsUses - //|> Array.map (fun su -> sprintf "%s, %s, is definition = %b, Symbol (def range = %A)" - // (formatRange su.RangeAlternate) su.Symbol.DisplayName su.IsFromDefinition - // (su.Symbol.DeclarationLocation |> Option.map formatRange)) - //|> Logging.Logging.logInfof "SymbolUses:\n%+A" - // - //definitions - //|> Seq.map (fun su -> sprintf "su range = %s, symbol range = %A, symbol name = %s" - // (formatRange su.RangeAlternate) (su.Symbol.DeclarationLocation |> Option.map formatRange) su.Symbol.DisplayName) - //|> Logging.Logging.logInfof "Definitions:\n%A" - // - //usages - //|> Seq.map formatRange - //|> Seq.toArray - //|> Logging.Logging.logInfof "Used ranges:\n%A" - // - //unusedRanges - //|> Array.map formatRange - //|> Logging.Logging.logInfof "Unused ranges: %A" - //#endif - unusedRanges interface IFSharpUnusedDeclarationsDiagnosticAnalyzer with @@ -98,8 +36,7 @@ type internal UnusedDeclarationsAnalyzer [] () = let! sourceText = document.GetTextAsync() let checker = getChecker document let! _, _, checkResults = checker.ParseAndCheckDocument(document, projectOptions, sourceText = sourceText, userOpName = userOpName) - let! allSymbolUsesInFile = checkResults.GetAllUsesOfAllSymbolsInFile() |> liftAsync - let unusedRanges = getUnusedDeclarationRanges allSymbolUsesInFile (isScriptFile document.FilePath) + let! unusedRanges = UnusedDeclarations.getUnusedDeclarations( checkResults, (isScriptFile document.FilePath)) |> liftAsync return unusedRanges |> Seq.map (fun m -> Diagnostic.Create(descriptor, RoslynHelpers.RangeToLocation(m, sourceText, document.FilePath))) diff --git a/vsintegration/src/FSharp.Editor/LanguageService/Symbols.fs b/vsintegration/src/FSharp.Editor/LanguageService/Symbols.fs index a3d9b784526..dd7359d08fd 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/Symbols.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/Symbols.fs @@ -77,32 +77,6 @@ type FSharpSymbolUse with | projects -> Some (SymbolDeclarationLocation.Projects (projects, isSymbolLocalForProject)) | None -> None - member this.IsPrivateToFile = - let isPrivate = - match this.Symbol with - | :? FSharpMemberOrFunctionOrValue as m -> not m.IsModuleValueOrMember || m.Accessibility.IsPrivate - | :? FSharpEntity as m -> m.Accessibility.IsPrivate - | :? FSharpGenericParameter -> true - | :? FSharpUnionCase as m -> m.Accessibility.IsPrivate - | :? FSharpField as m -> m.Accessibility.IsPrivate - | _ -> false - - let declarationLocation = - match this.Symbol.SignatureLocation with - | Some x -> Some x - | _ -> - match this.Symbol.DeclarationLocation with - | Some x -> Some x - | _ -> this.Symbol.ImplementationLocation - - let declaredInTheFile = - match declarationLocation with - | Some declRange -> declRange.FileName = this.RangeAlternate.FileName - | _ -> false - - isPrivate && declaredInTheFile - - type FSharpMemberOrFunctionOrValue with member x.IsConstructor = x.CompiledName = ".ctor"