From 60cb2cf74de9274d9275817ff086ed73cb4212ad Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis <12659251+teo-tsirpanis@users.noreply.github.com> Date: Thu, 15 Oct 2020 15:49:57 +0300 Subject: [PATCH] Refactor the templating engine and the command tool cache et al. (#615) * Use a more efficient implementation of the Common module functions. Use an allocation-free implementation of the ParamKey type. Fix formatting in BuildCommand.fs and syntax highlighting in _template.html. * Rewrite the template engine to be more memory-efficient. It uses spans. For the most of allocation savings, FSharp.Formatting.Common now targets .NET Standard 2.1 too but the package is not yet updated; only the command tool will take advantage of all improvements. * Ignore files generated by the AssemblyInfo FAKE target. Remove an unused source file. And use LINQ-to-XML to generate version.props. * Serialize the command tool cache with the data contract serializer. The cache is both more secure and more compact (the cache's size for this project was reduced by a third, after using binary XML). And use a more reliable way to install the command tools during documentation generation. * Override ParamKey.ToString. --- .gitignore | 6 +- Directory.Build.props | 2 +- build.fsx | 43 +- docs/_template.html | 2 +- paket.dependencies | 1 + paket.lock | 118 ++--- src/Common/AssemblyInfo.cs | 20 - src/Common/AssemblyInfo.fs | 19 - .../AssemblyInfo.fs | 13 - .../BuildCommand.fs | 468 +++++++++--------- .../Common/Array.fs | 6 - src/FSharp.Formatting.CommandTool/Options.fs | 26 +- .../FSharp.Formatting.Common.fsproj | 2 +- src/FSharp.Formatting.Common/Templating.fs | 111 +++-- .../YaafFSharpScripting.fs | 31 +- src/FSharp.Formatting.Common/paket.references | 1 + version.props | 9 - 17 files changed, 414 insertions(+), 464 deletions(-) delete mode 100644 src/Common/AssemblyInfo.cs delete mode 100644 src/Common/AssemblyInfo.fs delete mode 100644 src/FSharp.Formatting.CommandTool/AssemblyInfo.fs delete mode 100644 src/FSharp.Formatting.CommandTool/Common/Array.fs delete mode 100644 version.props diff --git a/.gitignore b/.gitignore index 3b8421be6..649fce3b6 100644 --- a/.gitignore +++ b/.gitignore @@ -38,4 +38,8 @@ _NCrunch_* .ionide/ artifacts/ tests/FSharp.ApiDocs.Tests/output/ -tmp \ No newline at end of file +tmp +.idea/ +*.binlog +version.props +src/Common/AssemblyInfo.?s diff --git a/Directory.Build.props b/Directory.Build.props index 3761773d4..56860a8b7 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - + .pdb; $(AllowedOutputExtensionsInPackageBuildOutputFolder) diff --git a/build.fsx b/build.fsx index 153b55c39..ffaac3eb5 100644 --- a/build.fsx +++ b/build.fsx @@ -9,7 +9,7 @@ #endif open System -open System.IO +open System.Xml.Linq open Fake.Core open Fake.Core.TargetOperators open Fake.IO.Globbing.Operators @@ -52,15 +52,14 @@ Target.create "AssemblyInfo" (fun _ -> AssemblyInfoFile.createFSharp "src/Common/AssemblyInfo.fs" info AssemblyInfoFile.createCSharp "src/Common/AssemblyInfo.cs" info - let releaseNotes = String.toLines release.Notes |> System.Net.WebUtility.HtmlEncode - File.WriteAllText("version.props", sprintf """ - - %s - -%s - - - """ release.NugetVersion releaseNotes) + let versionProps = + XElement(XName.Get "Project", + XElement(XName.Get "PropertyGroup", + XElement(XName.Get "Version", release.NugetVersion), + XElement(XName.Get "PackageReleaseNotes", String.toLines release.Notes) + ) + ) + versionProps.Save("version.props") ) // Clean build results @@ -104,8 +103,8 @@ Target.create "Tests" (fun _ -> Target.create "NuGet" (fun _ -> DotNet.pack (fun pack -> { pack with - OutputPath = Some artifactsDir - Configuration = configuration + OutputPath = Some artifactsDir + Configuration = configuration }) solutionFile ) @@ -115,15 +114,15 @@ Target.create "NuGet" (fun _ -> Target.create "GenerateDocs" (fun _ -> Shell.cleanDir ".fsdocs" Shell.cleanDir ".packages" - DotNet.exec id "tool" "uninstall --local FSharp.Formatting.CommandTool" |> ignore - // Use a local package store to avoid reuse of previous builds of the package with the same version - try - Environment.setEnvironVar "NUGET_PACKAGES" (__SOURCE_DIRECTORY__ + "/.packages") - DotNet.exec id "tool" ("install --local --no-cache --version " + release.NugetVersion + " --add-source " + artifactsDir + " FSharp.Formatting.CommandTool") |> ignore - finally - Environment.setEnvironVar "NUGET_PACKAGES" "" - DotNet.exec id "fsdocs" "build --strict --clean --property Configuration=Release" |> ignore - DotNet.exec id "tool" "uninstall --local FSharp.Formatting.CommandTool" |> ignore + // Τhe tool has been uninstalled when the + // artifacts folder was removed in the Clean target. + DotNet.exec id "tool" ("install --no-cache --version " + release.NugetVersion + " --add-source " + artifactsDir + " --tool-path " + artifactsDir + " FSharp.Formatting.CommandTool") |> ignore + CreateProcess.fromRawCommand (artifactsDir @@ "fsdocs") ["build"; "--strict"; "--clean"; "--property"; "Configuration=Release"] + |> CreateProcess.ensureExitCode + |> Proc.run + |> ignore + // DotNet.exec id "fsdocs" "build --strict --clean --property Configuration=Release" |> ignore + // DotNet.exec id "tool" "uninstall --local FSharp.Formatting.CommandTool" |> ignore Shell.cleanDir ".packages" ) @@ -146,7 +145,7 @@ Target.create "PublishNuget" (fun _ -> let apikey = Environment.environVar "NUGET_KEY" for artifact in !! (artifactsDir + "/*nupkg") do let result = DotNet.exec id "nuget" (sprintf "push -s %s -k %s %s" source apikey artifact) - if not result.OK then failwith "failed to push packages" + if not result.OK then failwith "failed to push packages" ) Target.create "CreateTag" (fun _ -> diff --git a/docs/_template.html b/docs/_template.html index 8b0f6757f..5a47fccd1 100644 --- a/docs/_template.html +++ b/docs/_template.html @@ -71,7 +71,7 @@

{{fsdocs-collection- - + diff --git a/paket.dependencies b/paket.dependencies index bd5383d1c..a692a0fab 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -10,6 +10,7 @@ nuget Dotnet.ProjInfo nuget Dotnet.ProjInfo.Workspace nuget Newtonsoft.Json nuget Suave 2.1.1 +nuget System.Memory # Used to create notebook docs with mybinder links that work # See https://github.com/dotnet/interactive/blob/master/docs/CreateBinder.md diff --git a/paket.lock b/paket.lock index fde27e1c3..b2ce33198 100644 --- a/paket.lock +++ b/paket.lock @@ -1,14 +1,14 @@ STORAGE: NONE -RESTRICTION: || (== netcoreapp3.1) (== netstandard2.0) +RESTRICTION: || (== netcoreapp3.1) (== netstandard2.0) (== netstandard2.1) NUGET remote: https://api.nuget.org/v3/index.json CommandLineParser (2.8) - Dotnet.ProjInfo (0.43) + Dotnet.ProjInfo (0.44) FSharp.Core (>= 4.6.2) Microsoft.NETFramework.ReferenceAssemblies (>= 1.0) System.ValueTuple (>= 4.4) - Dotnet.ProjInfo.Workspace (0.43) - Dotnet.ProjInfo (>= 0.43) + Dotnet.ProjInfo.Workspace (0.44) + Dotnet.ProjInfo (>= 0.44) FSharp.Core (>= 4.6.2) Microsoft.NETFramework.ReferenceAssemblies (>= 1.0) Sln (>= 0.3) @@ -29,18 +29,18 @@ NUGET NETStandard.Library (>= 2.0.3) NUnit (>= 3.12 < 4.0) Microsoft.CodeAnalysis.Analyzers (3.0) - Microsoft.CodeAnalysis.Common (3.6) + Microsoft.CodeAnalysis.Common (3.7) Microsoft.CodeAnalysis.Analyzers (>= 3.0) System.Collections.Immutable (>= 1.5) - System.Memory (>= 4.5.3) + System.Memory (>= 4.5.4) System.Reflection.Metadata (>= 1.6) System.Runtime.CompilerServices.Unsafe (>= 4.7) System.Text.Encoding.CodePages (>= 4.5.1) System.Threading.Tasks.Extensions (>= 4.5.3) - Microsoft.CodeAnalysis.CSharp (3.6) - Microsoft.CodeAnalysis.Common (3.6) - Microsoft.CodeCoverage (16.6.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= net45)) (&& (== netstandard2.0) (>= netcoreapp2.1)) - Microsoft.DotNet.InternalAbstractions (1.0) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + Microsoft.CodeAnalysis.CSharp (3.7) + Microsoft.CodeAnalysis.Common (3.7) + Microsoft.CodeCoverage (16.7.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= net45)) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= net45)) (&& (== netstandard2.1) (>= netcoreapp2.1)) + Microsoft.DotNet.InternalAbstractions (1.0) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) System.AppContext (>= 4.1) System.Collections (>= 4.0.11) System.IO (>= 4.1) @@ -49,40 +49,40 @@ NUGET System.Runtime.Extensions (>= 4.1) System.Runtime.InteropServices (>= 4.1) System.Runtime.InteropServices.RuntimeInformation (>= 4.0) - Microsoft.NET.Test.Sdk (16.6.1) - Microsoft.CodeCoverage (>= 16.6.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= net45)) (&& (== netstandard2.0) (>= netcoreapp2.1)) - Microsoft.TestPlatform.TestHost (>= 16.6.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + Microsoft.NET.Test.Sdk (16.7.1) + Microsoft.CodeCoverage (>= 16.7.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= net45)) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= net45)) (&& (== netstandard2.1) (>= netcoreapp2.1)) + Microsoft.TestPlatform.TestHost (>= 16.7.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) Microsoft.NETCore.Platforms (3.1.1) Microsoft.NETCore.Targets (3.1) Microsoft.NETFramework.ReferenceAssemblies (1.0) - Microsoft.TestPlatform.ObjectModel (16.6.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + Microsoft.TestPlatform.ObjectModel (16.7.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) NuGet.Frameworks (>= 5.0) - Microsoft.TestPlatform.TestHost (16.6.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) - Microsoft.TestPlatform.ObjectModel (>= 16.6.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.0) (>= uap10.0)) - Newtonsoft.Json (>= 9.0.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.0) (>= uap10.0)) + Microsoft.TestPlatform.TestHost (16.7.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) + Microsoft.TestPlatform.ObjectModel (>= 16.7.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.0) (>= uap10.0)) (&& (== netstandard2.1) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= uap10.0)) + Newtonsoft.Json (>= 9.0.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.0) (>= uap10.0)) (&& (== netstandard2.1) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= uap10.0)) Microsoft.Win32.Primitives (4.3) Microsoft.NETCore.Platforms (>= 1.1) Microsoft.NETCore.Targets (>= 1.1) System.Runtime (>= 4.3) - Microsoft.Win32.Registry (4.7) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + Microsoft.Win32.Registry (4.7) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) System.Security.AccessControl (>= 4.7) System.Security.Principal.Windows (>= 4.7) NETStandard.Library (2.0.3) Microsoft.NETCore.Platforms (>= 1.1) Newtonsoft.Json (12.0.3) - NuGet.Frameworks (5.6) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + NuGet.Frameworks (5.6) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) NUnit (3.12) NETStandard.Library (>= 2.0) NUnit3TestAdapter (3.17) - Microsoft.DotNet.InternalAbstractions (>= 1.0) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) - System.ComponentModel.EventBasedAsync (>= 4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) - System.ComponentModel.TypeConverter (>= 4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) - System.Diagnostics.Process (>= 4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) - System.Reflection (>= 4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) - System.Runtime.InteropServices.RuntimeInformation (>= 4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) - System.Threading.Thread (>= 4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) - System.Xml.XmlDocument (>= 4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) - System.Xml.XPath.XmlDocument (>= 4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + Microsoft.DotNet.InternalAbstractions (>= 1.0) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) + System.ComponentModel.EventBasedAsync (>= 4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) + System.ComponentModel.TypeConverter (>= 4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) + System.Diagnostics.Process (>= 4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) + System.Reflection (>= 4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) + System.Runtime.InteropServices.RuntimeInformation (>= 4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) + System.Threading.Thread (>= 4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) + System.Xml.XmlDocument (>= 4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) + System.Xml.XPath.XmlDocument (>= 4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) runtime.debian.9-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) @@ -137,7 +137,7 @@ NUGET System.Runtime.Serialization.Json (>= 4.0.2) System.Security.Claims (>= 4.0.1) System.Security.Cryptography.Primitives (>= 4.3) - System.AppContext (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + System.AppContext (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) System.Runtime (>= 4.3) System.Buffers (4.5.1) System.Collections (4.3) @@ -156,15 +156,15 @@ NUGET System.Threading (>= 4.3) System.Threading.Tasks (>= 4.3) System.Collections.Immutable (1.7.1) - System.Memory (>= 4.5.4) - restriction: || (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (>= uap10.1)) (== netstandard2.0) - System.Collections.NonGeneric (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + System.Memory (>= 4.5.4) - restriction: || (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (>= uap10.1)) (== netstandard2.0) (== netstandard2.1) + System.Collections.NonGeneric (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) System.Diagnostics.Debug (>= 4.3) System.Globalization (>= 4.3) System.Resources.ResourceManager (>= 4.3) System.Runtime (>= 4.3) System.Runtime.Extensions (>= 4.3) System.Threading (>= 4.3) - System.Collections.Specialized (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + System.Collections.Specialized (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) System.Collections.NonGeneric (>= 4.3) System.Globalization (>= 4.3) System.Globalization.Extensions (>= 4.3) @@ -172,18 +172,18 @@ NUGET System.Runtime (>= 4.3) System.Runtime.Extensions (>= 4.3) System.Threading (>= 4.3) - System.ComponentModel (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + System.ComponentModel (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) System.Runtime (>= 4.3) - System.ComponentModel.EventBasedAsync (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + System.ComponentModel.EventBasedAsync (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) System.Resources.ResourceManager (>= 4.3) System.Runtime (>= 4.3) System.Threading (>= 4.3) System.Threading.Tasks (>= 4.3) - System.ComponentModel.Primitives (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + System.ComponentModel.Primitives (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) System.ComponentModel (>= 4.3) System.Resources.ResourceManager (>= 4.3) System.Runtime (>= 4.3) - System.ComponentModel.TypeConverter (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + System.ComponentModel.TypeConverter (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) System.Collections (>= 4.3) System.Collections.NonGeneric (>= 4.3) System.Collections.Specialized (>= 4.3) @@ -281,10 +281,10 @@ NUGET System.Resources.ResourceManager (>= 4.3) System.Runtime (>= 4.3) System.Runtime.Extensions (>= 4.3) - System.Memory (4.5.4) - System.Buffers (>= 4.5.1) - restriction: || (&& (== netcoreapp3.1) (>= monoandroid)) (&& (== netcoreapp3.1) (>= monotouch)) (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (&& (== netcoreapp3.1) (< netstandard1.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (>= xamarinios)) (&& (== netcoreapp3.1) (>= xamarinmac)) (&& (== netcoreapp3.1) (>= xamarintvos)) (&& (== netcoreapp3.1) (>= xamarinwatchos)) (== netstandard2.0) - System.Numerics.Vectors (>= 4.4) - restriction: || (&& (== netcoreapp3.1) (< netcoreapp2.0)) (== netstandard2.0) - System.Runtime.CompilerServices.Unsafe (>= 4.5.3) - restriction: || (&& (== netcoreapp3.1) (>= monoandroid)) (&& (== netcoreapp3.1) (>= monotouch)) (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (&& (== netcoreapp3.1) (< netcoreapp2.1)) (&& (== netcoreapp3.1) (< netstandard1.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (>= uap10.1)) (&& (== netcoreapp3.1) (>= xamarinios)) (&& (== netcoreapp3.1) (>= xamarinmac)) (&& (== netcoreapp3.1) (>= xamarintvos)) (&& (== netcoreapp3.1) (>= xamarinwatchos)) (== netstandard2.0) + System.Memory (4.5.4) - restriction: == netstandard2.0 + System.Buffers (>= 4.5.1) - restriction: || (&& (== netcoreapp3.1) (>= monoandroid)) (&& (== netcoreapp3.1) (>= monotouch)) (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (&& (== netcoreapp3.1) (< netstandard1.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (>= xamarinios)) (&& (== netcoreapp3.1) (>= xamarinmac)) (&& (== netcoreapp3.1) (>= xamarintvos)) (&& (== netcoreapp3.1) (>= xamarinwatchos)) (== netstandard2.0) (== netstandard2.1) + System.Numerics.Vectors (>= 4.4) - restriction: || (&& (== netcoreapp3.1) (< netcoreapp2.0)) (== netstandard2.0) (== netstandard2.1) + System.Runtime.CompilerServices.Unsafe (>= 4.5.3) - restriction: || (&& (== netcoreapp3.1) (>= monoandroid)) (&& (== netcoreapp3.1) (>= monotouch)) (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (&& (== netcoreapp3.1) (< netcoreapp2.1)) (&& (== netcoreapp3.1) (< netstandard1.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (>= uap10.1)) (&& (== netcoreapp3.1) (>= xamarinios)) (&& (== netcoreapp3.1) (>= xamarinmac)) (&& (== netcoreapp3.1) (>= xamarintvos)) (&& (== netcoreapp3.1) (>= xamarinwatchos)) (== netstandard2.0) (== netstandard2.1) System.Net.Primitives (4.3.1) Microsoft.NETCore.Platforms (>= 1.1.1) Microsoft.NETCore.Targets (>= 1.1.3) @@ -319,7 +319,7 @@ NUGET System.Threading (>= 4.3) System.Threading.Tasks (>= 4.3) System.Threading.ThreadPool (>= 4.3) - System.Numerics.Vectors (4.5) - restriction: || (&& (== netcoreapp3.1) (< netcoreapp2.0)) (== netstandard2.0) + System.Numerics.Vectors (4.5) - restriction: == netstandard2.0 System.Private.DataContractSerialization (4.3) System.Collections (>= 4.3) System.Collections.Concurrent (>= 4.3) @@ -353,17 +353,17 @@ NUGET System.Reflection.Primitives (>= 4.3) System.Runtime (>= 4.3) System.Reflection.Emit (4.7) - System.Reflection.Emit.ILGeneration (>= 4.7) - restriction: || (&& (== netcoreapp3.1) (< netcoreapp2.0) (< netstandard2.1)) (&& (== netcoreapp3.1) (>= netcoreapp5.0)) (&& (== netcoreapp3.1) (< netstandard1.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (>= uap10.1)) (== netstandard2.0) + System.Reflection.Emit.ILGeneration (>= 4.7) - restriction: || (&& (== netcoreapp3.1) (< netcoreapp2.0) (< netstandard2.1)) (&& (== netcoreapp3.1) (>= netcoreapp5.0)) (&& (== netcoreapp3.1) (< netstandard1.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (>= uap10.1)) (== netstandard2.0) (&& (== netstandard2.1) (>= netcoreapp5.0)) (&& (== netstandard2.1) (< netstandard1.1)) (&& (== netstandard2.1) (< netstandard2.0)) (&& (== netstandard2.1) (>= uap10.1)) System.Reflection.Emit.ILGeneration (4.7) System.Reflection.Emit.Lightweight (4.7) - System.Reflection.Emit.ILGeneration (>= 4.7) - restriction: || (&& (== netcoreapp3.1) (< netcoreapp2.0) (< netstandard2.1)) (&& (== netcoreapp3.1) (>= netcoreapp5.0)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (< portable-net45+wp8)) (&& (== netcoreapp3.1) (>= uap10.1)) (== netstandard2.0) + System.Reflection.Emit.ILGeneration (>= 4.7) - restriction: || (&& (== netcoreapp3.1) (< netcoreapp2.0) (< netstandard2.1)) (&& (== netcoreapp3.1) (>= netcoreapp5.0)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (< portable-net45+wp8)) (&& (== netcoreapp3.1) (>= uap10.1)) (== netstandard2.0) (&& (== netstandard2.1) (>= netcoreapp5.0)) (&& (== netstandard2.1) (< netstandard2.0)) (&& (== netstandard2.1) (< portable-net45+wp8)) (&& (== netstandard2.1) (>= uap10.1)) System.Reflection.Extensions (4.3) Microsoft.NETCore.Platforms (>= 1.1) Microsoft.NETCore.Targets (>= 1.1) System.Reflection (>= 4.3) System.Runtime (>= 4.3) System.Reflection.Metadata (1.8.1) - System.Collections.Immutable (>= 1.7.1) - restriction: || (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netstandard1.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (== netstandard2.0) + System.Collections.Immutable (>= 1.7.1) - restriction: || (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netstandard1.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (== netstandard2.0) (== netstandard2.1) System.Reflection.Primitives (4.3) Microsoft.NETCore.Platforms (>= 1.1) Microsoft.NETCore.Targets (>= 1.1) @@ -394,7 +394,7 @@ NUGET System.Reflection.Primitives (>= 4.3) System.Runtime (>= 4.3) System.Runtime.Handles (>= 4.3) - System.Runtime.InteropServices.RuntimeInformation (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + System.Runtime.InteropServices.RuntimeInformation (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) runtime.native.System (>= 4.3) System.Reflection (>= 4.3) System.Reflection.Extensions (>= 4.3) @@ -418,8 +418,8 @@ NUGET System.Runtime.Serialization.Primitives (4.3) System.Resources.ResourceManager (>= 4.3) System.Runtime (>= 4.3) - System.Security.AccessControl (4.7) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) - Microsoft.NETCore.Platforms (>= 3.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.0)) + System.Security.AccessControl (4.7) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) + Microsoft.NETCore.Platforms (>= 3.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.0)) (&& (== netstandard2.1) (>= netcoreapp2.0)) System.Security.Principal.Windows (>= 4.7) System.Security.Claims (4.3) System.Collections (>= 4.3) @@ -509,26 +509,26 @@ NUGET System.Threading (>= 4.3) System.Security.Principal (4.3) System.Runtime (>= 4.3) - System.Security.Principal.Windows (4.7) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + System.Security.Principal.Windows (4.7) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) System.Text.Encoding (4.3) Microsoft.NETCore.Platforms (>= 1.1) Microsoft.NETCore.Targets (>= 1.1) System.Runtime (>= 4.3) System.Text.Encoding.CodePages (4.7.1) - Microsoft.NETCore.Platforms (>= 3.1.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.0)) - System.Runtime.CompilerServices.Unsafe (>= 4.7.1) - restriction: || (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (== netstandard2.0) + Microsoft.NETCore.Platforms (>= 3.1.1) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.0)) (&& (== netstandard2.1) (>= netcoreapp2.0)) + System.Runtime.CompilerServices.Unsafe (>= 4.7.1) - restriction: || (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (== netstandard2.0) (== netstandard2.1) System.Text.Encoding.Extensions (4.3) Microsoft.NETCore.Platforms (>= 1.1) Microsoft.NETCore.Targets (>= 1.1) System.Runtime (>= 4.3) System.Text.Encoding (>= 4.3) System.Text.RegularExpressions (4.3.1) - System.Collections (>= 4.3) - restriction: || (&& (== netcoreapp3.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (>= netcoreapp5.0)) (== netstandard2.0) - System.Globalization (>= 4.3) - restriction: || (&& (== netcoreapp3.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (>= netcoreapp5.0)) (== netstandard2.0) - System.Resources.ResourceManager (>= 4.3) - restriction: || (&& (== netcoreapp3.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (>= netcoreapp5.0)) (== netstandard2.0) + System.Collections (>= 4.3) - restriction: || (&& (== netcoreapp3.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (>= netcoreapp5.0)) (== netstandard2.0) (== netstandard2.1) + System.Globalization (>= 4.3) - restriction: || (&& (== netcoreapp3.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (>= netcoreapp5.0)) (== netstandard2.0) (== netstandard2.1) + System.Resources.ResourceManager (>= 4.3) - restriction: || (&& (== netcoreapp3.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (>= netcoreapp5.0)) (== netstandard2.0) (== netstandard2.1) System.Runtime (>= 4.3.1) - System.Runtime.Extensions (>= 4.3.1) - restriction: || (&& (== netcoreapp3.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (>= netcoreapp5.0)) (== netstandard2.0) - System.Threading (>= 4.3) - restriction: || (&& (== netcoreapp3.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (>= netcoreapp5.0)) (== netstandard2.0) + System.Runtime.Extensions (>= 4.3.1) - restriction: || (&& (== netcoreapp3.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (>= netcoreapp5.0)) (== netstandard2.0) (== netstandard2.1) + System.Threading (>= 4.3) - restriction: || (&& (== netcoreapp3.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (>= netcoreapp5.0)) (== netstandard2.0) (== netstandard2.1) System.Threading (4.3) System.Runtime (>= 4.3) System.Threading.Tasks (>= 4.3) @@ -537,8 +537,8 @@ NUGET Microsoft.NETCore.Targets (>= 1.1) System.Runtime (>= 4.3) System.Threading.Tasks.Extensions (4.5.4) - System.Runtime.CompilerServices.Unsafe (>= 4.5.3) - restriction: || (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.1)) (&& (== netcoreapp3.1) (< netstandard1.0)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (>= wp8)) (== netstandard2.0) - System.Threading.Thread (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + System.Runtime.CompilerServices.Unsafe (>= 4.5.3) - restriction: || (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.1)) (&& (== netcoreapp3.1) (< netstandard1.0)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (>= wp8)) (== netstandard2.0) (== netstandard2.1) + System.Threading.Thread (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) System.Runtime (>= 4.3) System.Threading.ThreadPool (4.3) System.Runtime (>= 4.3) @@ -602,7 +602,7 @@ NUGET System.Threading (>= 4.3) System.Xml.ReaderWriter (>= 4.3) System.Xml.XmlDocument (>= 4.3) - System.Xml.XPath (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + System.Xml.XPath (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) System.Collections (>= 4.3) System.Diagnostics.Debug (>= 4.3) System.Globalization (>= 4.3) @@ -612,7 +612,7 @@ NUGET System.Runtime.Extensions (>= 4.3) System.Threading (>= 4.3) System.Xml.ReaderWriter (>= 4.3) - System.Xml.XPath.XmlDocument (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) + System.Xml.XPath.XmlDocument (4.3) - restriction: || (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.1)) (&& (== netstandard2.1) (>= netcoreapp2.1)) System.Collections (>= 4.3) System.Globalization (>= 4.3) System.IO (>= 4.3) diff --git a/src/Common/AssemblyInfo.cs b/src/Common/AssemblyInfo.cs deleted file mode 100644 index 5417d7941..000000000 --- a/src/Common/AssemblyInfo.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Auto-Generated by FAKE; do not edit -// -using System.Reflection; - -[assembly: AssemblyProduct("FSharp.Formatting")] -[assembly: AssemblyDescription("A package of libraries for building great F# documentation, samples and blogs")] -[assembly: AssemblyVersion("7.2.9")] -[assembly: AssemblyFileVersion("7.2.9")] -[assembly: AssemblyInformationalVersion("7.2.9")] -[assembly: AssemblyCopyright("Apache 2.0 License")] -namespace System { - internal static class AssemblyVersionInformation { - internal const System.String AssemblyProduct = "FSharp.Formatting"; - internal const System.String AssemblyDescription = "A package of libraries for building great F# documentation, samples and blogs"; - internal const System.String AssemblyVersion = "7.2.9"; - internal const System.String AssemblyFileVersion = "7.2.9"; - internal const System.String AssemblyInformationalVersion = "7.2.9"; - internal const System.String AssemblyCopyright = "Apache 2.0 License"; - } -} diff --git a/src/Common/AssemblyInfo.fs b/src/Common/AssemblyInfo.fs deleted file mode 100644 index 7c1b3cad7..000000000 --- a/src/Common/AssemblyInfo.fs +++ /dev/null @@ -1,19 +0,0 @@ -// Auto-Generated by FAKE; do not edit -namespace System -open System.Reflection - -[] -[] -[] -[] -[] -[] -do () - -module internal AssemblyVersionInformation = - let [] AssemblyProduct = "FSharp.Formatting" - let [] AssemblyDescription = "A package of libraries for building great F# documentation, samples and blogs" - let [] AssemblyVersion = "7.2.9" - let [] AssemblyFileVersion = "7.2.9" - let [] AssemblyInformationalVersion = "7.2.9" - let [] AssemblyCopyright = "Apache 2.0 License" diff --git a/src/FSharp.Formatting.CommandTool/AssemblyInfo.fs b/src/FSharp.Formatting.CommandTool/AssemblyInfo.fs deleted file mode 100644 index 858242a3e..000000000 --- a/src/FSharp.Formatting.CommandTool/AssemblyInfo.fs +++ /dev/null @@ -1,13 +0,0 @@ -module AssemblyInfo -open System.Reflection - -[] -[] -[] -[] -[] -[] -do () - -[] -let assemblyVersion = "2.2.12" diff --git a/src/FSharp.Formatting.CommandTool/BuildCommand.fs b/src/FSharp.Formatting.CommandTool/BuildCommand.fs index 493d7c14a..f47cdf9a4 100644 --- a/src/FSharp.Formatting.CommandTool/BuildCommand.fs +++ b/src/FSharp.Formatting.CommandTool/BuildCommand.fs @@ -8,8 +8,9 @@ open System.IO open System.Globalization open System.Reflection open System.Runtime.InteropServices -open System.Runtime.Serialization.Formatters.Binary +open System.Runtime.Serialization open System.Text +open System.Xml open FSharp.Formatting.Common open FSharp.Formatting.HtmlModel @@ -38,18 +39,20 @@ module Utils = let saveBinary (object:'T) (fileName:string) = try Directory.CreateDirectory (Path.GetDirectoryName(fileName)) |> ignore with _ -> () - let formatter = BinaryFormatter() - use fs = new FileStream(fileName, FileMode.Create) - formatter.Serialize(fs, object) + let formatter = DataContractSerializer(typeof<'T>) + use fs = File.Create(fileName) + use xw = XmlDictionaryWriter.CreateBinaryWriter(fs) + formatter.WriteObject(xw, object) fs.Flush() let loadBinary<'T> (fileName:string):'T option = - let formatter = BinaryFormatter() - use fs = new FileStream(fileName, FileMode.Open) + let formatter = DataContractSerializer(typeof<'T>) + use fs = File.OpenRead(fileName) + use xw = XmlDictionaryReader.CreateBinaryReader(fs, XmlDictionaryReaderQuotas.Max) try - let object = formatter.Deserialize(fs) :?> 'T + let object = formatter.ReadObject(xw) :?> 'T Some object - with e -> None + with _ -> None let cacheBinary cacheFile cacheValid (f: unit -> 'T) : 'T = let attempt = @@ -214,35 +217,35 @@ module Crack = IsTestProject = msbuildPropBool "IsTestProject" |> Option.defaultValue false IsLibrary = msbuildPropString "OutputType" |> Option.map (fun s -> s.ToLowerInvariant()) |> ((=) (Some "library")) IsPackable = msbuildPropBool "IsPackable" |> Option.defaultValue false - RepositoryUrl = msbuildPropString "RepositoryUrl" - RepositoryType = msbuildPropString "RepositoryType" - RepositoryBranch = msbuildPropString "RepositoryBranch" - FsDocsCollectionNameLink = msbuildPropString "FsDocsCollectionNameLink" - FsDocsSourceFolder = msbuildPropString "FsDocsSourceFolder" - FsDocsSourceRepository = msbuildPropString "FsDocsSourceRepository" - FsDocsLicenseLink = msbuildPropString "FsDocsLicenseLink" - FsDocsReleaseNotesLink = msbuildPropString "FsDocsReleaseNotesLink" - FsDocsLogoLink = msbuildPropString "FsDocsLogoLink" - FsDocsLogoSource = msbuildPropString "FsDocsLogoSource" - FsDocsNavbarPosition = msbuildPropString "FsDocsNavbarPosition" + RepositoryUrl = msbuildPropString "RepositoryUrl" + RepositoryType = msbuildPropString "RepositoryType" + RepositoryBranch = msbuildPropString "RepositoryBranch" + FsDocsCollectionNameLink = msbuildPropString "FsDocsCollectionNameLink" + FsDocsSourceFolder = msbuildPropString "FsDocsSourceFolder" + FsDocsSourceRepository = msbuildPropString "FsDocsSourceRepository" + FsDocsLicenseLink = msbuildPropString "FsDocsLicenseLink" + FsDocsReleaseNotesLink = msbuildPropString "FsDocsReleaseNotesLink" + FsDocsLogoLink = msbuildPropString "FsDocsLogoLink" + FsDocsLogoSource = msbuildPropString "FsDocsLogoSource" + FsDocsNavbarPosition = msbuildPropString "FsDocsNavbarPosition" FsDocsTheme = msbuildPropString "FsDocsTheme" FsDocsWarnOnMissingDocs = msbuildPropBool "FsDocsWarnOnMissingDocs" |> Option.defaultValue false UsesMarkdownComments = msbuildPropBool "UsesMarkdownComments" |> Option.defaultValue false - PackageProjectUrl = msbuildPropString "PackageProjectUrl" - Authors = msbuildPropString "Authors" + PackageProjectUrl = msbuildPropString "PackageProjectUrl" + Authors = msbuildPropString "Authors" GenerateDocumentationFile = msbuildPropBool "GenerateDocumentationFile" |> Option.defaultValue false - PackageLicenseExpression = msbuildPropString "PackageLicenseExpression" - PackageTags = msbuildPropString "PackageTags" + PackageLicenseExpression = msbuildPropString "PackageLicenseExpression" + PackageTags = msbuildPropString "PackageTags" Copyright = msbuildPropString "Copyright" PackageVersion = msbuildPropString "PackageVersion" PackageIconUrl = msbuildPropString "PackageIconUrl" RepositoryCommit = msbuildPropString "RepositoryCommit" } - + | Ok ok -> failwithf "huh? ok = %A" ok | Error err -> failwithf "error - %s\nlog - %s" (err.ToString()) (String.concat "\n" msgs) | Ok ok -> failwithf "huh? ok = %A" ok | Error err -> failwithf "error - %s\nlog - %s" (err.ToString()) (String.concat "\n" msgs) - + let getProjectsFromSlnFile (slnPath : string) = match InspectSln.tryParseSln slnPath with | Ok (_, slnData) -> @@ -254,7 +257,7 @@ module Crack = let crackProjects (strict, extraMsbuildProperties, userRoot, userCollectionName, userParameters, projects) = let slnDir = Path.GetFullPath "." - + //printfn "x.projects = %A" x.projects let collectionName, projectFiles = match projects with @@ -264,7 +267,7 @@ module Crack = printfn "getting projects from solution file %s" sln let collectionName = defaultArg userCollectionName (Path.GetFileNameWithoutExtension(sln)) collectionName, getProjectsFromSlnFile sln - | _ -> + | _ -> let projectFiles = [ yield! Directory.EnumerateFiles(slnDir, "*.fsproj") for d in Directory.EnumerateDirectories(slnDir) do @@ -272,23 +275,23 @@ module Crack = for d2 in Directory.EnumerateDirectories(d) do yield! Directory.EnumerateFiles(d2, "*.fsproj") ] - let collectionName = - defaultArg userCollectionName + let collectionName = + defaultArg userCollectionName (match projectFiles with | [ file1 ] -> Path.GetFileNameWithoutExtension(file1) | _ -> Path.GetFileName(slnDir)) collectionName, projectFiles - - | projectFiles -> + + | projectFiles -> let collectionName = Path.GetFileName(slnDir) collectionName, projectFiles - + //printfn "projects = %A" projectFiles let projectFiles = projectFiles |> List.choose (fun s -> if s.Contains(".Tests") || s.Contains("test") then - printfn " skipping project '%s' because it looks like a test project" (Path.GetFileName s) + printfn " skipping project '%s' because it looks like a test project" (Path.GetFileName s) None else Some s) @@ -297,14 +300,14 @@ module Crack = if projectFiles.Length = 0 then printfn "no project files found, no API docs will be generated" - printfn "cracking projects..." + printfn "cracking projects..." let projectInfos = projectFiles |> Array.ofList - |> Array.Parallel.choose (fun p -> + |> Array.Parallel.choose (fun p -> try Some (crackProjectFile slnDir extraMsbuildProperties p) - with e -> + with e -> if strict then exit 1 printfn " skipping project '%s' because an error occurred while cracking it: %A" (Path.GetFileName p) e None) @@ -318,13 +321,13 @@ module Crack = if info.TargetPath.IsNone then printfn " skipping project '%s' because it doesn't have a target path" shortName None - elif not info.IsLibrary then + elif not info.IsLibrary then printfn " skipping project '%s' because it isn't a library" shortName None - elif info.IsTestProject then + elif info.IsTestProject then printfn " skipping project '%s' because it has true" shortName None - elif not info.GenerateDocumentationFile then + elif not info.GenerateDocumentationFile then printfn " skipping project '%s' because it doesn't have " shortName None else @@ -374,7 +377,7 @@ module Crack = UsesMarkdownComments = false Copyright = projectInfos |> List.tryPick (fun info -> info.Copyright) PackageVersion = projectInfos |> List.tryPick (fun info -> info.PackageVersion) - PackageIconUrl = projectInfos |> List.tryPick (fun info -> info.PackageIconUrl) + PackageIconUrl = projectInfos |> List.tryPick (fun info -> info.PackageIconUrl) RepositoryCommit = projectInfos |> List.tryPick (fun info -> info.RepositoryCommit) } @@ -383,10 +386,10 @@ module Crack = defaultArg userRoot (defaultArg projectUrl ("/" + collectionName) |> ensureTrailingSlash) let parametersForProjectInfo (info: CrackedProjectInfo) = - let projectUrl = info.PackageProjectUrl |> Option.map ensureTrailingSlash |> Option.defaultValue root - let repoUrl = info.RepositoryUrl |> Option.map ensureTrailingSlash - userParameters @ - [ param None ParamKeys.``root`` (Some root) + let projectUrl = info.PackageProjectUrl |> Option.map ensureTrailingSlash |> Option.defaultValue root + let repoUrl = info.RepositoryUrl |> Option.map ensureTrailingSlash + userParameters @ + [ param None ParamKeys.``root`` (Some root) param None ParamKeys.``fsdocs-authors`` (Some (info.Authors |> Option.defaultValue "")) param None ParamKeys.``fsdocs-collection-name`` (Some collectionName) param None ParamKeys.``fsdocs-collection-name-link`` (Some (info.FsDocsCollectionNameLink |> Option.defaultValue projectUrl)) @@ -405,21 +408,22 @@ module Crack = param (Some "") ParamKeys.``fsdocs-repository-link`` repoUrl param None ParamKeys.``fsdocs-repository-branch`` info.RepositoryBranch param None ParamKeys.``fsdocs-repository-commit`` info.RepositoryCommit - ] - - let crackedProjects = - [ for info in projectInfos do - let substitutions = parametersForProjectInfo info - (info.TargetPath.Value, - info.RepositoryUrl, - info.RepositoryBranch, - info.RepositoryType, - info.UsesMarkdownComments, - info.FsDocsWarnOnMissingDocs, - info.FsDocsSourceFolder, - info.FsDocsSourceRepository, - substitutions) ] - + ] + + let crackedProjects = [ + for info in projectInfos do + let substitutions = parametersForProjectInfo info + ( info.TargetPath.Value, + info.RepositoryUrl, + info.RepositoryBranch, + info.RepositoryType, + info.UsesMarkdownComments, + info.FsDocsWarnOnMissingDocs, + info.FsDocsSourceFolder, + info.FsDocsSourceRepository, + substitutions) + ] + let paths = [ for info in projectInfos -> Path.GetDirectoryName info.TargetPath.Value ] let docsParameters = parametersForProjectInfo projectInfoForDocs @@ -429,7 +433,7 @@ module Crack = /// Convert markdown, script and other content into a static site type internal DocContent(outputDirectory, previous: Map<_,_>, lineNumbers, fsiEvaluator, substitutions, saveImages, watch, root) = - let createImageSaver (outputDirectory) = + let createImageSaver (outputDirectory) = // Download images so that they can be embedded let wc = new System.Net.WebClient() let mutable counter = 0 @@ -446,25 +450,22 @@ type internal DocContent(outputDirectory, previous: Map<_,_>, lineNumbers, fsiEv url2 else url - let processFile (inputFile: string) outputKind template outputPrefix imageSaver = - [ - let name = Path.GetFileName(inputFile) - if name.StartsWith(".") then - printfn "skipping file %s" inputFile - elif name.StartsWith "_template" then - () - else - let isFsx = inputFile.EndsWith(".fsx", true, CultureInfo.InvariantCulture) - let isMd = inputFile.EndsWith(".md", true, CultureInfo.InvariantCulture) + let processFile (inputFile: string) outputKind template outputPrefix imageSaver = [ + let name = Path.GetFileName(inputFile) + if name.StartsWith(".") then + printfn "skipping file %s" inputFile + elif not (name.StartsWith "_template") then + let isFsx = inputFile.EndsWith(".fsx", true, CultureInfo.InvariantCulture) + let isMd = inputFile.EndsWith(".md", true, CultureInfo.InvariantCulture) // A _template.tex or _template.pynb is needed to generate those files - match outputKind, template with - | OutputKind.Pynb, None -> () - | OutputKind.Latex, None -> () - | OutputKind.Fsx, None -> () - | _ -> + match outputKind, template with + | OutputKind.Pynb, None -> () + | OutputKind.Latex, None -> () + | OutputKind.Fsx, None -> () + | _ -> - let imageSaverOpt = + let imageSaverOpt = match outputKind with | OutputKind.Pynb when saveImages <> Some false -> Some imageSaver | OutputKind.Latex when saveImages <> Some false -> Some imageSaver @@ -472,36 +473,36 @@ type internal DocContent(outputDirectory, previous: Map<_,_>, lineNumbers, fsiEv | OutputKind.Html when saveImages = Some true -> Some imageSaver | _ -> None - let ext = outputKind.Extension - let relativeOutputFile = - if isFsx || isMd then - let basename = Path.GetFileNameWithoutExtension(inputFile) - Path.Combine(outputPrefix, sprintf "%s.%s" basename ext) - else - Path.Combine(outputPrefix, name) + let ext = outputKind.Extension + let relativeOutputFile = + if isFsx || isMd then + let basename = Path.GetFileNameWithoutExtension(inputFile) + Path.Combine(outputPrefix, sprintf "%s.%s" basename ext) + else + Path.Combine(outputPrefix, name) // Update only when needed - template or file or tool has changed - let outputFile = Path.GetFullPath(Path.Combine(outputDirectory, relativeOutputFile)) - let changed = - let fileChangeTime = try File.GetLastWriteTime(inputFile) with _ -> DateTime.MaxValue - let templateChangeTime = - match template with - | Some t when isFsx || isMd -> try File.GetLastWriteTime(t) with _ -> DateTime.MaxValue - | _ -> DateTime.MinValue - let toolChangeTime = - try File.GetLastWriteTime(Assembly.GetExecutingAssembly().Location) with _ -> DateTime.MaxValue - let changeTime = fileChangeTime |> max templateChangeTime |> max toolChangeTime - let generateTime = try File.GetLastWriteTime(outputFile) with _ -> System.DateTime.MinValue - changeTime > generateTime + let outputFile = Path.GetFullPath(Path.Combine(outputDirectory, relativeOutputFile)) + let changed = + let fileChangeTime = try File.GetLastWriteTime(inputFile) with _ -> DateTime.MaxValue + let templateChangeTime = + match template with + | Some t when isFsx || isMd -> try File.GetLastWriteTime(t) with _ -> DateTime.MaxValue + | _ -> DateTime.MinValue + let toolChangeTime = + try File.GetLastWriteTime(Assembly.GetExecutingAssembly().Location) with _ -> DateTime.MaxValue + let changeTime = fileChangeTime |> max templateChangeTime |> max toolChangeTime + let generateTime = try File.GetLastWriteTime(outputFile) with _ -> System.DateTime.MinValue + changeTime > generateTime // If it's changed or we don't know anything about it // we have to compute the model to get the global substitutions right - let mainRun = (outputKind = OutputKind.Html) - let haveModel = previous.TryFind inputFile - if changed || (watch && mainRun && haveModel.IsNone) then - if isFsx then - printfn " generating model for %s --> %s" inputFile relativeOutputFile - let model = + let mainRun = (outputKind = OutputKind.Html) + let haveModel = previous.TryFind inputFile + if changed || (watch && mainRun && haveModel.IsNone) then + if isFsx then + printfn " generating model for %s --> %s" inputFile relativeOutputFile + let model = Literate.ParseAndTransformScriptFile (inputFile, output = relativeOutputFile, outputKind = outputKind, ?formatAgent = None, ?prefix = None, ?fscoptions = None, @@ -512,15 +513,15 @@ type internal DocContent(outputDirectory, previous: Map<_,_>, lineNumbers, fsiEv //?tokenKindToCss = tokenKindToCss, ?imageSaver=imageSaverOpt) - yield ((if mainRun then Some (inputFile, model) else None), + yield ((if mainRun then Some (inputFile, model) else None), (fun p -> printfn " writing %s --> %s" inputFile relativeOutputFile ensureDirectory (Path.GetDirectoryName(outputFile)) SimpleTemplating.UseFileAsSimpleTemplate( p@model.Substitutions, template, outputFile))) - elif isMd then - printfn " preparing %s --> %s" inputFile relativeOutputFile - let model = + elif isMd then + printfn " preparing %s --> %s" inputFile relativeOutputFile + let model = Literate.ParseAndTransformMarkdownFile (inputFile, output = relativeOutputFile, outputKind = outputKind, ?formatAgent = None, ?prefix = None, ?fscoptions = None, @@ -531,15 +532,15 @@ type internal DocContent(outputDirectory, previous: Map<_,_>, lineNumbers, fsiEv //?tokenKindToCss = tokenKindToCss, ?imageSaver=imageSaverOpt) - yield ( (if mainRun then Some (inputFile, model) else None), + yield ( (if mainRun then Some (inputFile, model) else None), (fun p -> printfn " writing %s --> %s" inputFile relativeOutputFile ensureDirectory (Path.GetDirectoryName(outputFile)) SimpleTemplating.UseFileAsSimpleTemplate( p@model.Substitutions, template, outputFile))) - else + else if mainRun then - yield (None, + yield (None, (fun _p -> printfn " copying %s --> %s" inputFile relativeOutputFile ensureDirectory (Path.GetDirectoryName(outputFile)) @@ -550,13 +551,12 @@ type internal DocContent(outputDirectory, previous: Map<_,_>, lineNumbers, fsiEv File.Copy(inputFile, outputFile, true) File.SetLastWriteTime(outputFile,DateTime.Now) with _ when watch -> () )) - else - if mainRun && watch then - //printfn "skipping unchanged file %s" inputFile - yield (Some (inputFile, haveModel.Value), (fun _ -> ())) - ] - let rec processDirectory (htmlTemplate, texTemplate, pynbTemplate, fsxTemplate) indir outputPrefix = - [ + else + if mainRun && watch then + //printfn "skipping unchanged file %s" inputFile + yield (Some (inputFile, haveModel.Value), (fun _ -> ())) + ] + let rec processDirectory (htmlTemplate, texTemplate, pynbTemplate, fsxTemplate) indir outputPrefix = [ // Look for the presence of the _template.* files to activate the // generation of the content. let possibleNewHtmlTemplate = Path.Combine(indir, "_template.html") @@ -570,7 +570,7 @@ type internal DocContent(outputDirectory, previous: Map<_,_>, lineNumbers, fsiEv ensureDirectory (Path.Combine(outputDirectory, outputPrefix)) - let inputs = Directory.GetFiles(indir, "*") + let inputs = Directory.GetFiles(indir, "*") let imageSaver = createImageSaver (Path.Combine(outputDirectory, outputPrefix)) // Look for the four different kinds of content @@ -586,39 +586,40 @@ type internal DocContent(outputDirectory, previous: Map<_,_>, lineNumbers, fsiEv printfn " skipping directory %s" subdir else yield! processDirectory (htmlTemplate, texTemplate, pynbTemplate, fsxTemplate) (Path.Combine(indir, name)) (Path.Combine(outputPrefix, name)) - ] + ] - member _.Convert(input, htmlTemplate, extraInputs) = + member _.Convert(input, htmlTemplate, extraInputs) = - let inputDirectories = extraInputs @ [(input, ".") ] - [ - for (inputDirectory, outputPrefix) in inputDirectories do - yield! processDirectory (htmlTemplate, None, None, None) inputDirectory outputPrefix - ] + let inputDirectories = extraInputs @ [(input, ".") ] + [ + for (inputDirectory, outputPrefix) in inputDirectories do + yield! processDirectory (htmlTemplate, None, None, None) inputDirectory outputPrefix + ] - member _.GetSearchIndexEntries(docModels: (string * LiterateDocModel) list) = + member _.GetSearchIndexEntries(docModels: (string * LiterateDocModel) list) = [| for (_inputFile, model) in docModels do match model.IndexText with | Some text -> {title=model.Title; content = text; uri=model.Uri(root) } | _ -> () |] - member _.GetNavigationEntries(docModels: (string * LiterateDocModel) list) = - let modelsForList = - [ for thing in docModels do - match thing with - | (inputFile, model) - when model.OutputKind = OutputKind.Html && - // Don't put the index in the list - not (Path.GetFileNameWithoutExtension(inputFile) = "index") -> model - | _ -> () ] - - [ if modelsForList.Length > 0 then - li [Class "nav-header"] [!! "Documentation"] - for model in modelsForList do - let link = model.Uri(root) - li [Class "nav-item"] [ a [Class "nav-link"; (Href link)] [encode model.Title ] ] - ] - |> List.map (fun html -> html.ToString()) |> String.concat " \n" + member _.GetNavigationEntries(docModels: (string * LiterateDocModel) list) = + let modelsForList = + [ for thing in docModels do + match thing with + | (inputFile, model) + when model.OutputKind = OutputKind.Html && + // Don't put the index in the list + not (Path.GetFileNameWithoutExtension(inputFile) = "index") -> model + | _ -> () ] + + [ + if modelsForList.Length > 0 then + li [Class "nav-header"] [!! "Documentation"] + for model in modelsForList do + let link = model.Uri(root) + li [Class "nav-item"] [ a [Class "nav-link"; (Href link)] [encode model.Title ] ] + ] + |> List.map (fun html -> html.ToString()) |> String.concat " \n" /// Processes and runs Suave server to host them on localhost module Serve = @@ -626,12 +627,13 @@ module Serve = let refreshEvent = new Event<_>() let socketHandler (webSocket : WebSocket) _ = socket { - while true do - do! - refreshEvent.Publish - |> Control.Async.AwaitEvent - |> Suave.Sockets.SocketOp.ofAsync - do! webSocket.send Text (ByteSegment (Encoding.UTF8.GetBytes "refreshed")) true } + while true do + do! + refreshEvent.Publish + |> Control.Async.AwaitEvent + |> Suave.Sockets.SocketOp.ofAsync + do! webSocket.send Text (ByteSegment (Encoding.UTF8.GetBytes "refreshed")) true + } let startWebServer outputDirectory localPort = let defaultBinding = defaultConfig.bindings.[0] @@ -642,12 +644,13 @@ module Serve = homeFolder = Some outputDirectory } let app = choose [ - path "/" >=> Redirection.redirect "/index.html" - path "/websocket" >=> handShake socketHandler - Writers.setHeader "Cache-Control" "no-cache, no-store, must-revalidate" - >=> Writers.setHeader "Pragma" "no-cache" - >=> Writers.setHeader "Expires" "0" - >=> Files.browseHome ] + path "/" >=> Redirection.redirect "/index.html" + path "/websocket" >=> handShake socketHandler + Writers.setHeader "Cache-Control" "no-cache, no-store, must-revalidate" + >=> Writers.setHeader "Pragma" "no-cache" + >=> Writers.setHeader "Expires" "0" + >=> Files.browseHome + ] startWebServerAsync serverConfig app |> snd |> Async.Start type CoreBuildOptions(watch) = @@ -707,7 +710,7 @@ type CoreBuildOptions(watch) = member val clean = false with get, set member this.Execute() = - let protect f = + let protect f = try f() true @@ -728,19 +731,21 @@ type CoreBuildOptions(watch) = (evalPairwiseStringsNoOption this.parameters |> List.map (fun (a,b) -> (ParamKey a, b))) + let userParametersDict = readOnlyDict userParameters + // Adjust the user substitutions for 'watch' mode root let userRoot, userParameters = if watch then let userRoot = sprintf "http://localhost:%d/" this.port_option - if (dict userParameters).ContainsKey(ParamKeys.root) then - printfn "ignoring user-specified root since in watch mode, root = %s" userRoot + if userParametersDict.ContainsKey(ParamKeys.root) then + printfn "ignoring user-specified root since in watch mode, root = %s" userRoot let userParameters = [ ParamKeys.``root``, userRoot] @ (userParameters |> List.filter (fun (a, _) -> a <> ParamKeys.``root``)) Some userRoot, userParameters else let r = - match (dict userParameters).TryGetValue(ParamKeys.root) with + match userParametersDict.TryGetValue(ParamKeys.root) with | true, v -> Some v | _ -> None r, userParameters @@ -763,8 +768,8 @@ type CoreBuildOptions(watch) = (fun () -> Crack.crackProjects (this.strict, this.extraMsbuildProperties, userRoot, userCollectionName, userParameters, projects), key1) if crackedProjects.Length > 0 then - printfn "" - printfn "Inputs for API Docs:" + printfn "" + printfn "Inputs for API Docs:" for (dllFile, _, _, _, _, _, _, _, _) in crackedProjects do printfn " %s" dllFile @@ -773,15 +778,15 @@ type CoreBuildOptions(watch) = let msg = sprintf "*** %s does not exist, has it been built? You may need to provide --property Configuration=Release." dllFile if this.strict then failwith msg - else + else printfn "%s" msg if crackedProjects.Length > 0 then - printfn "" - printfn "Substitutions/parameters:" + printfn "" + printfn "Substitutions/parameters:" // Print the substitutions - for (ParamKey pk, p) in docsParameters do - printfn " %s --> %s" pk p + for (ParamKey pk, p) in docsParameters do + printfn " %s --> %s" pk p // The substitutions may differ for some projects due to different settings in the project files, if so show that let pd = dict docsParameters @@ -791,11 +796,11 @@ type CoreBuildOptions(watch) = printfn " (%s) %s --> %s" (Path.GetFileNameWithoutExtension(dllFile)) pkv2 p2 let apiDocInputs = - [ for (dllFile, repoUrlOption, repoBranchOption, repoTypeOption, projectMarkdownComments, projectWarn, projectSourceFolder, projectSourceRepo, projectParameters) in crackedProjects -> + [ for (dllFile, repoUrlOption, repoBranchOption, repoTypeOption, projectMarkdownComments, projectWarn, projectSourceFolder, projectSourceRepo, projectParameters) in crackedProjects -> let sourceRepo = match projectSourceRepo with | Some s -> Some s - | None -> + | None -> match evalString this.sourceRepo with | Some v -> Some v | None -> @@ -811,7 +816,7 @@ type CoreBuildOptions(watch) = let sourceFolder = match projectSourceFolder with | Some s -> s - | None -> + | None -> match evalString this.sourceFolder with | None -> Environment.CurrentDirectory | Some v -> v @@ -828,9 +833,9 @@ type CoreBuildOptions(watch) = PublicOnly = not this.nonpublic } ] let output = - if this.output = "" then - if watch then "tmp/watch" else "output" - else this.output + if this.output = "" then + if watch then "tmp/watch" else "output" + else this.output // This is in-package // From .nuget\packages\fsharp.formatting.commandtool\7.1.7\tools\netcoreapp3.1\any @@ -840,35 +845,35 @@ type CoreBuildOptions(watch) = // This is in-repo only let defaultTemplateAttempt2 = Path.GetFullPath(Path.Combine(dir, "..", "..", "..", "..", "..", "docs", "_template.html")) let defaultTemplate = - if this.nodefaultcontent then - None - else - if (try File.Exists(defaultTemplateAttempt1) with _ -> false) then - Some defaultTemplateAttempt1 - elif (try File.Exists(defaultTemplateAttempt2) with _ -> false) then - Some defaultTemplateAttempt2 - else None - - let extraInputs = - [ if not this.nodefaultcontent then - // The "extras" content goes in "." - // From .nuget\packages\fsharp.formatting.commandtool\7.1.7\tools\netcoreapp3.1\any - // to .nuget\packages\fsharp.formatting.commandtool\7.1.7\extras - let attempt1 = Path.GetFullPath(Path.Combine(dir, "..", "..", "..", "extras")) - if (try Directory.Exists(attempt1) with _ -> false) then - printfn "using extra content from %s" attempt1 - (attempt1, ".") - else - // This is for in-repo use only, assuming we are executing directly from - // src\FSharp.Formatting.CommandTool\bin\Debug\netcoreapp3.1\fsdocs.exe - // src\FSharp.Formatting.CommandTool\bin\Release\netcoreapp3.1\fsdocs.exe - let attempt2 = Path.GetFullPath(Path.Combine(dir, "..", "..", "..", "..", "..", "docs", "content")) - if (try Directory.Exists(attempt2) with _ -> false) then - printfn "using extra content from %s" attempt2 - (attempt2, "content") - else - printfn "no extra content found at %s or %s" attempt1 attempt2 - ] + if this.nodefaultcontent then + None + else + if (try File.Exists(defaultTemplateAttempt1) with _ -> false) then + Some defaultTemplateAttempt1 + elif (try File.Exists(defaultTemplateAttempt2) with _ -> false) then + Some defaultTemplateAttempt2 + else None + + let extraInputs = [ + if not this.nodefaultcontent then + // The "extras" content goes in "." + // From .nuget\packages\fsharp.formatting.commandtool\7.1.7\tools\netcoreapp3.1\any + // to .nuget\packages\fsharp.formatting.commandtool\7.1.7\extras + let attempt1 = Path.GetFullPath(Path.Combine(dir, "..", "..", "..", "extras")) + if (try Directory.Exists(attempt1) with _ -> false) then + printfn "using extra content from %s" attempt1 + (attempt1, ".") + else + // This is for in-repo use only, assuming we are executing directly from + // src\FSharp.Formatting.CommandTool\bin\Debug\netcoreapp3.1\fsdocs.exe + // src\FSharp.Formatting.CommandTool\bin\Release\netcoreapp3.1\fsdocs.exe + let attempt2 = Path.GetFullPath(Path.Combine(dir, "..", "..", "..", "..", "..", "docs", "content")) + if (try Directory.Exists(attempt2) with _ -> false) then + printfn "using extra content from %s" attempt2 + (attempt2, "content") + else + printfn "no extra content found at %s or %s" attempt1 attempt2 + ] // The incremental state (as well as the files written to disk) let mutable latestApiDocGlobalParameters = [ ] @@ -894,8 +899,8 @@ type CoreBuildOptions(watch) = protect (fun () -> //printfn "projectInfos = %A" projectInfos - printfn "" - printfn "Content:" + printfn "" + printfn "Content:" let saveImages = (match this.saveImages with "some" -> None | "none" -> Some false | "all" -> Some true | _ -> None) let fsiEvaluator = (if this.eval then Some ( FsiEvaluator(strict=this.strict) :> IFsiEvaluator) else None) let docContent = @@ -910,18 +915,18 @@ type CoreBuildOptions(watch) = let navEntries = docContent.GetNavigationEntries(actualDocModels) let results = Map.ofList [ - for (thing, _action) in docModels do - match thing with - | Some res -> res - | None -> () ] + for (thing, _action) in docModels do + match thing with + | Some res -> res + | None -> () ] latestDocContentResults <- results latestDocContentSearchIndexEntries <- extrasForSearchIndex latestDocContentGlobalParameters <- [ ParamKeys.``fsdocs-list-of-documents`` , navEntries ] latestDocContentPhase2 <- (fun globals -> - printfn "" - printfn "Write Content:" + printfn "" + printfn "Write Content:" for (_thing, action) in docModels do action globals @@ -953,12 +958,12 @@ type CoreBuildOptions(watch) = | Some d -> printfn "note, no template file '%s' or '%s', using default template %s" t1 t2 d Some d - | None -> + | None -> printfn "note, no template file '%s' or '%s', and no default template at '%s'" t1 t2 defaultTemplateAttempt1 None - printfn "" - printfn "API docs:" + printfn "" + printfn "API docs:" printfn " generating model for %d assemblies in API docs..." apiDocInputs.Length let globals, index, phase2 = ApiDocs.GenerateHtmlPhased ( @@ -976,15 +981,15 @@ type CoreBuildOptions(watch) = latestApiDocSearchIndexEntries <- index latestApiDocGlobalParameters <- globals - latestApiDocPhase2 <- phase2 + latestApiDocPhase2 <- phase2 ) let runGeneratePhase2 () = protect (fun () -> - printfn "" - printfn "Write API Docs:" + printfn "" + printfn "Write API Docs:" let globals = getLatestGlobalParameters() - latestApiDocPhase2 globals + latestApiDocPhase2 globals regenerateSearchIndex() ) @@ -999,8 +1004,8 @@ type CoreBuildOptions(watch) = for file in Directory.EnumerateFiles(dir) do File.Delete file |> ignore for subdir in Directory.EnumerateDirectories dir do - if not (Path.GetFileName(subdir).StartsWith ".") then - clean subdir + if not (Path.GetFileName(subdir).StartsWith ".") then + clean subdir if output <> "/" && output <> "." && fullOut <> fullIn && not (String.IsNullOrEmpty output) then try clean fullOut with e -> printfn "warning: error during cleaning, continuing: %s" e.Message @@ -1008,18 +1013,18 @@ type CoreBuildOptions(watch) = printfn "warning: skipping cleaning due to strange output path: \"%s\"" output if watch then - printfn "Building docs first time..." + printfn "Building docs first time..." //----------------------------------------- // Build let ok = - let ok1 = runDocContentPhase1() - let ok2 = runGeneratePhase1() + let ok1 = runDocContentPhase1() + let ok2 = runGeneratePhase1() let ok2 = ok2 && runGeneratePhase2() // Run this second to override anything produced by API generate, e.g. // bespoke file for namespaces etc. - let ok1 = ok1 && runDocContentPhase2() + let ok1 = ok1 && runDocContentPhase2() regenerateSearchIndex() ok1 && ok2 @@ -1041,7 +1046,7 @@ type CoreBuildOptions(watch) = let mutable generateQueued = true let docsDependenciesChanged = Event<_>() - docsDependenciesChanged.Publish.Add(fun () -> + docsDependenciesChanged.Publish.Add(fun () -> if not docsQueued then docsQueued <- true printfn "Detected change in '%s', scheduling rebuild of docs..." this.input @@ -1052,13 +1057,13 @@ type CoreBuildOptions(watch) = if runDocContentPhase1() then if runDocContentPhase2() then regenerateSearchIndex() - ) }) ) + ) }) ) let apiDocsDependenciesChanged = Event<_>() - apiDocsDependenciesChanged.Publish.Add(fun () -> + apiDocsDependenciesChanged.Publish.Add(fun () -> if not generateQueued then generateQueued <- true - printfn "Detected change in built outputs, scheduling rebuild of API docs..." + printfn "Detected change in built outputs, scheduling rebuild of API docs..." Async.Start(async { do! Async.Sleep(300) lock monitor (fun () -> @@ -1083,10 +1088,10 @@ type CoreBuildOptions(watch) = // Listen to changes in output DLLs for (projectOutputWatcher, projectOutput) in projectOutputWatchers do - projectOutputWatcher.Filter <- Path.GetFileName(projectOutput) - projectOutputWatcher.Path <- Path.GetDirectoryName(projectOutput) - projectOutputWatcher.NotifyFilter <- NotifyFilters.LastWrite - projectOutputWatcher.Changed.Add (fun _ -> apiDocsDependenciesChanged.Trigger()) + projectOutputWatcher.Filter <- Path.GetFileName(projectOutput) + projectOutputWatcher.Path <- Path.GetDirectoryName(projectOutput) + projectOutputWatcher.NotifyFilter <- NotifyFilters.LastWrite + projectOutputWatcher.Changed.Add (fun _ -> apiDocsDependenciesChanged.Trigger()) // Start raising events docsWatcher.EnableRaisingEvents <- true @@ -1109,11 +1114,11 @@ type CoreBuildOptions(watch) = Process.Start("xdg-open", url) |> ignore elif (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) then Process.Start("open", url) |> ignore - + OpenBrowser (url) waitForKey watch - if ok then 0 else 1 + if ok then 0 else 1 abstract noserver_option : bool default x.noserver_option = false @@ -1150,6 +1155,3 @@ type WatchCommand() = override x.port_option = x.port [] member val port = 8901 with get, set - - - diff --git a/src/FSharp.Formatting.CommandTool/Common/Array.fs b/src/FSharp.Formatting.CommandTool/Common/Array.fs deleted file mode 100644 index 8fc801970..000000000 --- a/src/FSharp.Formatting.CommandTool/Common/Array.fs +++ /dev/null @@ -1,6 +0,0 @@ -module Array - -let contains a e = - let A = a |> Array.filter (fun s -> s = e) - if A.Length > 0 then true - else false \ No newline at end of file diff --git a/src/FSharp.Formatting.CommandTool/Options.fs b/src/FSharp.Formatting.CommandTool/Options.fs index 5ca17ba50..f920ccbc0 100644 --- a/src/FSharp.Formatting.CommandTool/Options.fs +++ b/src/FSharp.Formatting.CommandTool/Options.fs @@ -2,30 +2,24 @@ namespace FSharp.Formatting.CommandTool module Common = - let evalString s = - if s = "" then None - else Some s + let evalString s = if s = "" then None else Some s let evalStrings a = - let a = Seq.toArray a - if a = [|""|] then None - else Some (List.ofArray a) + match Seq.tryExactlyOne a with + | Some "" -> None + | _ -> Some (List.ofSeq a) let evalPairwiseStrings a = - let a = Seq.toArray a - if a = [|""|] then None - else Some (a |> Seq.pairwise |> Array.ofSeq |> List.ofArray) + match Seq.tryExactlyOne a with + | Some "" -> None + | _ -> a |> Seq.pairwise |> List.ofSeq |> Some let evalPairwiseStringsNoOption a = - let a = Seq.toArray a - if a = [|""|] then [] - else a |> Seq.pairwise |> Array.ofSeq |> List.ofArray + evalPairwiseStrings a |> Option.defaultValue [] let concat a = - let mutable s = "" - for i in a do s <- (sprintf "%s %s" s i) - if s = " " then s <- "" - s + let s = String.concat " " a + if s = " " then "" else s let waitForKey b = if b then diff --git a/src/FSharp.Formatting.Common/FSharp.Formatting.Common.fsproj b/src/FSharp.Formatting.Common/FSharp.Formatting.Common.fsproj index cb2048966..f6fba9287 100644 --- a/src/FSharp.Formatting.Common/FSharp.Formatting.Common.fsproj +++ b/src/FSharp.Formatting.Common/FSharp.Formatting.Common.fsproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.0; netstandard2.1 TRACE;YAAF_FSHARP_SCRIPTING_PUBLIC true diff --git a/src/FSharp.Formatting.Common/Templating.fs b/src/FSharp.Formatting.Common/Templating.fs index d0c21ef57..537050b38 100644 --- a/src/FSharp.Formatting.Common/Templating.fs +++ b/src/FSharp.Formatting.Common/Templating.fs @@ -1,25 +1,19 @@ namespace FSharp.Formatting.Templating +open System +open System.Collections.Generic open System.IO +open System.Text -#if DEBUG +[] type ParamKey = ParamKey of string -#else -/// An abbreviation for 'string' representing a strong name for a parameter key -type ParamKey = string -#endif +with + override x.ToString() = + match x with ParamKey x -> x /// A list of parameters for substituting in templates, indexed by parameter keys type Substitutions = (ParamKey * string) list -#if !DEBUG -[] -/// Defines the parameter keys known to FSharp.Formatting processing code -module internal ParamKeyUtils = - let ParamKey (c: string) : ParamKey = c - let (|ParamKey|) (c: ParamKey) : string = c -#endif - /// /// Defines the parameter keys known to FSharp.Formatting processing code /// @@ -110,28 +104,61 @@ module ParamKeys = module internal SimpleTemplating = - // Replace '{{xyz}}' or '{xyz}' in template text - let ApplySubstitutions (substitutions: seq) (templateTextOpt: string option) = - match templateTextOpt with - | None | Some "" -> - // If there is no template or the template is an empty file, return just document + tooltips (tooltips empty if not HTML) - let lookup = substitutions |> dict - (if lookup.ContainsKey ParamKeys.``fsdocs-content`` then lookup.[ParamKeys.``fsdocs-content``] else "") + - (if lookup.ContainsKey ParamKeys.``fsdocs-tooltips`` then "\n\n" + lookup.[ParamKeys.``fsdocs-tooltips``] else "") - | Some templateText -> - // First replace {{key}} or {key} with some uglier keys and then replace them with values - // (in case one of the keys appears in some other value) - let id = System.Guid.NewGuid().ToString("d") - let temp = - (templateText, substitutions) ||> Seq.fold (fun text (ParamKey key, _value) -> - let key2 = "{{" + key + "}}" - let rkey = "{" + key + id + "}" - let text = text.Replace(key2, rkey) - text) - let result = - (temp, substitutions) ||> Seq.fold (fun text (ParamKey key, value) -> - text.Replace("{" + key + id + "}", value)) - result +#if NETSTANDARD2_0 + type StringBuilder with + member this.Append(span: ReadOnlySpan) = + this.Append(span.ToString()) +#endif + + // Replace '{{xyz}}' in template text + let ApplySubstitutionsInText (substitutions: seq) (text: string) = + let substitutions = readOnlyDict substitutions + let sb = StringBuilder(text.Length) + let mutable span = text.AsSpan() + while not span.IsEmpty do + // We try to find the first double curly bracket. + match span.IndexOf("{{".AsSpan(), StringComparison.Ordinal) with + | -1 -> + // If it's not found, there are no more tags in the template. + // We simply append all the remaining text. + sb.Append(span) |> ignore + span <- ReadOnlySpan.Empty + | curlyBraceBegin -> + // If we found two beginning curly brackets, + // we first append all the text before and + // then advance our span until just after them. + sb.Append(span.Slice(0, curlyBraceBegin)) |> ignore + span <- span.Slice(curlyBraceBegin + "{{".Length) + // Now we try to find the first double ending curly + // bracket after the beginning ones we previously found. + match span.IndexOf("}}".AsSpan(), StringComparison.Ordinal) with + | -1 -> + // If the whole tag had not been closed, we add the beginning + // double curly brackets we had previously discarded and then + // add the rest of the text. + sb.Append("{{").Append(span) |> ignore + span <- ReadOnlySpan.Empty + | curlyBraceEnd -> + // Otherwise we extract the tag's + // content, i.e. the parameter key. + let key = span.Slice(0, curlyBraceEnd).ToString() + match substitutions.TryGetValue(ParamKey key) with + | true, value -> + sb.Append(value) |> ignore + | false, _ -> + sb.Append("{{").Append(key).Append("}}") |> ignore + span <- span.Slice(curlyBraceEnd + "}}".Length) + sb.ToString() + + // Replace '{{xyz}}' in text + let ApplySubstitutions (substitutions: seq) templateTextOpt = + match templateTextOpt with + | None | Some "" -> + // If there is no template or the template is an empty file, return just document + tooltips (tooltips empty if not HTML) + let lookup = readOnlyDict substitutions + (if lookup.ContainsKey ParamKeys.``fsdocs-content`` then lookup.[ParamKeys.``fsdocs-content``] else "") + + (if lookup.ContainsKey ParamKeys.``fsdocs-tooltips`` then "\n\n" + lookup.[ParamKeys.``fsdocs-tooltips``] else "") + | Some templateText -> ApplySubstitutionsInText substitutions templateText let UseFileAsSimpleTemplate (substitutions, templateOpt, outputFile) = let templateTextOpt = templateOpt |> Option.map System.IO.File.ReadAllText @@ -141,17 +168,3 @@ module internal SimpleTemplating = Directory.CreateDirectory(path) |> ignore with _ -> () File.WriteAllText(outputFile, outputText) - - // Replace '{{xyz}}' in text - let ApplySubstitutionsInText (parameters:seq) (text: string) = - let id = System.Guid.NewGuid().ToString("d") - let temp = - (text, parameters) ||> Seq.fold (fun text (ParamKey key, _value) -> - let key2 = "{{" + key + "}}" - let rkey = "{" + key + id + "}" - let text = text.Replace(key2, rkey) - text) - let result = - (temp, parameters) ||> Seq.fold (fun text (ParamKey key, value) -> - text.Replace("{" + key + id + "}", value)) - result diff --git a/src/FSharp.Formatting.Common/YaafFSharpScripting.fs b/src/FSharp.Formatting.Common/YaafFSharpScripting.fs index f3d595a0e..c2693f774 100644 --- a/src/FSharp.Formatting.Common/YaafFSharpScripting.fs +++ b/src/FSharp.Formatting.Common/YaafFSharpScripting.fs @@ -71,7 +71,7 @@ module internal CompilerServiceExtensions = |> Array.toList) let fscoreResolveDirs libDirs = - [ + [ yield System.AppContext.BaseDirectory yield! libDirs @@ -97,7 +97,7 @@ module internal CompilerServiceExtensions = failwithf "Could not find a FSharp.Core.dll in %s" paths let hasAssembly asm l = - l |> Seq.exists (fun a -> Path.GetFileNameWithoutExtension a =? asm) + l |> Seq.exists (fun (a: string) -> Path.GetFileNameWithoutExtension a =? asm) let getCheckerArguments frameworkVersion defaultReferences hasFsCoreLib (fsCoreLib: _ option) dllFiles libDirs otherFlags = ignore frameworkVersion @@ -164,7 +164,7 @@ module internal CompilerServiceExtensions = if not hasFsCoreLib then Some (findFSCore dllFiles libDirs) else None - + let projFileName, args = getCheckerArguments frameworkVersion ignore hasFsCoreLib (fsCoreLib: _ option) dllFiles libDirs otherFlags //Log.verbf "Checker Arguments: %O" (Log.formatArgs args) @@ -225,7 +225,10 @@ module internal CompilerServiceExtensions = Directory.EnumerateFiles(libDir, "*.dll") |> Seq.map Path.GetFullPath // Filter files already referenced directly - |> Seq.filter (fun file -> dllFiles |> Seq.map Path.GetFileName |> Seq.exists ((=?) (Path.GetFileName file)) |> not) + |> Seq.filter (fun file -> + let fileName = Path.GetFileName file + dllFiles |> Seq.exists (fun (dllFile: string) -> + Path.GetFileName dllFile =? fileName) |> not) |> Seq.filter (fun file -> if Path.GetFileName file =? "FSharp.Core.dll" then FSharpAssemblyHelper.tryCheckFsCore file |> Option.isSome @@ -338,7 +341,7 @@ type internal FsiEvaluationException = sprintf "FsiEvaluationException:\n\nError: %s\n\nOutput: %s\n\nInput: %s\n\Arguments: %s\n\nException: %s" (nl x.Result.Error.Merged) (nl x.Result.Output.Merged) (nl x.Input) (Log.formatArgs args) (base.ToString()) - + /// Exception for invalid expression types type internal FsiExpressionTypeException = @@ -405,8 +408,8 @@ module internal Shell = addedPrinters <- Choice2Of2 (typeof<'T>, unbox >> printer) :: addedPrinters module internal ArgParser = - let (|StartsWith|_|) start (s:string) = - if s.StartsWith (start) then + let (|StartsWith|_|) (start: string) (s:string) = + if s.StartsWith(start) then StartsWith(s.Substring(start.Length)) |> Some else @@ -883,7 +886,7 @@ type internal FsiSession (fsi: obj, options: FsiOptions, reportGlobal, liveOut, let addDiagsToFsiOutput (o: InteractionOutputs) diags = { o with Output = { o.Output with FsiOutput = diagsToString diags + o.Output.FsiOutput } } - member __.EvalInteraction text = + member __.EvalInteraction text = let i, (r, diags) = evalInteraction text let i2 = addDiagsToFsiOutput i diags let res = @@ -891,8 +894,8 @@ type internal FsiSession (fsi: obj, options: FsiOptions, reportGlobal, liveOut, | Choice1Of2 v -> Ok v | Choice2Of2 exn -> Error exn i2, res - - member __.EvalScript path = + + member __.EvalScript path = let i, (r, diags) = evalScript path let i2 = addDiagsToFsiOutput i diags let res = @@ -919,9 +922,9 @@ type internal FsiSession (fsi: obj, options: FsiOptions, reportGlobal, liveOut, /// See https://github.com/Microsoft/visualfsharp/issues/1392 member x.EvalScriptAsInteraction s = // See https://github.com/fsharp/FSharp.Compiler.Service/issues/621 - let scriptContents = - sprintf "#line 1 @\"%s\"\n" s + - System.IO.File.ReadAllText s + + let scriptContents = + sprintf "#line 1 @\"%s\"\n" s + + System.IO.File.ReadAllText s + "\n()" x.EvalInteraction scriptContents @@ -976,7 +979,7 @@ type internal FsiSession (fsi: obj, options: FsiOptions, reportGlobal, liveOut, member x.WithCd dir f = use __ = x.ChangeCurrentDirectory dir f () - + /// Change the current directory (so that relative paths within scripts work properly). /// Returns a handle to change the current directory back to it's initial state /// (Because this will change the current directory of the currently running code as well!). diff --git a/src/FSharp.Formatting.Common/paket.references b/src/FSharp.Formatting.Common/paket.references index 2a8a7e53f..bd239211c 100644 --- a/src/FSharp.Formatting.Common/paket.references +++ b/src/FSharp.Formatting.Common/paket.references @@ -1,2 +1,3 @@ FSharp.Core FSharp.Compiler.Service +System.Memory framework: netstandard2.0 diff --git a/version.props b/version.props deleted file mode 100644 index 4aa7a4d7b..000000000 --- a/version.props +++ /dev/null @@ -1,9 +0,0 @@ - - - 7.2.9 - -Document how to do math in XML comments -Add --strict flag to fsdocs - - - \ No newline at end of file