diff --git a/global.json b/global.json index 13b47e6d801..599fe57e58d 100644 --- a/global.json +++ b/global.json @@ -2,5 +2,6 @@ "sdk": { "version": "3.0.100" }, - "version": "8.0.0" + "version": "8.0.0", + "doc_current": "master" } \ No newline at end of file diff --git a/src/CodeGeneration/DocGenerator/AsciiDoc/GeneratedAsciidocVisitor.cs b/src/CodeGeneration/DocGenerator/AsciiDoc/GeneratedAsciidocVisitor.cs index 2f89257ae4a..0e859378132 100644 --- a/src/CodeGeneration/DocGenerator/AsciiDoc/GeneratedAsciidocVisitor.cs +++ b/src/CodeGeneration/DocGenerator/AsciiDoc/GeneratedAsciidocVisitor.cs @@ -73,7 +73,7 @@ public override void VisitDocument(Document document) _newDocument.Attributes.Add(new AttributeEntry("nuget", "https://www.nuget.org/packages")); var originalFile = Regex.Replace(_source.FullName.Replace("\\", "/"), @"^(.*Tests/)", - $"{github}/tree/{Program.BranchName}/src/Tests/Tests/"); + $"{github}/tree/{Program.DocVersion}/src/Tests/Tests/"); _newDocument.Insert(0, new Comment { diff --git a/src/CodeGeneration/DocGenerator/Buildalyzer/AnalyzerManager.cs b/src/CodeGeneration/DocGenerator/Buildalyzer/AnalyzerManager.cs deleted file mode 100644 index 0a1b44035d1..00000000000 --- a/src/CodeGeneration/DocGenerator/Buildalyzer/AnalyzerManager.cs +++ /dev/null @@ -1,149 +0,0 @@ -#region License - -//MIT License -// -//Copyright (c) 2017 Dave Glick -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files (the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Xml.Linq; -using DocGenerator.Buildalyzer.Logging; -using Microsoft.Build.Construction; -using Microsoft.Build.Framework; -using Microsoft.Extensions.Logging; - -namespace DocGenerator.Buildalyzer -{ - public class AnalyzerManager - { - private readonly Dictionary _projects = new Dictionary(); - - public AnalyzerManager(ILoggerFactory loggerFactory = null, LoggerVerbosity loggerVerbosity = LoggerVerbosity.Normal) - : this(null, null, loggerFactory, loggerVerbosity) { } - - public AnalyzerManager(TextWriter logWriter, LoggerVerbosity loggerVerbosity = LoggerVerbosity.Normal) - : this(null, logWriter, loggerVerbosity) { } - - public AnalyzerManager(string solutionFilePath, string[] projects, ILoggerFactory loggerFactory = null, - LoggerVerbosity loggerVerbosity = LoggerVerbosity.Normal - ) - { - LoggerVerbosity = loggerVerbosity; - ProjectLogger = loggerFactory?.CreateLogger(); - - if (solutionFilePath != null) - { - solutionFilePath = ValidatePath(solutionFilePath, true); - SolutionDirectory = Path.GetDirectoryName(solutionFilePath); - GetProjectsInSolution(solutionFilePath, projects); - } - } - - public AnalyzerManager(string solutionFilePath, TextWriter logWriter, LoggerVerbosity loggerVerbosity = LoggerVerbosity.Normal) - { - LoggerVerbosity = loggerVerbosity; - if (logWriter != null) - { - var loggerFactory = new LoggerFactory(); - loggerFactory.AddProvider(new TextWriterLoggerProvider(logWriter)); - ProjectLogger = loggerFactory.CreateLogger(); - } - - if (solutionFilePath != null) - { - solutionFilePath = ValidatePath(solutionFilePath, true); - SolutionDirectory = Path.GetDirectoryName(solutionFilePath); - GetProjectsInSolution(solutionFilePath); - } - } - - public IReadOnlyDictionary Projects => _projects; - - public string SolutionDirectory { get; } - - internal LoggerVerbosity LoggerVerbosity { get; } - - internal ILogger ProjectLogger { get; } - - private void GetProjectsInSolution(string solutionFilePath, string[] projects = null) - { - projects = projects ?? new string[] { }; - var supportedType = new[] - { - SolutionProjectType.KnownToBeMSBuildFormat, - SolutionProjectType.WebProject - }; - - var solution = SolutionFile.Parse(solutionFilePath); - foreach (var project in solution.ProjectsInOrder) - { - if (!supportedType.Contains(project.ProjectType)) continue; - if (projects.Length > 0 && !projects.Contains(project.ProjectName)) continue; - - GetProject(project.AbsolutePath); - } - } - - public ProjectAnalyzer GetProject(string projectFilePath) - { - if (projectFilePath == null) throw new ArgumentNullException(nameof(projectFilePath)); - - // Normalize as .sln uses backslash regardless of OS the sln is created on - projectFilePath = projectFilePath.Replace('\\', Path.DirectorySeparatorChar); - projectFilePath = ValidatePath(projectFilePath, true); - if (_projects.TryGetValue(projectFilePath, out var project)) return project; - - project = new ProjectAnalyzer(this, projectFilePath); - _projects.Add(projectFilePath, project); - return project; - } - - public ProjectAnalyzer GetProject(string projectFilePath, XDocument projectDocument) - { - if (projectFilePath == null) throw new ArgumentNullException(nameof(projectFilePath)); - - if (projectDocument == null) throw new ArgumentNullException(nameof(projectDocument)); - - // Normalize as .sln uses backslash regardless of OS the sln is created on - projectFilePath = projectFilePath.Replace('\\', Path.DirectorySeparatorChar); - projectFilePath = ValidatePath(projectFilePath, false); - if (_projects.TryGetValue(projectFilePath, out var project)) return project; - - project = new ProjectAnalyzer(this, projectFilePath, projectDocument); - _projects.Add(projectFilePath, project); - return project; - } - - private static string ValidatePath(string path, bool checkExists) - { - if (path == null) throw new ArgumentNullException(nameof(path)); - - path = Path.GetFullPath(path); // Normalize the path - if (checkExists && !File.Exists(path)) throw new ArgumentException($"The path {path} could not be found."); - - return path; - } - } -} diff --git a/src/CodeGeneration/DocGenerator/Buildalyzer/AnalyzerManagerExtensions.cs b/src/CodeGeneration/DocGenerator/Buildalyzer/AnalyzerManagerExtensions.cs deleted file mode 100644 index 663953b4a4b..00000000000 --- a/src/CodeGeneration/DocGenerator/Buildalyzer/AnalyzerManagerExtensions.cs +++ /dev/null @@ -1,40 +0,0 @@ -#region License - -//MIT License -// -//Copyright (c) 2017 Dave Glick -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files (the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. - -#endregion - -using Microsoft.CodeAnalysis; - -namespace DocGenerator.Buildalyzer -{ - public static class AnalyzerManagerExtensions - { - public static AdhocWorkspace GetWorkspace(this AnalyzerManager manager) - { - var workspace = new AdhocWorkspace(); - foreach (var project in manager.Projects.Values) project.AddToWorkspace(workspace); - return workspace; - } - } -} diff --git a/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/BuildEnvironment.cs b/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/BuildEnvironment.cs deleted file mode 100644 index fcc250cd930..00000000000 --- a/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/BuildEnvironment.cs +++ /dev/null @@ -1,71 +0,0 @@ -#region License - -//MIT License -// -//Copyright (c) 2017 Dave Glick -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files (the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. - -#endregion - -using System.Collections.Generic; - -namespace DocGenerator.Buildalyzer.Environment -{ - internal abstract class BuildEnvironment - { - private string _oldMsBuildExtensionsPath; - private string _oldMsBuildSdksPath; - - public abstract string GetToolsPath(); - - public virtual Dictionary GetGlobalProperties(string solutionDir) => - new Dictionary - { - { MsBuildProperties.SolutionDir, solutionDir }, - { MsBuildProperties.DesignTimeBuild, "true" }, - { MsBuildProperties.BuildProjectReferences, "false" }, - { MsBuildProperties.SkipCompilerExecution, "true" }, - { MsBuildProperties.ProvideCommandLineArgs, "true" }, - // Workaround for a problem with resource files, see https://github.com/dotnet/sdk/issues/346#issuecomment-257654120 - { MsBuildProperties.GenerateResourceMsBuildArchitecture, "CurrentArchitecture" } - }; - - public virtual void SetEnvironmentVars(IReadOnlyDictionary globalProperties) - { - if (globalProperties.TryGetValue(MsBuildProperties.MsBuildExtensionsPath, out var msBuildExtensionsPath)) - { - _oldMsBuildExtensionsPath = System.Environment.GetEnvironmentVariable(MsBuildProperties.MsBuildExtensionsPath); - System.Environment.SetEnvironmentVariable(MsBuildProperties.MsBuildExtensionsPath, msBuildExtensionsPath); - } - if (globalProperties.TryGetValue(MsBuildProperties.MsBuildSdKsPath, out var msBuildSdKsPath)) - { - _oldMsBuildSdksPath = System.Environment.GetEnvironmentVariable(MsBuildProperties.MsBuildSdKsPath); - System.Environment.SetEnvironmentVariable(MsBuildProperties.MsBuildSdKsPath, msBuildSdKsPath); - } - } - - public virtual void UnsetEnvironmentVars() - { - if (_oldMsBuildExtensionsPath != null) - System.Environment.SetEnvironmentVariable(MsBuildProperties.MsBuildExtensionsPath, _oldMsBuildExtensionsPath); - if (_oldMsBuildSdksPath != null) System.Environment.SetEnvironmentVariable(MsBuildProperties.MsBuildSdKsPath, _oldMsBuildSdksPath); - } - } -} diff --git a/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/CoreEnvironment.cs b/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/CoreEnvironment.cs deleted file mode 100644 index 6bfad74b99b..00000000000 --- a/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/CoreEnvironment.cs +++ /dev/null @@ -1,61 +0,0 @@ -#region License - -//MIT License -// -//Copyright (c) 2017 Dave Glick -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files (the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. - -#endregion - -using System.Collections.Generic; -using System.IO; - -namespace DocGenerator.Buildalyzer.Environment -{ - // Based on code from OmniSharp - // https://github.com/OmniSharp/omnisharp-roslyn/blob/78ccc8b4376c73da282a600ac6fb10fce8620b52/src/OmniSharp.Abstractions/Services/DotNetCliService.cs - internal class CoreEnvironment : BuildEnvironment - { - public CoreEnvironment(string projectPath) - { - var dotnetPath = DotnetPathResolver.ResolvePath(projectPath); - ToolsPath = dotnetPath; - ExtensionsPath = dotnetPath; - SdksPath = Path.Combine(dotnetPath, "Sdks"); - RoslynTargetsPath = Path.Combine(dotnetPath, "Roslyn"); - } - - public string ExtensionsPath { get; } - public string RoslynTargetsPath { get; } - public string SdksPath { get; } - public string ToolsPath { get; } - - public override string GetToolsPath() => ToolsPath; - - public override Dictionary GetGlobalProperties(string solutionDir) - { - var globalProperties = base.GetGlobalProperties(solutionDir); - globalProperties.Add(MsBuildProperties.MsBuildExtensionsPath, ExtensionsPath); - globalProperties.Add(MsBuildProperties.MsBuildSdKsPath, SdksPath); - globalProperties.Add(MsBuildProperties.RoslynTargetsPath, RoslynTargetsPath); - return globalProperties; - } - } -} diff --git a/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/DotnetPathResolver.cs b/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/DotnetPathResolver.cs deleted file mode 100644 index 49ce2753563..00000000000 --- a/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/DotnetPathResolver.cs +++ /dev/null @@ -1,135 +0,0 @@ -#region License - -//MIT License -// -//Copyright (c) 2017 Dave Glick -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files (the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; - -namespace DocGenerator.Buildalyzer.Environment -{ - internal static class DotnetPathResolver - { - private const string DotnetCliUiLanguage = nameof(DotnetCliUiLanguage); - private static string _basePath; - - private static readonly object BasePathLock = new object(); - - public static string ResolvePath(string projectPath) - { - lock (BasePathLock) - { - if (_basePath != null) return _basePath; - - // Need to rety calling "dotnet --info" and do a hacky timeout for the process otherwise it occasionally locks up during testing (and possibly in the field) - List lines; - var retry = 0; - do - { - lines = GetInfo(projectPath); - retry++; - } while ((lines == null || lines.Count == 0) && retry < 5); - _basePath = ParseBasePath(lines); - - return _basePath; - } - } - - private static List GetInfo(string projectPath) - { - // Ensure that we set the DOTNET_CLI_UI_LANGUAGE environment variable to "en-US" before - // running 'dotnet --info'. Otherwise, we may get localized results. - var originalCliLanguage = System.Environment.GetEnvironmentVariable(DotnetCliUiLanguage); - System.Environment.SetEnvironmentVariable(DotnetCliUiLanguage, "en-US"); - - try - { - // Create the process info - var process = new Process(); - process.StartInfo.FileName = "dotnet"; - process.StartInfo.Arguments = "--info"; - process.StartInfo.WorkingDirectory = - Path.GetDirectoryName(projectPath); // global.json may change the version, so need to set working directory - process.StartInfo.CreateNoWindow = true; - process.StartInfo.UseShellExecute = false; - - // Capture output - var lines = new List(); - process.StartInfo.RedirectStandardOutput = true; - process.OutputDataReceived += (s, e) => lines.Add(e.Data); - - // Execute the process - process.Start(); - process.BeginOutputReadLine(); - var sw = new Stopwatch(); - sw.Start(); - while (!process.HasExited) - { - if (sw.ElapsedMilliseconds > 4000) break; - } - sw.Stop(); - process.Close(); - return lines; - } - finally - { - System.Environment.SetEnvironmentVariable(DotnetCliUiLanguage, originalCliLanguage); - } - } - - private static string ParseBasePath(List lines) - { - if (lines == null || lines.Count == 0) throw new InvalidOperationException("Could not get results from `dotnet --info` call"); - - foreach (var line in lines) - { - var colonIndex = line.IndexOf(':'); - if (colonIndex >= 0 - && line.Substring(0, colonIndex).Trim().Equals("Base Path", StringComparison.OrdinalIgnoreCase)) - { - var basePath = line.Substring(colonIndex + 1).Trim(); - - // Make sure the base path matches the runtime architecture if on Windows - // Note that this only works for the default installation locations under "Program Files" - if (basePath.Contains(@"\Program Files\") && !System.Environment.Is64BitProcess) - { - var newBasePath = basePath.Replace(@"\Program Files\", @"\Program Files (x86)\"); - if (Directory.Exists(newBasePath)) basePath = newBasePath; - } - else if (basePath.Contains(@"\Program Files (x86)\") && System.Environment.Is64BitProcess) - { - var newBasePath = basePath.Replace(@"\Program Files (x86)\", @"\Program Files\"); - if (Directory.Exists(newBasePath)) basePath = newBasePath; - } - - return basePath; - } - } - - throw new InvalidOperationException("Could not locate base path in `dotnet --info` results"); - } - } -} diff --git a/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/EnvironmentFactory.cs b/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/EnvironmentFactory.cs deleted file mode 100644 index 030942a4340..00000000000 --- a/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/EnvironmentFactory.cs +++ /dev/null @@ -1,74 +0,0 @@ -#region License - -//MIT License -// -//Copyright (c) 2017 Dave Glick -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files (the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. - -#endregion - -using System; -using System.Linq; -using System.Runtime.InteropServices; -using System.Xml.Linq; - -namespace DocGenerator.Buildalyzer.Environment -{ - internal abstract class EnvironmentFactory - { - public static BuildEnvironment GetBuildEnvironment(string projectPath, XDocument projectDocument) - { - // If we're running on .NET Core, use the .NET Core SDK regardless of the project file - if (RuntimeInformation.FrameworkDescription - .Replace(" ", "") - .StartsWith(".NETCore", StringComparison.OrdinalIgnoreCase)) - return new CoreEnvironment(projectPath); - - // Look at the project file to determine - var projectElement = projectDocument.GetDescendants("Project").FirstOrDefault(); - if (projectElement != null) - { - // Does this project use the SDK? - // Check for an SDK attribute on the project element - // If no attribute, check for a SDK import (see https://github.com/Microsoft/msbuild/issues/1493) - if (projectElement.GetAttributeValue("Sdk") != null - || projectElement.GetDescendants("Import").Any(x => x.GetAttributeValue("Sdk") != null)) - { - // Use the Framework tools if this project targets .NET Framework ("net" followed by a digit) - // https://docs.microsoft.com/en-us/dotnet/standard/frameworks - var targetFramework = projectElement.GetDescendants("TargetFramework").FirstOrDefault()?.Value; - if (targetFramework != null - && targetFramework.StartsWith("net", StringComparison.OrdinalIgnoreCase) - && targetFramework.Length > 3 - && char.IsDigit(targetFramework[4])) - return new FrameworkEnvironment(projectPath, true); - - // Otherwise use the .NET Core SDK - return new CoreEnvironment(projectPath); - } - - // Use Framework tools if a ToolsVersion attribute - if (projectElement.GetAttributeValue("ToolsVersion") != null) return new FrameworkEnvironment(projectPath, false); - } - - throw new InvalidOperationException("Unrecognized project file format"); - } - } -} diff --git a/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/FrameworkEnvironment.cs b/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/FrameworkEnvironment.cs deleted file mode 100644 index fa2d668184d..00000000000 --- a/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/FrameworkEnvironment.cs +++ /dev/null @@ -1,84 +0,0 @@ -#region License - -//MIT License -// -//Copyright (c) 2017 Dave Glick -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files (the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Microsoft.Build.Utilities; - -namespace DocGenerator.Buildalyzer.Environment -{ - internal class FrameworkEnvironment : BuildEnvironment - { - public FrameworkEnvironment(string projectPath, bool sdkProject) - { - ToolsPath = LocateToolsPath(); - ExtensionsPath = Path.GetFullPath(Path.Combine(ToolsPath, @"..\..\")); - SdKsPath = Path.Combine(sdkProject ? DotnetPathResolver.ResolvePath(projectPath) : ExtensionsPath, "Sdks"); - RoslynTargetsPath = Path.Combine(ToolsPath, "Roslyn"); - } - - public string ExtensionsPath { get; } - public string RoslynTargetsPath { get; } - public string SdKsPath { get; } - public string ToolsPath { get; } - - public override string GetToolsPath() => ToolsPath; - - public override Dictionary GetGlobalProperties(string solutionDir) - { - var globalProperties = base.GetGlobalProperties(solutionDir); - globalProperties.Add(MsBuildProperties.MsBuildExtensionsPath, ExtensionsPath); - globalProperties.Add(MsBuildProperties.MsBuildSdKsPath, SdKsPath); - globalProperties.Add(MsBuildProperties.RoslynTargetsPath, RoslynTargetsPath); - return globalProperties; - } - - private static string LocateToolsPath() - { - var toolsPath = ToolLocationHelper.GetPathToBuildToolsFile("msbuild.exe", ToolLocationHelper.CurrentToolsVersion); - if (string.IsNullOrEmpty(toolsPath)) toolsPath = PollForToolsPath(); - if (string.IsNullOrEmpty(toolsPath)) throw new InvalidOperationException("Could not locate the tools (msbuild.exe) path"); - - return Path.GetDirectoryName(toolsPath); - } - - // From https://github.com/KirillOsenkov/MSBuildStructuredLog/blob/4649f55f900a324421bad5a714a2584926a02138/src/StructuredLogViewer/MSBuildLocator.cs - private static string PollForToolsPath() - { - var programFilesX86 = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFilesX86); - return new[] - { - Path.Combine(programFilesX86, @"Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe"), - Path.Combine(programFilesX86, @"Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe"), - Path.Combine(programFilesX86, @"Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe") - } - .Where(File.Exists) - .FirstOrDefault(); - } - } -} diff --git a/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/MsBuildProperties.cs b/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/MsBuildProperties.cs deleted file mode 100644 index 4df9392b31f..00000000000 --- a/src/CodeGeneration/DocGenerator/Buildalyzer/Environment/MsBuildProperties.cs +++ /dev/null @@ -1,47 +0,0 @@ -#region License - -//MIT License -// -//Copyright (c) 2017 Dave Glick -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files (the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. - -#endregion - -namespace DocGenerator.Buildalyzer.Environment -{ - public static class MsBuildProperties - { - public const string BuildProjectReferences = nameof(BuildProjectReferences); - - // Design-time Build - public const string DesignTimeBuild = nameof(DesignTimeBuild); - - // Others - public const string GenerateResourceMsBuildArchitecture = nameof(GenerateResourceMsBuildArchitecture); - - // MSBuild Project Loading - public const string MsBuildExtensionsPath = nameof(MsBuildExtensionsPath); - public const string MsBuildSdKsPath = nameof(MsBuildSdKsPath); - public const string ProvideCommandLineArgs = nameof(ProvideCommandLineArgs); - public const string RoslynTargetsPath = nameof(RoslynTargetsPath); - public const string SkipCompilerExecution = nameof(SkipCompilerExecution); - public const string SolutionDir = nameof(SolutionDir); - } -} diff --git a/src/CodeGeneration/DocGenerator/Buildalyzer/Logging/EmptyDisposable.cs b/src/CodeGeneration/DocGenerator/Buildalyzer/Logging/EmptyDisposable.cs deleted file mode 100644 index 745f4b14915..00000000000 --- a/src/CodeGeneration/DocGenerator/Buildalyzer/Logging/EmptyDisposable.cs +++ /dev/null @@ -1,35 +0,0 @@ -#region License - -//MIT License -// -//Copyright (c) 2017 Dave Glick -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files (the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. - -#endregion - -using System; - -namespace DocGenerator.Buildalyzer.Logging -{ - public class EmptyDisposable : IDisposable - { - public void Dispose() { } - } -} diff --git a/src/CodeGeneration/DocGenerator/Buildalyzer/Logging/TextWriterLogger.cs b/src/CodeGeneration/DocGenerator/Buildalyzer/Logging/TextWriterLogger.cs deleted file mode 100644 index da28a3df10b..00000000000 --- a/src/CodeGeneration/DocGenerator/Buildalyzer/Logging/TextWriterLogger.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region License - -//MIT License -// -//Copyright (c) 2017 Dave Glick -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files (the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. - -#endregion - -using System; -using System.IO; -using Microsoft.Extensions.Logging; - -namespace DocGenerator.Buildalyzer.Logging -{ - internal class TextWriterLogger : ILogger - { - private readonly TextWriter _textWriter; - - public TextWriterLogger(TextWriter textWriter) => _textWriter = textWriter; - - public IDisposable BeginScope(TState state) => new EmptyDisposable(); - - public bool IsEnabled(LogLevel logLevel) => true; - - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) => - _textWriter.Write(formatter(state, exception)); - } -} diff --git a/src/CodeGeneration/DocGenerator/Buildalyzer/Logging/TextWriterLoggerProvider.cs b/src/CodeGeneration/DocGenerator/Buildalyzer/Logging/TextWriterLoggerProvider.cs deleted file mode 100644 index dc700a89d12..00000000000 --- a/src/CodeGeneration/DocGenerator/Buildalyzer/Logging/TextWriterLoggerProvider.cs +++ /dev/null @@ -1,42 +0,0 @@ -#region License - -//MIT License -// -//Copyright (c) 2017 Dave Glick -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files (the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. - -#endregion - -using System.IO; -using Microsoft.Extensions.Logging; - -namespace DocGenerator.Buildalyzer.Logging -{ - public class TextWriterLoggerProvider : ILoggerProvider - { - private readonly TextWriter _textWriter; - - public TextWriterLoggerProvider(TextWriter textWriter) => _textWriter = textWriter; - - public void Dispose() { } - - public ILogger CreateLogger(string categoryName) => new TextWriterLogger(_textWriter); - } -} diff --git a/src/CodeGeneration/DocGenerator/Buildalyzer/ProjectAnalyzer.cs b/src/CodeGeneration/DocGenerator/Buildalyzer/ProjectAnalyzer.cs deleted file mode 100644 index 9c4a9fab913..00000000000 --- a/src/CodeGeneration/DocGenerator/Buildalyzer/ProjectAnalyzer.cs +++ /dev/null @@ -1,228 +0,0 @@ -#region License - -//MIT License -// -//Copyright (c) 2017 Dave Glick -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files (the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Xml.Linq; -using DocGenerator.Buildalyzer.Environment; -using Microsoft.Build.Evaluation; -using Microsoft.Build.Execution; -using Microsoft.Build.Logging; -using Microsoft.Build.Tasks; -using Microsoft.Build.Utilities; -using Microsoft.Extensions.Logging; -using ILogger = Microsoft.Build.Framework.ILogger; - -namespace DocGenerator.Buildalyzer -{ - public class ProjectAnalyzer - { - private readonly BuildEnvironment _buildEnvironment; - private readonly Dictionary _globalProperties; - private readonly ConsoleLogger _logger; - private readonly XDocument _projectDocument; - private ProjectInstance _compiledProject; - - private Project _project; - - internal ProjectAnalyzer(AnalyzerManager manager, string projectFilePath) - : this(manager, projectFilePath, XDocument.Load(projectFilePath)) { } - - internal ProjectAnalyzer(AnalyzerManager manager, string projectFilePath, XDocument projectDocument) - { - Manager = manager; - ProjectFilePath = projectFilePath; - var projectFolder = Path.GetDirectoryName(projectFilePath); - _projectDocument = TweakProjectDocument(projectDocument, projectFolder); - - // Get the paths - _buildEnvironment = EnvironmentFactory.GetBuildEnvironment(projectFilePath, _projectDocument); - - // Preload/enforce referencing some required assemblies - // ReSharper disable once UnusedVariable - var copy = new Copy(); - - - var solutionDir = manager.SolutionDirectory ?? projectFolder; - _globalProperties = _buildEnvironment.GetGlobalProperties(solutionDir); - - // Create the logger - if (manager.ProjectLogger != null) - _logger = new ConsoleLogger(manager.LoggerVerbosity, x => manager.ProjectLogger.LogInformation(x), null, null); - } - - public ProjectInstance CompiledProject => Compile(); - - /// - /// The global properties for MSBuild. By default, each project - /// is configured with properties that use a design-time build without calling the compiler. - /// - public IReadOnlyDictionary GlobalProperties => _globalProperties; - - public AnalyzerManager Manager { get; } - - public Project Project => Load(); - - public string ProjectFilePath { get; } - - public Project Load() - { - if (_project != null) return _project; - - // Create a project collection for each project since the toolset might change depending on the type of project - var projectCollection = CreateProjectCollection(); - - // Load the project - _buildEnvironment.SetEnvironmentVars(GlobalProperties); - try - { - using (var projectReader = _projectDocument.CreateReader()) - { - _project = projectCollection.LoadProject(projectReader); - _project.FullPath = ProjectFilePath; - } - return _project; - } - finally - { - _buildEnvironment.UnsetEnvironmentVars(); - } - } - - - // Tweaks the project file a bit to ensure a succesfull build - private static XDocument TweakProjectDocument(XDocument projectDocument, string projectFolder) - { - foreach (var import in projectDocument.GetDescendants("Import").ToArray()) - { - var att = import.Attribute("Project"); - if (att == null) continue; - - var project = att.Value; - - if (!ResolveKnownPropsPath(projectFolder, project, att, "PublishArtifacts.build.props")) - ResolveKnownPropsPath(projectFolder, project, att, "Artifacts.build.props"); - ResolveKnownPropsPath(projectFolder, project, att, "Library.build.props"); - } - // Add SkipGetTargetFrameworkProperties to every ProjectReference - foreach (var projectReference in projectDocument.GetDescendants("ProjectReference").ToArray()) - projectReference.AddChildElement("SkipGetTargetFrameworkProperties", "true"); - - // Removes all EnsureNuGetPackageBuildImports - foreach (var ensureNuGetPackageBuildImports in - projectDocument.GetDescendants("Target").Where(x => x.GetAttributeValue("Name") == "EnsureNuGetPackageBuildImports").ToArray()) - ensureNuGetPackageBuildImports.Remove(); - - return projectDocument; - } - - private static bool ResolveKnownPropsPath(string projectFolder, string project, XAttribute att, string buildPropFile) - { - if (!project.Contains(buildPropFile)) return false; - - var dir = new DirectoryInfo(projectFolder).Parent; - while (dir != null && dir.Name != "src") - dir = dir.Parent; - if (dir == null) return true; - - att.Value = Path.GetFullPath(Path.Combine(dir.FullName, buildPropFile)); - return false; - } - - private ProjectCollection CreateProjectCollection() - { - var projectCollection = new ProjectCollection(_globalProperties); - projectCollection.RemoveAllToolsets(); // Make sure we're only using the latest tools - projectCollection.AddToolset( - new Toolset(ToolLocationHelper.CurrentToolsVersion, _buildEnvironment.GetToolsPath(), projectCollection, string.Empty)); - projectCollection.DefaultToolsVersion = ToolLocationHelper.CurrentToolsVersion; - if (_logger != null) projectCollection.RegisterLogger(_logger); - return projectCollection; - } - - public ProjectInstance Compile() - { - if (_compiledProject != null) return _compiledProject; - - var project = Load(); - if (project == null) return null; - - // Compile the project - _buildEnvironment.SetEnvironmentVars(GlobalProperties); - try - { - var projectInstance = project.CreateProjectInstance(); - if (!projectInstance.Build("Clean", _logger == null ? null : new ILogger[] { _logger })) return null; - - if (!projectInstance.Build("Compile", _logger == null ? null : new ILogger[] { _logger })) return null; - - _compiledProject = projectInstance; - return _compiledProject; - } - finally - { - _buildEnvironment.UnsetEnvironmentVars(); - } - } - - public IReadOnlyList GetSourceFiles() => - Compile() - ?.Items - .Where(x => x.ItemType == "CscCommandLineArgs" && !x.EvaluatedInclude.StartsWith("/")) - .Select(x => Path.GetFullPath(Path.Combine(Path.GetDirectoryName(ProjectFilePath), x.EvaluatedInclude))) - .ToList(); - - public IReadOnlyList GetReferences() => - Compile() - ?.Items - .Where(x => x.ItemType == "CscCommandLineArgs" && x.EvaluatedInclude.StartsWith("/reference:")) - .Select(x => x.EvaluatedInclude.Substring(11).Trim('"')) - .ToList(); - - public IReadOnlyList GetProjectReferences() => - Compile() - ?.Items - .Where(x => x.ItemType == "ProjectReference") - .Select(x => Path.GetFullPath(Path.Combine(Path.GetDirectoryName(ProjectFilePath), x.EvaluatedInclude))) - .ToList(); - - public void SetGlobalProperty(string key, string value) - { - if (_project != null) throw new InvalidOperationException("Can not change global properties once project has been loaded"); - - _globalProperties[key] = value; - } - - public bool RemoveGlobalProperty(string key) - { - if (_project != null) throw new InvalidOperationException("Can not change global properties once project has been loaded"); - - return _globalProperties.Remove(key); - } - } -} diff --git a/src/CodeGeneration/DocGenerator/Buildalyzer/ProjectAnalyzerExtensions.cs b/src/CodeGeneration/DocGenerator/Buildalyzer/ProjectAnalyzerExtensions.cs deleted file mode 100644 index 8e2d08f8e34..00000000000 --- a/src/CodeGeneration/DocGenerator/Buildalyzer/ProjectAnalyzerExtensions.cs +++ /dev/null @@ -1,211 +0,0 @@ -#region License - -//MIT License -// -//Copyright (c) 2017 Dave Glick -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files (the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Text; -using Microsoft.CodeAnalysis.VisualBasic; - -namespace DocGenerator.Buildalyzer -{ - public static class ProjectAnalyzerExtensions - { - /// - /// Gets a Roslyn workspace for the analyzed project. - /// - /// The Buildalyzer project analyzer. - /// - /// true to add projects to the workspace for project references that exist in the same - /// . - /// - /// A Roslyn workspace. - public static AdhocWorkspace GetWorkspace(this ProjectAnalyzer analyzer, bool addProjectReferences = false) - { - if (analyzer == null) throw new ArgumentNullException(nameof(analyzer)); - - var workspace = new AdhocWorkspace(); - AddToWorkspace(analyzer, workspace, addProjectReferences); - return workspace; - } - - /// - /// Adds a project to an existing Roslyn workspace. - /// - /// The Buildalyzer project analyzer. - /// A Roslyn workspace. - /// - /// true to add projects to the workspace for project references that exist in the same - /// . - /// - /// The newly added Roslyn project. - public static Project AddToWorkspace(this ProjectAnalyzer analyzer, AdhocWorkspace workspace, bool addProjectReferences = false) - { - if (analyzer == null) throw new ArgumentNullException(nameof(analyzer)); - - if (workspace == null) throw new ArgumentNullException(nameof(workspace)); - - // Get or create an ID for this project - var projectGuid = analyzer.CompiledProject?.GetPropertyValue("ProjectGuid"); - var projectId = !string.IsNullOrEmpty(projectGuid) - && Guid.TryParse(analyzer.CompiledProject?.GetPropertyValue("ProjectGuid"), out var projectIdGuid) - ? ProjectId.CreateFromSerialized(projectIdGuid) - : ProjectId.CreateNewId(); - - // Create and add the project - var projectInfo = GetProjectInfo(analyzer, workspace, projectId); - var solution = workspace.CurrentSolution.AddProject(projectInfo); - - // Check if this project is referenced by any other projects in the workspace - foreach (var existingProject in solution.Projects.ToArray()) - { - if (!existingProject.Id.Equals(projectId) - && analyzer.Manager.Projects.TryGetValue(existingProject.FilePath, out var existingAnalyzer) - && (existingAnalyzer.GetProjectReferences()?.Contains(analyzer.ProjectFilePath) ?? false)) - { - // Add the reference to the existing project - var projectReference = new ProjectReference(projectId); - solution = solution.AddProjectReference(existingProject.Id, projectReference); - } - } - - // Apply solution changes - if (!workspace.TryApplyChanges(solution)) throw new InvalidOperationException("Could not apply workspace solution changes"); - - // Add any project references not already added - if (addProjectReferences) - { - foreach (var referencedAnalyzer in GetReferencedAnalyzerProjects(analyzer)) - { - // Check if the workspace contains the project inside the loop since adding one might also add this one due to transitive references - if (!workspace.CurrentSolution.Projects.Any(x => x.FilePath == referencedAnalyzer.ProjectFilePath)) - AddToWorkspace(referencedAnalyzer, workspace, addProjectReferences); - } - } - - // Find and return this project - return workspace.CurrentSolution.GetProject(projectId); - } - - private static ProjectInfo GetProjectInfo(ProjectAnalyzer analyzer, AdhocWorkspace workspace, ProjectId projectId) - { - var projectName = Path.GetFileNameWithoutExtension(analyzer.ProjectFilePath); - var languageName = GetLanguageName(analyzer.ProjectFilePath); - var projectInfo = ProjectInfo.Create( - projectId, - VersionStamp.Create(), - projectName, - projectName, - languageName, - analyzer.ProjectFilePath, - analyzer.CompiledProject?.GetPropertyValue("TargetPath"), - documents: GetDocuments(analyzer, projectId), - projectReferences: GetExistingProjectReferences(analyzer, workspace), - metadataReferences: GetMetadataReferences(analyzer), - compilationOptions: CreateCompilationOptions(analyzer.Project, languageName)); - return projectInfo; - } - - private static CompilationOptions CreateCompilationOptions(Microsoft.Build.Evaluation.Project project, string languageName) - { - var outputType = project.GetPropertyValue("OutputType"); - OutputKind? kind = null; - switch (outputType) - { - case "Library": - kind = OutputKind.DynamicallyLinkedLibrary; - break; - case "Exe": - kind = OutputKind.ConsoleApplication; - break; - case "Module": - kind = OutputKind.NetModule; - break; - case "Winexe": - kind = OutputKind.WindowsApplication; - break; - } - - if (kind.HasValue) - { - if (languageName == LanguageNames.CSharp) return new CSharpCompilationOptions(kind.Value); - - if (languageName == LanguageNames.VisualBasic) return new VisualBasicCompilationOptions(kind.Value); - } - - return null; - } - - private static IEnumerable GetExistingProjectReferences(ProjectAnalyzer analyzer, AdhocWorkspace workspace) => - analyzer.GetProjectReferences() - ?.Select(x => workspace.CurrentSolution.Projects.FirstOrDefault(y => y.FilePath == x)) - .Where(x => x != null) - .Select(x => new ProjectReference(x.Id)) - ?? Array.Empty(); - - private static IEnumerable GetReferencedAnalyzerProjects(ProjectAnalyzer analyzer) => - analyzer.GetProjectReferences() - ?.Select(x => analyzer.Manager.Projects.TryGetValue(x, out var a) ? a : null) - .Where(x => x != null) - ?? Array.Empty(); - - private static IEnumerable GetDocuments(ProjectAnalyzer analyzer, ProjectId projectId) => - analyzer - .GetSourceFiles() - ?.Where(File.Exists) - .Select(x => DocumentInfo.Create( - DocumentId.CreateNewId(projectId), - Path.GetFileName(x), - loader: TextLoader.From( - TextAndVersion.Create( - SourceText.From(File.ReadAllText(x)), VersionStamp.Create())), - filePath: x)) - ?? Array.Empty(); - - private static IEnumerable GetMetadataReferences(ProjectAnalyzer analyzer) => - analyzer - .GetReferences() - ?.Where(File.Exists) - .Select(x => MetadataReference.CreateFromFile(x)) - ?? (IEnumerable)Array.Empty(); - - private static string GetLanguageName(string projectPath) - { - switch (Path.GetExtension(projectPath)) - { - case ".csproj": - return LanguageNames.CSharp; - case ".vbproj": - return LanguageNames.VisualBasic; - default: - throw new InvalidOperationException("Could not determine supported language from project path"); - } - } - } -} diff --git a/src/CodeGeneration/DocGenerator/Buildalyzer/XDocumentExtensions.cs b/src/CodeGeneration/DocGenerator/Buildalyzer/XDocumentExtensions.cs deleted file mode 100644 index 86dd59a5546..00000000000 --- a/src/CodeGeneration/DocGenerator/Buildalyzer/XDocumentExtensions.cs +++ /dev/null @@ -1,49 +0,0 @@ -#region License - -//MIT License -// -//Copyright (c) 2017 Dave Glick -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files (the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Xml.Linq; - -namespace DocGenerator.Buildalyzer -{ - internal static class XDocumentExtensions - { - public static IEnumerable GetDescendants(this XDocument document, string name) => - document.Descendants().Where(x => string.Equals(x.Name.LocalName, name, StringComparison.OrdinalIgnoreCase)); - - public static IEnumerable GetDescendants(this XElement element, string name) => - element.Descendants().Where(x => string.Equals(x.Name.LocalName, name, StringComparison.OrdinalIgnoreCase)); - - public static string GetAttributeValue(this XElement element, string name) => - element.Attributes().FirstOrDefault(x => string.Equals(x.Name.LocalName, name, StringComparison.OrdinalIgnoreCase))?.Value; - - // Adds a child element with the same namespace as the parent - public static void AddChildElement(this XElement element, string name, string value) => - element.Add(new XElement(XName.Get(name, element.Name.NamespaceName), value)); - } -} diff --git a/src/CodeGeneration/DocGenerator/DocGenerator.csproj b/src/CodeGeneration/DocGenerator/DocGenerator.csproj index a9559f22a7f..b4a29d1efdc 100644 --- a/src/CodeGeneration/DocGenerator/DocGenerator.csproj +++ b/src/CodeGeneration/DocGenerator/DocGenerator.csproj @@ -11,12 +11,15 @@ - + + + + - - + + \ No newline at end of file diff --git a/src/CodeGeneration/DocGenerator/LitUp.cs b/src/CodeGeneration/DocGenerator/LitUp.cs index dfaf25eaaae..5f457ed0ec2 100644 --- a/src/CodeGeneration/DocGenerator/LitUp.cs +++ b/src/CodeGeneration/DocGenerator/LitUp.cs @@ -4,7 +4,8 @@ using System.IO; using System.Linq; using System.Threading.Tasks; -using DocGenerator.Buildalyzer; +using Buildalyzer; +using Buildalyzer.Workspaces; using DocGenerator.Documentation.Files; using Microsoft.CodeAnalysis; @@ -48,20 +49,20 @@ public static async Task GoAsync(string[] args) //.NET core csprojects are not supported all that well. // https://github.com/dotnet/roslyn/issues/21660 :sadpanda: // Use Buildalyzer to get a workspace from the solution. - var analyzer = new AnalyzerManager(Path.Combine(Program.InputDirPath, "Elasticsearch.sln"), new[] - { - "Elasticsearch.Net", - "Nest", - "Tests" - }); + var options = new AnalyzerManagerOptions() { }; + + var analyzer = new AnalyzerManager(Path.Combine(Program.InputDirPath, "CodeGeneration", "ElasticsearchCodeGeneration.sln")); var workspace = analyzer.GetWorkspace(); - workspace.WorkspaceFailed += (s, e) => { Console.Error.WriteLine(e.Diagnostic.Message); }; + workspace.WorkspaceFailed += (s, e) => + { + Console.Error.WriteLine(e.Diagnostic.Message); + }; // Buildalyzer, similar to MsBuildWorkspace with the new csproj file format, does // not pick up source documents in the project directory. Manually add them - AddDocumentsToWorkspace(workspace); + // AddDocumentsToWorkspace(workspace); var projects = workspace.CurrentSolution.Projects .ToDictionary(p => p.Name, StringComparer.OrdinalIgnoreCase); diff --git a/src/CodeGeneration/DocGenerator/Program.cs b/src/CodeGeneration/DocGenerator/Program.cs index 30acb594512..b0520bc7865 100644 --- a/src/CodeGeneration/DocGenerator/Program.cs +++ b/src/CodeGeneration/DocGenerator/Program.cs @@ -4,6 +4,9 @@ using System.Linq; using System.Text.RegularExpressions; using CommandLine; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace DocGenerator { @@ -11,37 +14,31 @@ public static class Program { static Program() { - string P(string path) - { - return path.Replace(@"\", Path.DirectorySeparatorChar.ToString()); - } + var root = new DirectoryInfo(Directory.GetCurrentDirectory()); - var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory()); - var globalJson = P(@"..\..\..\global.json"); - if (currentDirectory.Name == "DocGenerator" && currentDirectory.Parent.Name == "CodeGeneration") - { - Console.WriteLine("IDE: " + currentDirectory); - InputDirPath = P(@"..\..\"); - OutputDirPath = P(@"..\..\..\docs"); - BuildOutputPath = P(@"..\..\..\src"); - } - else + do { - globalJson = P(@"..\..\..\..\global.json"); - Console.WriteLine("CMD: " + currentDirectory); - InputDirPath = P(@"..\..\..\..\src"); - OutputDirPath = P(@"..\..\..\..\docs"); - BuildOutputPath = P(@"..\..\..\..\build\output"); - } + if (File.Exists(Path.Combine(root.FullName, "global.json"))) + break; + root = root.Parent; + } while (root != null && root.Parent != root.Root); + + if (root == null || root.Parent == root.Root) + throw new Exception("Expected to find a global.json in a parent folder"); + + + var r = root.FullName; + var globalJson = Path.Combine(r, "global.json"); + InputDirPath = Path.Combine(r, "src"); + OutputDirPath = Path.Combine(r, "docs"); + BuildOutputPath = Path.Combine(r, "build", "output"); - var globalJsonVersion = string.Join(".", Regex.Matches(File.ReadAllText(globalJson), "\"version\": \"(.*)\"") - .Last() - .Groups[^1] - .Value - .Split(".") - .Take(2)); + var jObject = JObject.Parse(File.ReadAllText(globalJson)); - DocVersion = globalJsonVersion; + DocVersion = string.Join(".", jObject["doc_current"] + .Value() + .Split(".") + .Take(2)); var process = new Process { diff --git a/src/CodeGeneration/ElasticsearchCodeGeneration.sln b/src/CodeGeneration/ElasticsearchCodeGeneration.sln new file mode 100644 index 00000000000..be6386a7810 --- /dev/null +++ b/src/CodeGeneration/ElasticsearchCodeGeneration.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DocGenerator", "DocGenerator\DocGenerator.csproj", "{CA294A8E-DD3D-48EE-8EE2-A9D4461BD5B5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elasticsearch.Net", "..\Elasticsearch.Net\Elasticsearch.Net.csproj", "{3EDAD606-EA29-4F03-B4A1-F301542C9C77}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nest", "..\Nest\Nest.csproj", "{D9E18A91-86F1-4F55-8AC6-015EAB4D3360}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "..\Tests\Tests\Tests.csproj", "{C268FDAD-F6A6-479D-A1DC-10A5DE67A076}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CA294A8E-DD3D-48EE-8EE2-A9D4461BD5B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CA294A8E-DD3D-48EE-8EE2-A9D4461BD5B5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CA294A8E-DD3D-48EE-8EE2-A9D4461BD5B5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CA294A8E-DD3D-48EE-8EE2-A9D4461BD5B5}.Release|Any CPU.Build.0 = Release|Any CPU + {3EDAD606-EA29-4F03-B4A1-F301542C9C77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3EDAD606-EA29-4F03-B4A1-F301542C9C77}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3EDAD606-EA29-4F03-B4A1-F301542C9C77}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3EDAD606-EA29-4F03-B4A1-F301542C9C77}.Release|Any CPU.Build.0 = Release|Any CPU + {D9E18A91-86F1-4F55-8AC6-015EAB4D3360}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D9E18A91-86F1-4F55-8AC6-015EAB4D3360}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9E18A91-86F1-4F55-8AC6-015EAB4D3360}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D9E18A91-86F1-4F55-8AC6-015EAB4D3360}.Release|Any CPU.Build.0 = Release|Any CPU + {C268FDAD-F6A6-479D-A1DC-10A5DE67A076}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C268FDAD-F6A6-479D-A1DC-10A5DE67A076}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C268FDAD-F6A6-479D-A1DC-10A5DE67A076}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C268FDAD-F6A6-479D-A1DC-10A5DE67A076}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/src/Elasticsearch.Net/Elasticsearch.Net.csproj b/src/Elasticsearch.Net/Elasticsearch.Net.csproj index 3ae8df766cb..5942135cc34 100644 --- a/src/Elasticsearch.Net/Elasticsearch.Net.csproj +++ b/src/Elasticsearch.Net/Elasticsearch.Net.csproj @@ -7,6 +7,7 @@ true $(DefineConstants);NETSTANDARD + 8.0 diff --git a/src/Nest/Nest.csproj b/src/Nest/Nest.csproj index d282ca11458..9ad120fbcd2 100644 --- a/src/Nest/Nest.csproj +++ b/src/Nest/Nest.csproj @@ -3,6 +3,7 @@ netstandard2.0;net461 + 8.0 diff --git a/src/Tests/Tests/Tests.csproj b/src/Tests/Tests/Tests.csproj index 0742d540cbb..ac3fc36ef5c 100644 --- a/src/Tests/Tests/Tests.csproj +++ b/src/Tests/Tests/Tests.csproj @@ -6,6 +6,7 @@ $(NoWarn);xUnit1013 True True + 8.0