From 4d7b7d9b733d6a9da1f7efde03cbb05baa71e7cf Mon Sep 17 00:00:00 2001 From: Ignacio Etcheverry Date: Thu, 20 Aug 2020 12:56:36 +0200 Subject: [PATCH] 3.2 C#: Upgrade GodotTools to nuget Microsoft.Build This upgrade is needed in order to support reading and editing project files that use Sdks as well as other new features. A common example in 3.2 is having to specify a PackageReference version with a child element rather than the attribute. This is no longer the case now. Partial cherry-pick of f3bcd5f8dd36c4ce384f00a03650f71dce5c4de6 Most of the other changes from that commit were already partially cherry-picked in 3928fe200f1fda49655b429bd64f7bb55457c30d. --- .../GodotBuildLogger.cs | 16 +++++++++-- .../GodotTools.BuildLogger.csproj | 8 +++--- .../GodotTools.Core/GodotTools.Core.csproj | 8 ++---- .../GodotTools.Core/StringExtensions.cs | 14 ++-------- .../GodotTools.ProjectEditor.csproj | 14 +++++++--- .../GodotTools.ProjectEditor/MSBuild.exe | 0 .../ProjectExtensions.cs | 10 +++---- .../GodotTools.ProjectEditor/ProjectUtils.cs | 7 ++--- .../GodotTools/Build/MsBuildFinder.cs | 17 +++++------- .../editor/GodotTools/GodotTools/BuildTab.cs | 12 ++++----- .../GodotTools/GodotTools/GodotSharpEditor.cs | 8 +++--- .../GodotTools/GodotTools/GodotTools.csproj | 6 +---- .../GodotTools/Ides/MonoDevelop/Instance.cs | 2 +- .../GodotTools/Ides/Rider/RiderPathLocator.cs | 6 ++--- .../editor/GodotTools/GodotTools/Utils/OS.cs | 27 +++++++++---------- 15 files changed, 71 insertions(+), 84 deletions(-) create mode 100644 modules/mono/editor/GodotTools/GodotTools.ProjectEditor/MSBuild.exe diff --git a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs index 6015cb22b6e..3c1d21f5810 100644 --- a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs +++ b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs @@ -2,7 +2,6 @@ using System; using System.IO; using System.Security; using Microsoft.Build.Framework; -using GodotTools.Core; namespace GodotTools.BuildLogger { @@ -18,7 +17,7 @@ namespace GodotTools.BuildLogger if (null == Parameters) throw new LoggerException("Log directory was not set."); - var parameters = Parameters.Split(new[] { ';' }); + var parameters = Parameters.Split(new[] {';'}); string logDir = parameters[0]; @@ -183,4 +182,17 @@ namespace GodotTools.BuildLogger private StreamWriter issuesStreamWriter; private int indent; } + + internal static class StringExtensions + { + public static string CsvEscape(this string value, char delimiter = ',') + { + bool hasSpecialChar = value.IndexOfAny(new[] {'\"', '\n', '\r', delimiter}) != -1; + + if (hasSpecialChar) + return "\"" + value.Replace("\"", "\"\"") + "\""; + + return value; + } + } } diff --git a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj index 8e53a9b44b5..f0f586d43c1 100644 --- a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj @@ -1,13 +1,11 @@ {6CE9A984-37B1-4F8A-8FE9-609F05F071B3} - Library - net472 - 7 + netstandard2.0 + 7.2 - - + diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj b/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj index 135e61ec99f..d6d8962f90e 100644 --- a/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj @@ -1,11 +1,7 @@ {639E48BD-44E5-4091-8EDD-22D36DC0768D} - Library - net472 - 7 + netstandard2.0 + 7.2 - - - diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs b/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs index 890138911a0..012b69032e0 100644 --- a/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs +++ b/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs @@ -34,23 +34,13 @@ namespace GodotTools.Core return rooted ? Path.DirectorySeparatorChar + path : path; } - private static readonly string driveRoot = Path.GetPathRoot(Environment.CurrentDirectory); + private static readonly string DriveRoot = Path.GetPathRoot(Environment.CurrentDirectory); public static bool IsAbsolutePath(this string path) { return path.StartsWith("/", StringComparison.Ordinal) || path.StartsWith("\\", StringComparison.Ordinal) || - path.StartsWith(driveRoot, StringComparison.Ordinal); - } - - public static string CsvEscape(this string value, char delimiter = ',') - { - bool hasSpecialChar = value.IndexOfAny(new char[] { '\"', '\n', '\r', delimiter }) != -1; - - if (hasSpecialChar) - return "\"" + value.Replace("\"", "\"\"") + "\""; - - return value; + path.StartsWith(DriveRoot, StringComparison.Ordinal); } public static string ToSafeDirName(this string dirName, bool allowDirSeparator) diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj index 8dadea12990..0ca3177c78e 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj @@ -1,16 +1,24 @@  {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984} - Library net472 - 7 + 7.2 - + + + + + diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/MSBuild.exe b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/MSBuild.exe new file mode 100644 index 00000000000..e69de29bb2d diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectExtensions.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectExtensions.cs index f0e0d1b33de..14e2ca2c13a 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectExtensions.cs +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectExtensions.cs @@ -2,8 +2,8 @@ using GodotTools.Core; using System; using System.Collections.Generic; using System.IO; -using DotNet.Globbing; using Microsoft.Build.Construction; +using Microsoft.Build.Globbing; namespace GodotTools.ProjectEditor { @@ -11,8 +11,6 @@ namespace GodotTools.ProjectEditor { public static ProjectItemElement FindItemOrNull(this ProjectRootElement root, string itemType, string include, bool noCondition = false) { - GlobOptions globOptions = new GlobOptions {Evaluation = {CaseInsensitive = false}}; - string normalizedInclude = include.NormalizePath(); foreach (var itemGroup in root.ItemGroups) @@ -25,7 +23,7 @@ namespace GodotTools.ProjectEditor if (item.ItemType != itemType) continue; - var glob = Glob.Parse(item.Include.NormalizePath(), globOptions); + var glob = MSBuildGlob.Parse(item.Include.NormalizePath()); if (glob.IsMatch(normalizedInclude)) return item; @@ -36,8 +34,6 @@ namespace GodotTools.ProjectEditor } public static ProjectItemElement FindItemOrNullAbs(this ProjectRootElement root, string itemType, string include, bool noCondition = false) { - GlobOptions globOptions = new GlobOptions {Evaluation = {CaseInsensitive = false}}; - string normalizedInclude = Path.GetFullPath(include).NormalizePath(); foreach (var itemGroup in root.ItemGroups) @@ -50,7 +46,7 @@ namespace GodotTools.ProjectEditor if (item.ItemType != itemType) continue; - var glob = Glob.Parse(Path.GetFullPath(item.Include).NormalizePath(), globOptions); + var glob = MSBuildGlob.Parse(Path.GetFullPath(item.Include).NormalizePath()); if (glob.IsMatch(normalizedInclude)) return item; diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs index ef465190645..8774b4ee310 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs @@ -4,8 +4,8 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; -using DotNet.Globbing; using Microsoft.Build.Construction; +using Microsoft.Build.Globbing; namespace GodotTools.ProjectEditor { @@ -133,9 +133,6 @@ namespace GodotTools.ProjectEditor var result = new List(); var existingFiles = GetAllFilesRecursive(Path.GetDirectoryName(projectPath), "*.cs"); - var globOptions = new GlobOptions(); - globOptions.Evaluation.CaseInsensitive = false; - var root = ProjectRootElement.Open(projectPath); Debug.Assert(root != null); @@ -151,7 +148,7 @@ namespace GodotTools.ProjectEditor string normalizedInclude = item.Include.NormalizePath(); - var glob = Glob.Parse(normalizedInclude, globOptions); + var glob = MSBuildGlob.Parse(normalizedInclude); // TODO Check somehow if path has no blob to avoid the following loop... diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs index 7da6d082ffa..d11b7432e70 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs @@ -36,15 +36,13 @@ namespace GodotTools.Build } case BuildTool.MsBuildVs: { - if (_msbuildToolsPath.Empty() || !File.Exists(_msbuildToolsPath)) + if (string.IsNullOrEmpty(_msbuildToolsPath) || !File.Exists(_msbuildToolsPath)) { // Try to search it again if it wasn't found last time or if it was removed from its location _msbuildToolsPath = FindMsBuildToolsPathOnWindows(); - if (_msbuildToolsPath.Empty()) - { + if (string.IsNullOrEmpty(_msbuildToolsPath)) throw new FileNotFoundException($"Cannot find executable for '{BuildManager.PropNameMSBuildVs}'."); - } } if (!_msbuildToolsPath.EndsWith("\\")) @@ -57,15 +55,14 @@ namespace GodotTools.Build string msbuildPath = Path.Combine(Internal.MonoWindowsInstallRoot, "bin", "msbuild.bat"); if (!File.Exists(msbuildPath)) - { throw new FileNotFoundException($"Cannot find executable for '{BuildManager.PropNameMSBuildMono}'. Tried with path: {msbuildPath}"); - } return (msbuildPath, BuildTool.MsBuildMono); } case BuildTool.JetBrainsMsBuild: { var editorPath = (string)editorSettings.GetSetting(RiderPathManager.EditorPathSettingName); + if (!File.Exists(editorPath)) throw new FileNotFoundException($"Cannot find Rider executable. Tried with path: {editorPath}"); @@ -83,7 +80,7 @@ namespace GodotTools.Build } } - if (OS.IsUnixLike()) + if (OS.IsUnixLike) { switch (buildTool) { @@ -138,12 +135,12 @@ namespace GodotTools.Build { string ret = OS.PathWhich(name); - if (!ret.Empty()) + if (!string.IsNullOrEmpty(ret)) return ret; string retFallback = OS.PathWhich($"{name}.exe"); - if (!retFallback.Empty()) + if (!string.IsNullOrEmpty(retFallback)) return retFallback; foreach (string hintDir in MsBuildHintDirs) @@ -195,7 +192,7 @@ namespace GodotTools.Build string value = line.Substring(sepIdx + 1).StripEdges(); - if (value.Empty()) + if (string.IsNullOrEmpty(value)) throw new FormatException("installationPath value is empty"); if (!value.EndsWith("\\")) diff --git a/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs b/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs index 727581daab3..b35bd3244b0 100644 --- a/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs +++ b/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs @@ -72,7 +72,7 @@ namespace GodotTools { string[] csvColumns = file.GetCsvLine(); - if (csvColumns.Length == 1 && csvColumns[0].Empty()) + if (csvColumns.Length == 1 && string.IsNullOrEmpty(csvColumns[0])) return; if (csvColumns.Length != 7) @@ -115,12 +115,12 @@ namespace GodotTools // Get correct issue idx from issue list int issueIndex = (int)issuesList.GetItemMetadata(idx); - if (idx < 0 || idx >= issues.Count) + if (issueIndex < 0 || issueIndex >= issues.Count) throw new IndexOutOfRangeException("Issue index out of range"); BuildIssue issue = issues[issueIndex]; - if (issue.ProjectFile.Empty() && issue.File.Empty()) + if (string.IsNullOrEmpty(issue.ProjectFile) && string.IsNullOrEmpty(issue.File)) return; string projectDir = issue.ProjectFile.Length > 0 ? issue.ProjectFile.GetBaseDir() : BuildInfo.Solution.GetBaseDir(); @@ -158,14 +158,14 @@ namespace GodotTools string tooltip = string.Empty; tooltip += $"Message: {issue.Message}"; - if (!issue.Code.Empty()) + if (!string.IsNullOrEmpty(issue.Code)) tooltip += $"\nCode: {issue.Code}"; tooltip += $"\nType: {(issue.Warning ? "warning" : "error")}"; string text = string.Empty; - if (!issue.File.Empty()) + if (!string.IsNullOrEmpty(issue.File)) { text += $"{issue.File}({issue.Line},{issue.Column}): "; @@ -174,7 +174,7 @@ namespace GodotTools tooltip += $"\nColumn: {issue.Column}"; } - if (!issue.ProjectFile.Empty()) + if (!string.IsNullOrEmpty(issue.ProjectFile)) tooltip += $"\nProject: {issue.ProjectFile}"; text += issue.Message; diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index d9af134e2b3..747db262046 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -302,7 +302,7 @@ namespace GodotTools case ExternalEditorId.VsCode: { - if (_vsCodePath.Empty() || !File.Exists(_vsCodePath)) + if (string.IsNullOrEmpty(_vsCodePath) || !File.Exists(_vsCodePath)) { // Try to search it again if it wasn't found last time or if it was removed from its location _vsCodePath = VsCodeNames.SelectFirstNotNull(OS.PathWhich, orElse: string.Empty); @@ -354,7 +354,7 @@ namespace GodotTools if (OS.IsOSX) { - if (!osxAppBundleInstalled && _vsCodePath.Empty()) + if (!osxAppBundleInstalled && string.IsNullOrEmpty(_vsCodePath)) { GD.PushError("Cannot find code editor: VSCode"); return Error.FileNotFound; @@ -364,7 +364,7 @@ namespace GodotTools } else { - if (_vsCodePath.Empty()) + if (string.IsNullOrEmpty(_vsCodePath)) { GD.PushError("Cannot find code editor: VSCode"); return Error.FileNotFound; @@ -551,7 +551,7 @@ namespace GodotTools $",Visual Studio Code:{(int)ExternalEditorId.VsCode}" + $",JetBrains Rider:{(int)ExternalEditorId.Rider}"; } - else if (OS.IsUnixLike()) + else if (OS.IsUnixLike) { settingsHintStr += $",MonoDevelop:{(int)ExternalEditorId.MonoDevelop}" + $",Visual Studio Code:{(int)ExternalEditorId.VsCode}" + diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj index df0eb26be15..2c4537f5254 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj +++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj @@ -1,12 +1,8 @@ {27B00618-A6F2-4828-B922-05CAEB08C286} - Library net472 - $(SolutionDir)/../../../../ - $(GodotSourceRootPath)/bin/GodotSharp/Tools - Debug - 7 + 7.2 Debug $(SolutionDir)/../../../../ $(GodotSourceRootPath)/bin/GodotSharp diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs index 139845a28d0..d6fa2eeba70 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs @@ -128,7 +128,7 @@ namespace GodotTools.Ides.MonoDevelop {EditorId.MonoDevelop, "MonoDevelop.exe"} }; } - else if (OS.IsUnixLike()) + else if (OS.IsUnixLike) { ExecutableNames = new Dictionary { diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs index a6427fa485a..e22e9af919d 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs @@ -36,7 +36,7 @@ namespace GodotTools.Ides.Rider { return CollectRiderInfosMac(); } - if (OS.IsUnixLike()) + if (OS.IsUnixLike) { return CollectAllRiderPathsLinux(); } @@ -147,7 +147,7 @@ namespace GodotTools.Ides.Rider return GetToolboxRiderRootPath(localAppData); } - if (OS.IsUnixLike()) + if (OS.IsUnixLike) { var home = Environment.GetEnvironmentVariable("HOME"); if (string.IsNullOrEmpty(home)) @@ -209,7 +209,7 @@ namespace GodotTools.Ides.Rider private static string GetRelativePathToBuildTxt() { - if (OS.IsWindows || OS.IsUnixLike()) + if (OS.IsWindows || OS.IsUnixLike) return "../../build.txt"; if (OS.IsOSX) return "Contents/Resources/build.txt"; diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs index b687f89641e..0008e7444d2 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs @@ -62,6 +62,11 @@ namespace GodotTools.Utils return name.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase); } + private static bool IsAnyOS(IEnumerable names) + { + return names.Any(p => p.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase)); + } + private static readonly Lazy _isWindows = new Lazy(() => IsOS(Names.Windows)); private static readonly Lazy _isOSX = new Lazy(() => IsOS(Names.OSX)); private static readonly Lazy _isX11 = new Lazy(() => IsOS(Names.X11)); @@ -71,6 +76,7 @@ namespace GodotTools.Utils private static readonly Lazy _isAndroid = new Lazy(() => IsOS(Names.Android)); private static readonly Lazy _isiOS = new Lazy(() => IsOS(Names.iOS)); private static readonly Lazy _isHTML5 = new Lazy(() => IsOS(Names.HTML5)); + private static readonly Lazy _isUnixLike = new Lazy(() => IsAnyOS(UnixLikePlatforms)); public static bool IsWindows => _isWindows.Value || IsUWP; public static bool IsOSX => _isOSX.Value; @@ -82,18 +88,9 @@ namespace GodotTools.Utils public static bool IsiOS => _isiOS.Value; public static bool IsHTML5 => _isHTML5.Value; - private static bool? _isUnixCache; - private static readonly string[] UnixLikePlatforms = { Names.OSX, Names.X11, Names.Server, Names.Haiku, Names.Android, Names.iOS }; + private static readonly string[] UnixLikePlatforms = {Names.OSX, Names.X11, Names.Server, Names.Haiku, Names.Android, Names.iOS}; - public static bool IsUnixLike() - { - if (_isUnixCache.HasValue) - return _isUnixCache.Value; - - string osName = GetPlatformName(); - _isUnixCache = UnixLikePlatforms.Any(p => p.Equals(osName, StringComparison.OrdinalIgnoreCase)); - return _isUnixCache.Value; - } + public static bool IsUnixLike => _isUnixLike.Value; public static char PathSep => IsWindows ? ';' : ':'; @@ -121,10 +118,10 @@ namespace GodotTools.Utils return searchDirs.Select(dir => Path.Combine(dir, name)).FirstOrDefault(File.Exists); return (from dir in searchDirs - select Path.Combine(dir, name) + select Path.Combine(dir, name) into path - from ext in windowsExts - select path + ext).FirstOrDefault(File.Exists); + from ext in windowsExts + select path + ext).FirstOrDefault(File.Exists); } private static string PathWhichUnix([NotNull] string name) @@ -189,7 +186,7 @@ namespace GodotTools.Utils startInfo.UseShellExecute = false; - using (var process = new Process { StartInfo = startInfo }) + using (var process = new Process {StartInfo = startInfo}) { process.Start(); process.WaitForExit();