diff --git a/sdk.sln b/sdk.sln index 52840d8fce54..f077fa6852a4 100644 --- a/sdk.sln +++ b/sdk.sln @@ -73,8 +73,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cli", "Cli", "{9CEF03F6-1A6 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Cli.Utils", "src\Cli\Microsoft.DotNet.Cli.Utils\Microsoft.DotNet.Cli.Utils.csproj", "{CC25E192-70AD-4D91-B288-3AD40065DBAC}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Cli.Sln.Internal", "src\Cli\Microsoft.DotNet.Cli.Sln.Internal\Microsoft.DotNet.Cli.Sln.Internal.csproj", "{2119E6E5-2B75-402A-AFF3-3E7E7B671B9B}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.InternalAbstractions", "src\Cli\Microsoft.DotNet.InternalAbstractions\Microsoft.DotNet.InternalAbstractions.csproj", "{0FA6CEE9-7A97-4036-8D48-39BA4F85118E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Configurer", "src\Cli\Microsoft.DotNet.Configurer\Microsoft.DotNet.Configurer.csproj", "{B22C90C9-BA46-4F07-9613-253DD01E3EFF}" @@ -109,8 +107,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArgumentForwarding.Tests", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EndToEnd.Tests", "test\EndToEnd.Tests\EndToEnd.Tests.csproj", "{A0EFB2CB-517F-4746-902E-D0EBEFFBD89B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Cli.Sln.Internal.Tests", "test\Microsoft.DotNet.Cli.Sln.Internal.Tests\Microsoft.DotNet.Cli.Sln.Internal.Tests.csproj", "{82D910C3-A5E2-41F0-A142-F4F2D770CB59}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Cli.Utils.Tests", "test\Microsoft.DotNet.Cli.Utils.Tests\Microsoft.DotNet.Cli.Utils.Tests.csproj", "{C34FB893-2320-41A3-9D38-0061C22A6464}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.MSBuildSdkResolver.Tests", "test\Microsoft.DotNet.MSBuildSdkResolver.Tests\Microsoft.DotNet.MSBuildSdkResolver.Tests.csproj", "{0AE2AB83-1F0D-4E04-9C8D-5C35CE97FDDC}" @@ -578,10 +574,6 @@ Global {CC25E192-70AD-4D91-B288-3AD40065DBAC}.Debug|Any CPU.Build.0 = Debug|Any CPU {CC25E192-70AD-4D91-B288-3AD40065DBAC}.Release|Any CPU.ActiveCfg = Release|Any CPU {CC25E192-70AD-4D91-B288-3AD40065DBAC}.Release|Any CPU.Build.0 = Release|Any CPU - {2119E6E5-2B75-402A-AFF3-3E7E7B671B9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2119E6E5-2B75-402A-AFF3-3E7E7B671B9B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2119E6E5-2B75-402A-AFF3-3E7E7B671B9B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2119E6E5-2B75-402A-AFF3-3E7E7B671B9B}.Release|Any CPU.Build.0 = Release|Any CPU {0FA6CEE9-7A97-4036-8D48-39BA4F85118E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0FA6CEE9-7A97-4036-8D48-39BA4F85118E}.Debug|Any CPU.Build.0 = Debug|Any CPU {0FA6CEE9-7A97-4036-8D48-39BA4F85118E}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -646,10 +638,6 @@ Global {A0EFB2CB-517F-4746-902E-D0EBEFFBD89B}.Debug|Any CPU.Build.0 = Debug|Any CPU {A0EFB2CB-517F-4746-902E-D0EBEFFBD89B}.Release|Any CPU.ActiveCfg = Release|Any CPU {A0EFB2CB-517F-4746-902E-D0EBEFFBD89B}.Release|Any CPU.Build.0 = Release|Any CPU - {82D910C3-A5E2-41F0-A142-F4F2D770CB59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {82D910C3-A5E2-41F0-A142-F4F2D770CB59}.Debug|Any CPU.Build.0 = Debug|Any CPU - {82D910C3-A5E2-41F0-A142-F4F2D770CB59}.Release|Any CPU.ActiveCfg = Release|Any CPU - {82D910C3-A5E2-41F0-A142-F4F2D770CB59}.Release|Any CPU.Build.0 = Release|Any CPU {C34FB893-2320-41A3-9D38-0061C22A6464}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C34FB893-2320-41A3-9D38-0061C22A6464}.Debug|Any CPU.Build.0 = Debug|Any CPU {C34FB893-2320-41A3-9D38-0061C22A6464}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -1005,7 +993,6 @@ Global {E740A596-2CAE-476C-8062-49705C3A9CF0} = {580D1AE7-AA8F-4912-8B76-105594E00B3B} {9CEF03F6-1A61-431A-8ABD-9095974629AE} = {22AB674F-ED91-4FBC-BFEE-8A1E82F9F05E} {CC25E192-70AD-4D91-B288-3AD40065DBAC} = {9CEF03F6-1A61-431A-8ABD-9095974629AE} - {2119E6E5-2B75-402A-AFF3-3E7E7B671B9B} = {9CEF03F6-1A61-431A-8ABD-9095974629AE} {0FA6CEE9-7A97-4036-8D48-39BA4F85118E} = {9CEF03F6-1A61-431A-8ABD-9095974629AE} {B22C90C9-BA46-4F07-9613-253DD01E3EFF} = {9CEF03F6-1A61-431A-8ABD-9095974629AE} {D62591F3-ED86-4014-B765-7CDA47F55EE2} = {9CEF03F6-1A61-431A-8ABD-9095974629AE} @@ -1023,7 +1010,6 @@ Global {587A6639-FA2A-498C-8FA2-F77925DB732B} = {580D1AE7-AA8F-4912-8B76-105594E00B3B} {2D8AA9EA-3013-47DE-B2DD-E074F67467ED} = {580D1AE7-AA8F-4912-8B76-105594E00B3B} {A0EFB2CB-517F-4746-902E-D0EBEFFBD89B} = {580D1AE7-AA8F-4912-8B76-105594E00B3B} - {82D910C3-A5E2-41F0-A142-F4F2D770CB59} = {580D1AE7-AA8F-4912-8B76-105594E00B3B} {C34FB893-2320-41A3-9D38-0061C22A6464} = {580D1AE7-AA8F-4912-8B76-105594E00B3B} {0AE2AB83-1F0D-4E04-9C8D-5C35CE97FDDC} = {580D1AE7-AA8F-4912-8B76-105594E00B3B} {3D20D19D-74FB-4A43-B78C-B0AF90A696A0} = {580D1AE7-AA8F-4912-8B76-105594E00B3B} diff --git a/source-build.slnf b/source-build.slnf index dd00078d19a6..5090803b2313 100644 --- a/source-build.slnf +++ b/source-build.slnf @@ -8,7 +8,6 @@ "src\\BuiltInTools\\DotNetDeltaApplier\\Microsoft.Extensions.DotNetDeltaApplier.csproj", "src\\BuiltInTools\\DotNetWatchTasks\\DotNetWatchTasks.csproj", "src\\BuiltInTools\\dotnet-watch\\dotnet-watch.csproj", - "src\\Cli\\Microsoft.DotNet.Cli.Sln.Internal\\Microsoft.DotNet.Cli.Sln.Internal.csproj", "src\\Cli\\Microsoft.DotNet.Cli.Utils\\Microsoft.DotNet.Cli.Utils.csproj", "src\\Cli\\Microsoft.DotNet.Configurer\\Microsoft.DotNet.Configurer.csproj", "src\\Cli\\Microsoft.DotNet.InternalAbstractions\\Microsoft.DotNet.InternalAbstractions.csproj", diff --git a/src/BuiltInTools/dotnet-format/Workspaces/MSBuildWorkspaceFinder.cs b/src/BuiltInTools/dotnet-format/Workspaces/MSBuildWorkspaceFinder.cs index f654dade542c..4bdc9001568a 100644 --- a/src/BuiltInTools/dotnet-format/Workspaces/MSBuildWorkspaceFinder.cs +++ b/src/BuiltInTools/dotnet-format/Workspaces/MSBuildWorkspaceFinder.cs @@ -76,8 +76,11 @@ private static (bool isSolution, string workspacePath) FindFile(string workspace return (isSolution, workspacePath); } - private static IEnumerable FindSolutionFiles(string basePath) => Directory.EnumerateFileSystemEntries(basePath, "*.sln", SearchOption.TopDirectoryOnly) - .Concat(Directory.EnumerateFileSystemEntries(basePath, "*.slnf", SearchOption.TopDirectoryOnly)); + private static IEnumerable FindSolutionFiles(string basePath) => [ + ..Directory.EnumerateFileSystemEntries(basePath, "*.sln", SearchOption.TopDirectoryOnly), + ..Directory.EnumerateFileSystemEntries(basePath, "*.slnf", SearchOption.TopDirectoryOnly), + ..Directory.EnumerateFileSystemEntries(basePath, "*.slnx", SearchOption.TopDirectoryOnly) + ]; private static IEnumerable FindProjectFiles(string basePath) => Directory.EnumerateFileSystemEntries(basePath, "*.*proj", SearchOption.TopDirectoryOnly) .Where(f => !DnxProjectExtension.Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase)); diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/FileManipulation/FileUtil.cs b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/FileManipulation/FileUtil.cs deleted file mode 100644 index 504eba093dcc..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/FileManipulation/FileUtil.cs +++ /dev/null @@ -1,152 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// FileUtil.cs -// -// Author: -// Lluis Sanchez Gual -// -// Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) -// -// 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. - -namespace Microsoft.DotNet.Cli.Sln.Internal.FileManipulation -{ - internal static class FileUtil - { - internal static TextFormatInfo GetTextFormatInfo(string file) - { - var info = new TextFormatInfo(); - - string newLine = null; - Encoding encoding; - - using (FileStream fs = File.OpenRead(file)) - { - byte[] buf = new byte[1024]; - int nread, i; - - if ((nread = fs.Read(buf, 0, buf.Length)) <= 0) - { - return info; - } - - if (TryParse(buf, nread, out encoding)) - { - i = encoding.GetPreamble().Length; - } - else - { - encoding = null; - i = 0; - } - - do - { - while (i < nread) - { - if (buf[i] == '\r') - { - newLine = "\r\n"; - break; - } - else if (buf[i] == '\n') - { - newLine = "\n"; - break; - } - - i++; - } - - if (newLine == null) - { - if ((nread = fs.Read(buf, 0, buf.Length)) <= 0) - { - newLine = "\n"; - break; - } - - i = 0; - } - } while (newLine == null); - - info.EndsWithEmptyLine = fs.Seek(-1, SeekOrigin.End) > 0 && fs.ReadByte() == (int)'\n'; - info.NewLine = newLine; - info.Encoding = encoding; - return info; - } - } - - private static bool TryParse(byte[] buffer, int available, out Encoding encoding) - { - if (buffer.Length >= 2) - { - for (int i = 0; i < table.Length; i++) - { - bool matched = true; - - if (available < table[i].GetPreamble().Length) - { - continue; - } - - for (int j = 0; j < table[i].GetPreamble().Length; j++) - { - if (buffer[j] != table[i].GetPreamble()[j]) - { - matched = false; - break; - } - } - - if (matched) - { - encoding = table[i]; - return true; - } - } - } - - encoding = null; - - return false; - } - - private static readonly Encoding[] table = new[] { - Encoding.UTF8, - Encoding.UTF32, - Encoding.ASCII, - }; - } - - internal class TextFormatInfo - { - public TextFormatInfo() - { - NewLine = Environment.NewLine; - Encoding = null; - EndsWithEmptyLine = true; - } - - public string NewLine { get; set; } - public Encoding Encoding { get; set; } - public bool EndsWithEmptyLine { get; set; } - } -} diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/LocalizableStrings.resx b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/LocalizableStrings.resx deleted file mode 100644 index 524b72423138..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/LocalizableStrings.resx +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Invalid format in line {0}: {1} - - - Project section is missing '{0}' when parsing the line starting at position {1} - - - Property set is missing '{0}' - - - Global section specified more than once - - - Global section not closed - - - File header is missing version - - - Expected file header not found - - - Project section not closed - - - Invalid section type: {0} - - - Section id missing - - - Closing section tag not found - - diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/Microsoft.DotNet.Cli.Sln.Internal.csproj b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/Microsoft.DotNet.Cli.Sln.Internal.csproj deleted file mode 100644 index 1618b780490d..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/Microsoft.DotNet.Cli.Sln.Internal.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - SLN file reader/writer - $(SdkTargetFramework) - portable - Microsoft.DotNet.Cli.Sln.Internal - MicrosoftAspNetCore - true - true - true - - - - - - - - - - diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/ProjectTypeGuids.cs b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/ProjectTypeGuids.cs deleted file mode 100644 index 5db6beb30ed7..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/ProjectTypeGuids.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace Microsoft.DotNet.Cli.Sln.Internal -{ - public static class ProjectTypeGuids - { - public const string CSharpProjectTypeGuid = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"; - public const string FSharpProjectTypeGuid = "{F2A71F9B-5D33-465A-A702-920D77279786}"; - public const string VBProjectTypeGuid = "{F184B08F-C81C-45F6-A57F-5ABD9991F28F}"; - public const string SolutionFolderGuid = "{2150E333-8FDC-42A3-9474-1A3956D46DE8}"; - public const string SharedProjectGuid = "{D954291E-2A0B-460D-934E-DC6B0785DB48}"; - } -} diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/Properties/AssemblyInfo.cs b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/Properties/AssemblyInfo.cs deleted file mode 100644 index 98cdd1d19b73..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Microsoft.DotNet.Cli.Sln.Internal.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -[assembly: InternalsVisibleTo("dotnet-sln.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] - - diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/SlnFile.cs b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/SlnFile.cs deleted file mode 100644 index e7e758d6f00e..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/SlnFile.cs +++ /dev/null @@ -1,1199 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// -// SlnFile.cs -// -// Author: -// Lluis Sanchez Gual -// -// Copyright (c) 2016 Xamarin, Inc (http://www.xamarin.com) -// -// 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. - -using System.Collections; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.Globalization; -using System.Reflection; -using Microsoft.DotNet.Cli.Sln.Internal.FileManipulation; -using Microsoft.DotNet.Tools.Common; - -namespace Microsoft.DotNet.Cli.Sln.Internal -{ - public class SlnFile - { - private SlnProjectCollection _projects = new(); - private SlnSectionCollection _sections = new(); - private SlnPropertySet _metadata = new(true); - private int _prefixBlankLines = 1; - private TextFormatInfo _format = new(); - - public string FormatVersion { get; set; } - public string ProductDescription { get; set; } - - public string VisualStudioVersion - { - get { return _metadata.GetValue("VisualStudioVersion"); } - set { _metadata.SetValue("VisualStudioVersion", value); } - } - - public string MinimumVisualStudioVersion - { - get { return _metadata.GetValue("MinimumVisualStudioVersion"); } - set { _metadata.SetValue("MinimumVisualStudioVersion", value); } - } - - public string BaseDirectory - { - get { return Path.GetDirectoryName(FullPath); } - } - - public string FullPath { get; set; } - - public SlnPropertySet SolutionConfigurationsSection - { - get - { - return _sections - .GetOrCreateSection("SolutionConfigurationPlatforms", SlnSectionType.PreProcess) - .Properties; - } - } - - public SlnPropertySetCollection ProjectConfigurationsSection - { - get - { - return _sections - .GetOrCreateSection("ProjectConfigurationPlatforms", SlnSectionType.PostProcess) - .NestedPropertySets; - } - } - - public SlnSectionCollection Sections - { - get { return _sections; } - } - - public SlnProjectCollection Projects - { - get { return _projects; } - } - - public SlnFile() - { - _projects.ParentFile = this; - _sections.ParentFile = this; - } - - public static SlnFile Read(string file) - { - SlnFile slnFile = new() - { - FullPath = Path.GetFullPath(file), - _format = FileUtil.GetTextFormatInfo(file) - }; - - using (var sr = new StreamReader(new FileStream(file, FileMode.Open, FileAccess.Read))) - { - slnFile.Read(sr); - } - - return slnFile; - } - - private void Read(TextReader reader) - { - const string HeaderPrefix = "Microsoft Visual Studio Solution File, Format Version"; - - string line; - int curLineNum = 0; - bool globalFound = false; - bool productRead = false; - - while ((line = reader.ReadLine()) != null) - { - curLineNum++; - line = line.Trim(); - if (line.StartsWith(HeaderPrefix, StringComparison.Ordinal)) - { - if (line.Length <= HeaderPrefix.Length) - { - throw new InvalidSolutionFormatException( - curLineNum, - LocalizableStrings.FileHeaderMissingVersionError); - } - - FormatVersion = line.Substring(HeaderPrefix.Length).Trim(); - _prefixBlankLines = curLineNum - 1; - } - if (line.StartsWith("# ", StringComparison.Ordinal)) - { - if (!productRead) - { - productRead = true; - ProductDescription = line.Substring(2); - } - } - else if (line.StartsWith("Project", StringComparison.Ordinal)) - { - SlnProject p = new(); - p.Read(reader, line, ref curLineNum); - _projects.Add(p); - } - else if (line == "Global") - { - if (globalFound) - { - throw new InvalidSolutionFormatException( - curLineNum, - LocalizableStrings.GlobalSectionMoreThanOnceError); - } - globalFound = true; - while ((line = reader.ReadLine()) != null) - { - curLineNum++; - line = line.Trim(); - if (line == "EndGlobal") - { - break; - } - else if (line.StartsWith("GlobalSection", StringComparison.Ordinal)) - { - var sec = new SlnSection(); - sec.Read(reader, line, ref curLineNum); - _sections.Add(sec); - } - else // Ignore text that's out of place - { - continue; - } - } - if (line == null) - { - throw new InvalidSolutionFormatException( - curLineNum, - LocalizableStrings.GlobalSectionNotClosedError); - } - } - else if (line.IndexOf('=') != -1) - { - _metadata.ReadLine(line, curLineNum); - } - } - if (FormatVersion == null) - { - throw new InvalidSolutionFormatException(LocalizableStrings.FileHeaderMissingError); - } - } - - public void Write(string file = null) - { - if (!string.IsNullOrEmpty(file)) - { - FullPath = Path.GetFullPath(file); - } - var sw = new StringWriter(); - Write(sw); - File.WriteAllText(FullPath, sw.ToString(), Encoding.UTF8); - } - - private void Write(TextWriter writer) - { - writer.NewLine = _format.NewLine; - for (int n = 0; n < _prefixBlankLines; n++) - { - writer.WriteLine(); - } - writer.WriteLine("Microsoft Visual Studio Solution File, Format Version " + FormatVersion); - writer.WriteLine("# " + ProductDescription); - - _metadata.Write(writer); - - foreach (var p in _projects) - { - p.Write(writer); - } - - writer.WriteLine("Global"); - foreach (SlnSection s in _sections) - { - s.Write(writer, "GlobalSection"); - } - writer.WriteLine("EndGlobal"); - } - } - - public class SlnProject - { - private SlnSectionCollection _sections = new(); - - private SlnFile _parentFile; - - public SlnFile ParentFile - { - get - { - return _parentFile; - } - internal set - { - _parentFile = value; - _sections.ParentFile = _parentFile; - } - } - - public string Id { get; set; } - public string TypeGuid { get; set; } - public string Name { get; set; } - - private string _filePath; - public string FilePath - { - get - { - return _filePath; - } - set - { - _filePath = PathUtility.RemoveExtraPathSeparators( - PathUtility.GetPathWithDirectorySeparator(value)); - } - } - - public int Line { get; private set; } - internal bool Processed { get; set; } - - public SlnSectionCollection Sections - { - get { return _sections; } - } - - public SlnSection Dependencies - { - get - { - return _sections.GetSection("ProjectDependencies", SlnSectionType.PostProcess); - } - } - - internal void Read(TextReader reader, string line, ref int curLineNum) - { - Line = curLineNum; - - int n = 0; - FindNext(curLineNum, line, ref n, '('); - n++; - FindNext(curLineNum, line, ref n, '"'); - int n2 = n + 1; - FindNext(curLineNum, line, ref n2, '"'); - TypeGuid = line.Substring(n + 1, n2 - n - 1); - - n = n2 + 1; - FindNext(curLineNum, line, ref n, ')'); - FindNext(curLineNum, line, ref n, '='); - - FindNext(curLineNum, line, ref n, '"'); - n2 = n + 1; - FindNext(curLineNum, line, ref n2, '"'); - Name = line.Substring(n + 1, n2 - n - 1); - - n = n2 + 1; - FindNext(curLineNum, line, ref n, ','); - FindNext(curLineNum, line, ref n, '"'); - n2 = n + 1; - FindNext(curLineNum, line, ref n2, '"'); - FilePath = line.Substring(n + 1, n2 - n - 1); - - n = n2 + 1; - FindNext(curLineNum, line, ref n, ','); - FindNext(curLineNum, line, ref n, '"'); - n2 = n + 1; - FindNext(curLineNum, line, ref n2, '"'); - Id = line.Substring(n + 1, n2 - n - 1); - - while ((line = reader.ReadLine()) != null) - { - curLineNum++; - line = line.Trim(); - if (line == "EndProject") - { - return; - } - if (line.StartsWith("ProjectSection", StringComparison.Ordinal)) - { - if (_sections == null) - { - _sections = new SlnSectionCollection(); - } - var sec = new SlnSection(); - _sections.Add(sec); - sec.Read(reader, line, ref curLineNum); - } - } - - throw new InvalidSolutionFormatException( - curLineNum, - LocalizableStrings.ProjectSectionNotClosedError); - } - - private void FindNext(int ln, string line, ref int i, char c) - { - var inputIndex = i; - i = line.IndexOf(c, i); - if (i == -1) - { - throw new InvalidSolutionFormatException( - ln, - string.Format(LocalizableStrings.ProjectParsingErrorFormatString, c, inputIndex)); - } - } - - internal void Write(TextWriter writer) - { - writer.Write("Project(\""); - writer.Write(TypeGuid); - writer.Write("\") = \""); - writer.Write(Name); - writer.Write("\", \""); - writer.Write(PathUtility.GetPathWithBackSlashes(FilePath)); - writer.Write("\", \""); - writer.Write(Id); - writer.WriteLine("\""); - if (_sections != null) - { - foreach (SlnSection s in _sections) - { - s.Write(writer, "ProjectSection"); - } - } - writer.WriteLine("EndProject"); - } - } - - public class SlnSection - { - private SlnPropertySetCollection _nestedPropertySets; - private SlnPropertySet _properties; - private List _sectionLines; - private int _baseIndex; - - public string Id { get; set; } - public int Line { get; private set; } - - internal bool Processed { get; set; } - - public SlnFile ParentFile { get; internal set; } - - public bool IsEmpty - { - get - { - return (_properties == null || _properties.Count == 0) && - (_nestedPropertySets == null || _nestedPropertySets.All(t => t.IsEmpty)) && - (_sectionLines == null || _sectionLines.Count == 0); - } - } - - /// - /// If true, this section won't be written to the file if it is empty - /// - /// true if skip if empty; otherwise, false. - public bool SkipIfEmpty { get; set; } - - public void Clear() - { - _properties = null; - _nestedPropertySets = null; - _sectionLines = null; - } - - public SlnPropertySet Properties - { - get - { - if (_properties == null) - { - _properties = new SlnPropertySet - { - ParentSection = this - }; - if (_sectionLines != null) - { - foreach (var line in _sectionLines) - { - _properties.ReadLine(line, Line); - } - _sectionLines = null; - } - } - return _properties; - } - } - - public SlnPropertySetCollection NestedPropertySets - { - get - { - if (_nestedPropertySets == null) - { - _nestedPropertySets = new SlnPropertySetCollection(this); - if (_sectionLines != null) - { - LoadPropertySets(); - } - } - return _nestedPropertySets; - } - } - - public void SetContent(IEnumerable> lines) - { - _sectionLines = new List(lines.Select(p => p.Key + " = " + p.Value)); - _properties = null; - _nestedPropertySets = null; - } - - public IEnumerable> GetContent() - { - if (_sectionLines != null) - { - return _sectionLines.Select(li => - { - int i = li.IndexOf('='); - if (i != -1) - { - return new KeyValuePair(li.Substring(0, i).Trim(), li.Substring(i + 1).Trim()); - } - else - { - return new KeyValuePair(li.Trim(), ""); - } - }); - } - else - { - return new KeyValuePair[0]; - } - } - - public SlnSectionType SectionType { get; set; } - - private SlnSectionType ToSectionType(int curLineNum, string s) - { - if (s == "preSolution" || s == "preProject") - { - return SlnSectionType.PreProcess; - } - if (s == "postSolution" || s == "postProject") - { - return SlnSectionType.PostProcess; - } - throw new InvalidSolutionFormatException( - curLineNum, - string.Format(LocalizableStrings.InvalidSectionTypeError, s)); - } - - private string FromSectionType(bool isProjectSection, SlnSectionType type) - { - if (type == SlnSectionType.PreProcess) - { - return isProjectSection ? "preProject" : "preSolution"; - } - else - { - return isProjectSection ? "postProject" : "postSolution"; - } - } - - internal void Read(TextReader reader, string line, ref int curLineNum) - { - Line = curLineNum; - int k = line.IndexOf('('); - if (k == -1) - { - throw new InvalidSolutionFormatException( - curLineNum, - LocalizableStrings.SectionIdMissingError); - } - var tag = line.Substring(0, k).Trim(); - var k2 = line.IndexOf(')', k); - if (k2 == -1) - { - throw new InvalidSolutionFormatException( - curLineNum, - LocalizableStrings.SectionIdMissingError); - } - Id = line.Substring(k + 1, k2 - k - 1); - - k = line.IndexOf('=', k2); - SectionType = ToSectionType(curLineNum, line.Substring(k + 1).Trim()); - - var endTag = "End" + tag; - - _sectionLines = new List(); - _baseIndex = ++curLineNum; - while ((line = reader.ReadLine()) != null) - { - curLineNum++; - line = line.Trim(); - if (line == endTag) - { - break; - } - _sectionLines.Add(line); - } - if (line == null) - { - throw new InvalidSolutionFormatException( - curLineNum, - LocalizableStrings.ClosingSectionTagNotFoundError); - } - } - - private void LoadPropertySets() - { - if (_sectionLines != null) - { - SlnPropertySet curSet = null; - for (int n = 0; n < _sectionLines.Count; n++) - { - var line = _sectionLines[n]; - if (string.IsNullOrEmpty(line.Trim())) - { - continue; - } - var i = line.IndexOf('.'); - if (i == -1) - { - throw new InvalidSolutionFormatException( - _baseIndex + n, - string.Format(LocalizableStrings.InvalidPropertySetFormatString, '.')); - } - var id = line.Substring(0, i); - if (curSet == null || id != curSet.Id) - { - curSet = new SlnPropertySet(id); - _nestedPropertySets.Add(curSet); - } - curSet.ReadLine(line.Substring(i + 1), _baseIndex + n); - } - _sectionLines = null; - } - } - - internal void Write(TextWriter writer, string sectionTag) - { - if (SkipIfEmpty && IsEmpty) - { - return; - } - - writer.Write("\t"); - writer.Write(sectionTag); - writer.Write('('); - writer.Write(Id); - writer.Write(") = "); - writer.WriteLine(FromSectionType(sectionTag == "ProjectSection", SectionType)); - if (_sectionLines != null) - { - foreach (var l in _sectionLines) - { - writer.WriteLine("\t\t" + l); - } - } - else if (_properties != null) - { - _properties.Write(writer); - } - else if (_nestedPropertySets != null) - { - foreach (var ps in _nestedPropertySets) - { - ps.Write(writer); - } - } - writer.WriteLine("\tEnd" + sectionTag); - } - } - - /// - /// A collection of properties - /// - public class SlnPropertySet : IDictionary - { - private OrderedDictionary _values = new(); - private bool _isMetadata; - - internal bool Processed { get; set; } - - public SlnFile ParentFile - { - get { return ParentSection != null ? ParentSection.ParentFile : null; } - } - - public SlnSection ParentSection { get; set; } - - /// - /// Text file line of this section in the original file - /// - /// The line. - public int Line { get; private set; } - - internal SlnPropertySet() - { - } - - /// - /// Creates a new property set with the specified ID - /// - /// Identifier. - public SlnPropertySet(string id) - { - Id = id; - } - - internal SlnPropertySet(bool isMetadata) - { - _isMetadata = isMetadata; - } - - public bool IsEmpty - { - get - { - return _values.Count == 0; - } - } - - internal void ReadLine(string line, int currentLine) - { - if (Line == 0) - { - Line = currentLine; - } - int k = line.IndexOf('='); - if (k != -1) - { - var name = line.Substring(0, k).Trim(); - var val = line.Substring(k + 1).Trim(); - _values[name] = val; - } - else - { - line = line.Trim(); - if (!string.IsNullOrWhiteSpace(line)) - { - _values.Add(line, null); - } - } - } - - internal void Write(TextWriter writer) - { - foreach (DictionaryEntry e in _values) - { - if (!_isMetadata) - { - writer.Write("\t\t"); - } - if (Id != null) - { - writer.Write(Id + "."); - } - writer.WriteLine(e.Key + " = " + e.Value); - } - } - - public string Id { get; private set; } - - public string GetValue(string name, string defaultValue = null) - { - string res; - if (TryGetValue(name, out res)) - { - return res; - } - else - { - return defaultValue; - } - } - - public T GetValue(string name) - { - return (T)GetValue(name, typeof(T), default(T)); - } - - public T GetValue(string name, T defaultValue) - { - return (T)GetValue(name, typeof(T), defaultValue); - } - - public object GetValue(string name, Type t, object defaultValue) - { - string val; - if (TryGetValue(name, out val)) - { - if (t == typeof(bool)) - { - return (object)val.Equals("true", StringComparison.OrdinalIgnoreCase); - } - if (t.GetTypeInfo().IsEnum) - { - return Enum.Parse(t, val, true); - } - if (t.GetTypeInfo().IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) - { - var at = t.GetTypeInfo().GetGenericArguments()[0]; - if (string.IsNullOrEmpty(val)) - { - return null; - } - return Convert.ChangeType(val, at, CultureInfo.InvariantCulture); - - } - return Convert.ChangeType(val, t, CultureInfo.InvariantCulture); - } - else - { - return defaultValue; - } - } - - public void SetValue(string name, string value, string defaultValue = null, bool preserveExistingCase = false) - { - if (value == null && defaultValue == "") - { - value = ""; - } - if (value == defaultValue) - { - // if the value is default, only remove the property if it was not already the default - // to avoid unnecessary project file churn - string res; - if (TryGetValue(name, out res) && - !string.Equals(defaultValue ?? "", - res, preserveExistingCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)) - { - Remove(name); - } - return; - } - string currentValue; - if (preserveExistingCase && TryGetValue(name, out currentValue) && - string.Equals(value, currentValue, StringComparison.OrdinalIgnoreCase)) - { - return; - } - _values[name] = value; - } - - public void SetValue(string name, object value, object defaultValue = null) - { - var isDefault = Equals(value, defaultValue); - if (isDefault) - { - // if the value is default, only remove the property if it was not already the default - // to avoid unnecessary project file churn - if (ContainsKey(name) && (defaultValue == null || - !Equals(defaultValue, GetValue(name, defaultValue.GetType(), null)))) - { - Remove(name); - } - return; - } - - if (value is bool) - { - _values[name] = (bool)value ? "TRUE" : "FALSE"; - } - else - { - _values[name] = Convert.ToString(value, CultureInfo.InvariantCulture); - } - } - - void IDictionary.Add(string key, string value) - { - SetValue(key, value); - } - - public bool ContainsKey(string key) - { - return _values.Contains(key); - } - - public bool Remove(string key) - { - var wasThere = _values.Contains(key); - _values.Remove(key); - return wasThere; - } - - public bool TryGetValue(string key, out string value) - { - value = (string)_values[key]; - return value != null; - } - - public string this[string index] - { - get - { - return (string)_values[index]; - } - set - { - _values[index] = value; - } - } - - public ICollection Values - { - get - { - return _values.Values.Cast().ToList(); - } - } - - public ICollection Keys - { - get { return _values.Keys.Cast().ToList(); } - } - - void ICollection>.Add(KeyValuePair item) - { - SetValue(item.Key, item.Value); - } - - public void Clear() - { - _values.Clear(); - } - - internal void ClearExcept(HashSet keys) - { - foreach (var k in _values.Keys.Cast().Except(keys).ToArray()) - { - _values.Remove(k); - } - } - - bool ICollection>.Contains(KeyValuePair item) - { - var val = GetValue(item.Key); - return val == item.Value; - } - - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - foreach (DictionaryEntry de in _values) - { - array[arrayIndex++] = new KeyValuePair((string)de.Key, (string)de.Value); - } - } - - bool ICollection>.Remove(KeyValuePair item) - { - if (((ICollection>)this).Contains(item)) - { - Remove(item.Key); - return true; - } - else - { - return false; - } - } - - public int Count - { - get - { - return _values.Count; - } - } - - internal void SetLines(IEnumerable> lines) - { - _values.Clear(); - foreach (var line in lines) - { - _values[line.Key] = line.Value; - } - } - - bool ICollection>.IsReadOnly - { - get - { - return false; - } - } - - public IEnumerator> GetEnumerator() - { - foreach (DictionaryEntry de in _values) - { - yield return new KeyValuePair((string)de.Key, (string)de.Value); - } - } - - IEnumerator IEnumerable.GetEnumerator() - { - foreach (DictionaryEntry de in _values) - { - yield return new KeyValuePair((string)de.Key, (string)de.Value); - } - } - } - - public class SlnProjectCollection : Collection - { - private SlnFile _parentFile; - - internal SlnFile ParentFile - { - get - { - return _parentFile; - } - set - { - _parentFile = value; - foreach (var it in this) - { - it.ParentFile = _parentFile; - } - } - } - - public SlnProject GetProject(string id) - { - return this.FirstOrDefault(s => s.Id == id); - } - - public SlnProject GetOrCreateProject(string id) - { - var p = this.FirstOrDefault(s => s.Id.Equals(id, StringComparison.OrdinalIgnoreCase)); - if (p == null) - { - p = new SlnProject { Id = id }; - Add(p); - } - return p; - } - - protected override void InsertItem(int index, SlnProject item) - { - base.InsertItem(index, item); - item.ParentFile = ParentFile; - } - - protected override void SetItem(int index, SlnProject item) - { - base.SetItem(index, item); - item.ParentFile = ParentFile; - } - - protected override void RemoveItem(int index) - { - var it = this[index]; - it.ParentFile = null; - base.RemoveItem(index); - } - - protected override void ClearItems() - { - foreach (var it in this) - { - it.ParentFile = null; - } - base.ClearItems(); - } - } - - public class SlnSectionCollection : Collection - { - private SlnFile _parentFile; - - internal SlnFile ParentFile - { - get - { - return _parentFile; - } - set - { - _parentFile = value; - foreach (var it in this) - { - it.ParentFile = _parentFile; - } - } - } - - public SlnSection GetSection(string id) - { - return this.FirstOrDefault(s => s.Id == id); - } - - public SlnSection GetSection(string id, SlnSectionType sectionType) - { - return this.FirstOrDefault(s => s.Id == id && s.SectionType == sectionType); - } - - public SlnSection GetOrCreateSection(string id, SlnSectionType sectionType) - { - if (id == null) - { - throw new ArgumentNullException("id"); - } - var sec = this.FirstOrDefault(s => s.Id == id); - if (sec == null) - { - sec = new SlnSection - { - Id = id, - SectionType = sectionType - }; - Add(sec); - } - return sec; - } - - public void RemoveSection(string id) - { - if (id == null) - { - throw new ArgumentNullException("id"); - } - var s = GetSection(id); - if (s != null) - { - Remove(s); - } - } - - protected override void InsertItem(int index, SlnSection item) - { - base.InsertItem(index, item); - item.ParentFile = ParentFile; - } - - protected override void SetItem(int index, SlnSection item) - { - base.SetItem(index, item); - item.ParentFile = ParentFile; - } - - protected override void RemoveItem(int index) - { - var it = this[index]; - it.ParentFile = null; - base.RemoveItem(index); - } - - protected override void ClearItems() - { - foreach (var it in this) - { - it.ParentFile = null; - } - base.ClearItems(); - } - } - - public class SlnPropertySetCollection : Collection - { - private SlnSection _parentSection; - - internal SlnPropertySetCollection(SlnSection parentSection) - { - _parentSection = parentSection; - } - - public SlnPropertySet GetPropertySet(string id, bool ignoreCase = false) - { - var sc = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - return this.FirstOrDefault(s => s.Id.Equals(id, sc)); - } - - public SlnPropertySet GetOrCreatePropertySet(string id, bool ignoreCase = false) - { - var ps = GetPropertySet(id, ignoreCase); - if (ps == null) - { - ps = new SlnPropertySet(id); - Add(ps); - } - return ps; - } - - protected override void InsertItem(int index, SlnPropertySet item) - { - base.InsertItem(index, item); - item.ParentSection = _parentSection; - } - - protected override void SetItem(int index, SlnPropertySet item) - { - base.SetItem(index, item); - item.ParentSection = _parentSection; - } - - protected override void RemoveItem(int index) - { - var it = this[index]; - it.ParentSection = null; - base.RemoveItem(index); - } - - protected override void ClearItems() - { - foreach (var it in this) - { - it.ParentSection = null; - } - base.ClearItems(); - } - } - - public class InvalidSolutionFormatException : Exception - { - public InvalidSolutionFormatException(string details) - : base(details) - { - } - - public InvalidSolutionFormatException(int line, string details) - : base(string.Format(LocalizableStrings.ErrorMessageFormatString, line, details)) - { - } - } - - public enum SlnSectionType - { - PreProcess, - PostProcess - } -} - diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.cs.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.cs.xlf deleted file mode 100644 index 5d973eb64247..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.cs.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - Několikrát zadaný globální oddíl - - - - Global section not closed - Neuzavřený globální oddíl - - - - Expected file header not found - Nenalezena očekávaná hlavička souboru - - - - Project section not closed - Neuzavřený oddíl projektu - - - - Invalid section type: {0} - Neplatný typ oddílu: {0} - - - - Section id missing - Chybí ID oddílu - - - - Closing section tag not found - Nenalezena koncová značka oddílu - - - - Invalid format in line {0}: {1} - Neplatný formát na řádku {0}: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - V oddíle projektu chybí {0}, když analýza řádku začíná na pozici {1}. - - - - Property set is missing '{0}' - V sadě vlastností chybí {0}. - - - - File header is missing version - Chybějící verze v hlavičce souboru - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.de.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.de.xlf deleted file mode 100644 index 5e6f488308ac..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.de.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - Globaler Abschnitt mehrmals angegeben - - - - Global section not closed - Globaler Abschnitt nicht geschlossen - - - - Expected file header not found - Erwarteter Dateiheader nicht gefunden. - - - - Project section not closed - Projektabschnitt nicht geschlossen - - - - Invalid section type: {0} - Ungültiger Abschnittstyp: {0} - - - - Section id missing - Abschnitts-ID fehlt - - - - Closing section tag not found - Schließendes Abschnittstag nicht gefunden - - - - Invalid format in line {0}: {1} - Ungültiges Format in Zeile {0}: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - Im Projektabschnitt fehlt "{0}" beim Analysieren des Zeilenbeginns in Position {1} - - - - Property set is missing '{0}' - Im Eigenschaftensatz fehlt "{0}" - - - - File header is missing version - Der Dateiheader enthält keine Version. - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.es.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.es.xlf deleted file mode 100644 index 365664c207aa..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.es.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - Sección global especificada más de una vez - - - - Global section not closed - Sección global no cerrada - - - - Expected file header not found - No se encontró el encabezado de archivo esperado - - - - Project section not closed - Sección de proyecto no cerrada - - - - Invalid section type: {0} - Tipo de sección no válido: {0} - - - - Section id missing - Id. de sección omitido - - - - Closing section tag not found - No se encuentra la etiqueta de cierre de la sección - - - - Invalid format in line {0}: {1} - Formato no válido en línea {0}: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - Falta la sección del proyecto "{0}" al analizar la línea que inicia en la posición {1} - - - - Property set is missing '{0}' - A la propiedad establecida le falta "{0}" - - - - File header is missing version - Falta la versión del encabezado de archivo - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.fr.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.fr.xlf deleted file mode 100644 index dd00afbe039e..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.fr.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - Section Global spécifiée plusieurs fois - - - - Global section not closed - Section Global non fermée - - - - Expected file header not found - En-tête de fichier attendu introuvable - - - - Project section not closed - Section Project non fermée - - - - Invalid section type: {0} - Type de section non valide : {0} - - - - Section id missing - ID de section manquant - - - - Closing section tag not found - Balise de fermeture de section introuvable - - - - Invalid format in line {0}: {1} - Format non valide dans la ligne {0} : {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - '{0}' est manquant dans la section de projet lors de l'analyse de la ligne à partir de la position {1} - - - - Property set is missing '{0}' - '{0}' est manquant dans le jeu de propriétés - - - - File header is missing version - Version manquante pour l'en-tête de fichier - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.it.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.it.xlf deleted file mode 100644 index a19ec0313e93..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.it.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - La sezione Global è stata specificata più di una volta - - - - Global section not closed - La sezione Global non è stata chiusa - - - - Expected file header not found - L'intestazione del file prevista non è stata trovata - - - - Project section not closed - La sezione Project non è stata chiusa - - - - Invalid section type: {0} - Tipo di sezione non valido: {0} - - - - Section id missing - Manca l'ID sezione - - - - Closing section tag not found - Il tag di chiusura sessione non è stato trovato - - - - Invalid format in line {0}: {1} - Formato non valido alla riga {0}: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - Nella sezione del progetto manca '{0}' quando si analizza la riga a partire dalla posizione {1} - - - - Property set is missing '{0}' - Nel set di proprietà manca '{0}' - - - - File header is missing version - Nell'intestazione del file manca la versione - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ja.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ja.xlf deleted file mode 100644 index 0f7670d89f28..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ja.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - グローバル セクションが 2 回以上指定されています - - - - Global section not closed - グローバル セクションが閉じられていません - - - - Expected file header not found - 予期されたファイル ヘッダーがありません - - - - Project section not closed - プロジェクト セクションが閉じられていません - - - - Invalid section type: {0} - 無効なセクションの種類: {0} - - - - Section id missing - セクション ID がありません - - - - Closing section tag not found - 終了セクション タグが見つかりません - - - - Invalid format in line {0}: {1} - 行 {0} の形式が無効です: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - 位置 {1} から始まる行の解析中にプロジェクト セクションが見つかりません '{0}' - - - - Property set is missing '{0}' - プロパティ セットが見つかりません '{0}' - - - - File header is missing version - ファイル ヘッダーにバージョンが見つかりません - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ko.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ko.xlf deleted file mode 100644 index 7d8766ad5dda..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ko.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - 전역 섹션이 두 번 이상 지정됨 - - - - Global section not closed - 전역 섹션이 닫히지 않음 - - - - Expected file header not found - 필요한 파일 헤더가 없음 - - - - Project section not closed - 프로젝트 섹션이 닫히지 않음 - - - - Invalid section type: {0} - 잘못된 섹션 유형: {0} - - - - Section id missing - 섹션 ID가 누락됨 - - - - Closing section tag not found - 닫기 섹션 태그를 찾을 수 없음 - - - - Invalid format in line {0}: {1} - {0} 줄에 잘못된 형식: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - {1} 위치에서 시작하는 줄을 구문 분석할 때 프로젝트 섹션에 '{0}'이(가) 없습니다. - - - - Property set is missing '{0}' - 속성 설정에 '{0}'이(가) 없습니다. - - - - File header is missing version - 파일 헤더에 버전이 없습니다. - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.pl.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.pl.xlf deleted file mode 100644 index 957ee2041b72..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.pl.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - Sekcja globalna została określona więcej niż raz - - - - Global section not closed - Nie zamknięto sekcji globalnej - - - - Expected file header not found - Nie znaleziono oczekiwanego nagłówka pliku - - - - Project section not closed - Nie zamknięto sekcji projektu - - - - Invalid section type: {0} - Nieprawidłowy typ sekcji: {0} - - - - Section id missing - Brak identyfikatora sekcji - - - - Closing section tag not found - Nie odnaleziono tagu zamykającego sekcję - - - - Invalid format in line {0}: {1} - Nieprawidłowy format w wierszu {0}: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - W sekcji projektu brakuje elementu „{0}” podczas analizowania wiersza, począwszy od pozycji {1} - - - - Property set is missing '{0}' - W zestawie właściwości brakuje elementu „{0}” - - - - File header is missing version - Brak wersji nagłówka pliku - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.pt-BR.xlf deleted file mode 100644 index 877faf844fb7..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.pt-BR.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - Seção global especificada mais de uma vez - - - - Global section not closed - Seção global não fechada - - - - Expected file header not found - Cabeçalho do arquivo esperado não encontrado - - - - Project section not closed - Seção de projeto não fechada - - - - Invalid section type: {0} - Tipo de seção inválido: {0} - - - - Section id missing - ID de sessão ausente - - - - Closing section tag not found - Marca de fechamento de seção não encontrada - - - - Invalid format in line {0}: {1} - Formato inválido na linha {0}: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - A seção do projeto está sem o '{0}' ao analisar a linha na posição {1} - - - - Property set is missing '{0}' - O conjunto de propriedade está sem '{0}' - - - - File header is missing version - O cabeçalho do arquivo está sem a versão - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ru.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ru.xlf deleted file mode 100644 index 7caa01a43eef..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.ru.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - Глобальный раздел указан более одного раза. - - - - Global section not closed - Глобальный раздел не закрыт. - - - - Expected file header not found - Отсутствует требуемый заголовок файла - - - - Project section not closed - Раздел проекта не закрыт. - - - - Invalid section type: {0} - Недопустимый тип раздела: {0} - - - - Section id missing - Отсутствует идентификатор раздела. - - - - Closing section tag not found - Закрывающий тег раздела не найден. - - - - Invalid format in line {0}: {1} - Формат в строке {0} недопустим: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - В разделе проекта отсутствует "{0}" при анализе строки с начальной позицией {1} - - - - Property set is missing '{0}' - В наборе свойств отсутствует "{0}" - - - - File header is missing version - В заголовке файла отсутствует версия - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.tr.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.tr.xlf deleted file mode 100644 index a7c5cba6b88b..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.tr.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - Genel bölüm birden çok kez belirtilmiş - - - - Global section not closed - Genel bölüm kapatılmadı - - - - Expected file header not found - Beklenen dosya üst bilgisi bulunamadı - - - - Project section not closed - Proje bölümü kapatılmadı - - - - Invalid section type: {0} - Geçersiz bölüm türü: {0} - - - - Section id missing - Bölüm kimliği eksik - - - - Closing section tag not found - Kapatma bölümü etiketi bulunamadı - - - - Invalid format in line {0}: {1} - {0}. satırda geçersiz biçim: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - {1}. konumdan başlayan satır ayrıştırılırken proje bölümünde '{0}' eksik - - - - Property set is missing '{0}' - Özellik kümesinde '{0}' eksik - - - - File header is missing version - Dosya üst bilgisinde sürüm eksik - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.zh-Hans.xlf deleted file mode 100644 index b353d12475e4..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.zh-Hans.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - 多次指定了全局节 - - - - Global section not closed - 未关闭全局节 - - - - Expected file header not found - 未找到必需的文件头 - - - - Project section not closed - 未关闭项目节 - - - - Invalid section type: {0} - 无效的节类型: {0} - - - - Section id missing - 缺少节 ID - - - - Closing section tag not found - 未找到结束节标记 - - - - Invalid format in line {0}: {1} - 行 {0} 存在无效格式: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - 分析从位置 {1} 开始的行时,项目节缺少“{0}” - - - - Property set is missing '{0}' - 属性集缺少“{0}” - - - - File header is missing version - 文件头缺少版本 - - - - - \ No newline at end of file diff --git a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.zh-Hant.xlf deleted file mode 100644 index 7fef8a4f8621..000000000000 --- a/src/Cli/Microsoft.DotNet.Cli.Sln.Internal/xlf/LocalizableStrings.zh-Hant.xlf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Global section specified more than once - 全域區段指定了一次以上 - - - - Global section not closed - 全域區段未關閉 - - - - Expected file header not found - 找不到預期的檔案標頭 - - - - Project section not closed - 專案區段未關閉 - - - - Invalid section type: {0} - 區段類型無效: {0} - - - - Section id missing - 遺漏區段識別碼 - - - - Closing section tag not found - 找不到關閉區段標記 - - - - Invalid format in line {0}: {1} - 第 {0} 行的格式不正確: {1} - - - - Project section is missing '{0}' when parsing the line starting at position {1} - 從位置 {1} 開始剖析程式行時,專案區段缺少 '{0}' - - - - Property set is missing '{0}' - 屬性集缺少 '{0}' - - - - File header is missing version - 檔案標頭遺漏版本 - - - - - \ No newline at end of file diff --git a/src/Cli/dotnet/ProjectInstanceExtensions.cs b/src/Cli/dotnet/ProjectInstanceExtensions.cs index 29337fa22c35..eea4778316d3 100644 --- a/src/Cli/dotnet/ProjectInstanceExtensions.cs +++ b/src/Cli/dotnet/ProjectInstanceExtensions.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.Build.Execution; -using Microsoft.DotNet.Cli.Sln.Internal; namespace Microsoft.DotNet.Tools.Common { @@ -22,7 +21,7 @@ public static string GetDefaultProjectTypeGuid(this ProjectInstance projectInsta string projectTypeGuid = projectInstance.GetPropertyValue("DefaultProjectTypeGuid"); if (string.IsNullOrEmpty(projectTypeGuid) && projectInstance.FullPath.EndsWith(".shproj", StringComparison.OrdinalIgnoreCase)) { - projectTypeGuid = ProjectTypeGuids.SharedProjectGuid; + projectTypeGuid = "{D954291E-2A0B-460D-934E-DC6B0785DB48}"; } return projectTypeGuid; } diff --git a/src/Cli/dotnet/ReleasePropertyProjectLocator.cs b/src/Cli/dotnet/ReleasePropertyProjectLocator.cs index 803a44b0e442..2d52334b58f1 100644 --- a/src/Cli/dotnet/ReleasePropertyProjectLocator.cs +++ b/src/Cli/dotnet/ReleasePropertyProjectLocator.cs @@ -4,11 +4,13 @@ using System.CommandLine; using System.Diagnostics; using Microsoft.Build.Execution; -using Microsoft.DotNet.Cli.Sln.Internal; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Tools; using Microsoft.DotNet.Tools.Common; using Microsoft.NET.Build.Tasks; +using Microsoft.VisualStudio.SolutionPersistence; +using Microsoft.VisualStudio.SolutionPersistence.Model; +using Microsoft.VisualStudio.SolutionPersistence.Serializer; namespace Microsoft.DotNet.Cli { @@ -129,7 +131,7 @@ public IEnumerable GetCustomDefaultConfigurationValueIfSpecified() } catch (GracefulException) // Fall back to looking for a solution if multiple project files are found, or there's no project in the directory. { - string? potentialSln = Directory.GetFiles(arg, "*.sln", SearchOption.TopDirectoryOnly).FirstOrDefault(); + string? potentialSln = SlnFileFactory.ListSolutionFilesInDirectory(arg, false).FirstOrDefault(); if (!string.IsNullOrEmpty(potentialSln)) { @@ -145,10 +147,15 @@ public IEnumerable GetCustomDefaultConfigurationValueIfSpecified() /// Throws exception if two+ projects disagree in PublishRelease, PackRelease, or whatever _propertyToCheck is, and have it defined. public ProjectInstance? GetArbitraryProjectFromSolution(string slnPath, Dictionary globalProps) { - SlnFile sln; + string slnFullPath = Path.GetFullPath(slnPath); + if (!Path.Exists(slnFullPath)) + { + return null; + } + SolutionModel sln; try { - sln = SlnFileFactory.CreateFromFileOrDirectory(slnPath); + sln = SlnFileFactory.CreateFromFileOrDirectory(slnFullPath, false); } catch (GracefulException) { @@ -163,13 +170,13 @@ public IEnumerable GetCustomDefaultConfigurationValueIfSpecified() if (string.Equals(Environment.GetEnvironmentVariable(EnvironmentVariableNames.DOTNET_CLI_LAZY_PUBLISH_AND_PACK_RELEASE_FOR_SOLUTIONS), "true", StringComparison.OrdinalIgnoreCase)) { // Evaluate only one project for speed if this environment variable is used. Will break more customers if enabled (adding 8.0 project to SLN with other project TFMs with no Publish or PackRelease.) - return GetSingleProjectFromSolution(sln, globalProps); + return GetSingleProjectFromSolution(sln, slnFullPath, globalProps); } - Parallel.ForEach(sln.Projects.AsEnumerable(), (project, state) => + Parallel.ForEach(sln.SolutionProjects.AsEnumerable(), (project, state) => { #pragma warning disable CS8604 // Possible null reference argument. - string projectFullPath = Path.Combine(Path.GetDirectoryName(sln.FullPath), project.FilePath); + string projectFullPath = Path.Combine(Path.GetDirectoryName(slnFullPath), project.FilePath); #pragma warning restore CS8604 // Possible null reference argument. if (IsUnanalyzableProjectInSolution(project, projectFullPath)) return; @@ -208,12 +215,12 @@ public IEnumerable GetCustomDefaultConfigurationValueIfSpecified() /// The solution to get an arbitrary project from. /// The global properties to load into the project. /// null if no project exists in the solution that can be evaluated properly. Else, the first project in the solution that can be. - private ProjectInstance? GetSingleProjectFromSolution(SlnFile sln, Dictionary globalProps) + private ProjectInstance? GetSingleProjectFromSolution(SolutionModel sln, string slnPath, Dictionary globalProps) { - foreach (var project in sln.Projects.AsEnumerable()) + foreach (var project in sln.SolutionProjects.AsEnumerable()) { #pragma warning disable CS8604 // Possible null reference argument. - string projectFullPath = Path.Combine(Path.GetDirectoryName(sln.FullPath), project.FilePath); + string projectFullPath = Path.Combine(Path.GetDirectoryName(slnPath), project.FilePath); #pragma warning restore CS8604 // Possible null reference argument. if (IsUnanalyzableProjectInSolution(project, projectFullPath)) continue; @@ -234,9 +241,9 @@ public IEnumerable GetCustomDefaultConfigurationValueIfSpecified() /// The project under a solution to evaluate. /// The full hard-coded path of the project. /// True if the project is not supported by ProjectInstance class or appears to be invalid. - private bool IsUnanalyzableProjectInSolution(SlnProject project, string projectFullPath) + private bool IsUnanalyzableProjectInSolution(SolutionProjectModel project, string projectFullPath) { - return project.TypeGuid == solutionFolderGuid || project.TypeGuid == sharedProjectGuid || !IsValidProjectFilePath(projectFullPath); + return project.TypeId.ToString() == solutionFolderGuid || project.TypeId.ToString() == sharedProjectGuid || !IsValidProjectFilePath(projectFullPath); } /// Creates a ProjectInstance if the project is valid, elsewise, fails. @@ -262,7 +269,7 @@ private bool IsValidProjectFilePath(string path) /// Returns true if the path exists and is a sln file type. private bool IsValidSlnFilePath(string path) { - return File.Exists(path) && Path.GetExtension(path).EndsWith("sln"); + return File.Exists(path) && (Path.GetExtension(path).Equals(".sln")|| Path.GetExtension(path).Equals(".slnx")); } /// A case-insensitive dictionary of any properties passed from the user and their values. diff --git a/src/Cli/dotnet/SlnFileExtensions.cs b/src/Cli/dotnet/SlnFileExtensions.cs deleted file mode 100644 index 0a981b9e2429..000000000000 --- a/src/Cli/dotnet/SlnFileExtensions.cs +++ /dev/null @@ -1,541 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.Build.Construction; -using Microsoft.Build.Exceptions; -using Microsoft.Build.Execution; -using Microsoft.DotNet.Cli.Sln.Internal; -using Microsoft.DotNet.Cli.Utils; -using System.Collections.Generic; - -namespace Microsoft.DotNet.Tools.Common -{ - internal static class SlnFileExtensions - { - public static void AddProject(this SlnFile slnFile, string fullProjectPath, IList solutionFolders) - { - if (string.IsNullOrEmpty(fullProjectPath)) - { - throw new ArgumentException(); - } - - var relativeProjectPath = Path.GetRelativePath( - PathUtility.EnsureTrailingSlash(slnFile.BaseDirectory), - fullProjectPath); - - if (slnFile.Projects.Any((p) => - string.Equals(p.FilePath, relativeProjectPath, StringComparison.OrdinalIgnoreCase))) - { - Reporter.Output.WriteLine(string.Format( - CommonLocalizableStrings.SolutionAlreadyContainsProject, - slnFile.FullPath, - relativeProjectPath)); - } - else - { - ProjectRootElement rootElement = null; - ProjectInstance projectInstance = null; - try - { - rootElement = ProjectRootElement.Open(fullProjectPath); - projectInstance = new ProjectInstance(rootElement); - } - catch (InvalidProjectFileException e) - { - Reporter.Error.WriteLine(string.Format( - CommonLocalizableStrings.InvalidProjectWithExceptionMessage, - fullProjectPath, - e.Message)); - return; - } - - var slnProject = new SlnProject - { - Id = projectInstance.GetProjectId(), - TypeGuid = rootElement.GetProjectTypeGuid() ?? projectInstance.GetDefaultProjectTypeGuid(), - Name = Path.GetFileNameWithoutExtension(relativeProjectPath), - FilePath = relativeProjectPath - }; - - if (string.IsNullOrEmpty(slnProject.TypeGuid)) - { - Reporter.Error.WriteLine( - string.Format( - CommonLocalizableStrings.UnsupportedProjectType, - projectInstance.FullPath)); - return; - } - - // NOTE: The order you create the sections determines the order they are written to the sln - // file. In the case of an empty sln file, in order to make sure the solution configurations - // section comes first we need to add it first. This doesn't affect correctness but does - // stop VS from re-ordering things later on. Since we are keeping the SlnFile class low-level - // it shouldn't care about the VS implementation details. That's why we handle this here. - if (AreBuildConfigurationsApplicable(slnProject.TypeGuid)) - { - slnFile.AddDefaultBuildConfigurations(); - - slnFile.MapSolutionConfigurationsToProject( - projectInstance, - slnFile.ProjectConfigurationsSection.GetOrCreatePropertySet(slnProject.Id)); - } - - SetupSolutionFolders(slnFile, solutionFolders, relativeProjectPath, slnProject); - - slnFile.Projects.Add(slnProject); - - Reporter.Output.WriteLine( - string.Format(CommonLocalizableStrings.ProjectAddedToTheSolution, relativeProjectPath)); - } - } - - private static bool AreBuildConfigurationsApplicable(string projectTypeGuid) - { - return !projectTypeGuid.Equals(ProjectTypeGuids.SharedProjectGuid, StringComparison.OrdinalIgnoreCase); - } - - private static void SetupSolutionFolders(SlnFile slnFile, IList solutionFolders, string relativeProjectPath, SlnProject slnProject) - { - if (solutionFolders != null) - { - if (solutionFolders.Any()) - { - // Before adding a solution folder, check if the name conflicts with any existing projects in the solution - var duplicateProjects = slnFile.Projects.Where(p => solutionFolders.Contains(p.Name) - && p.TypeGuid != ProjectTypeGuids.SolutionFolderGuid).ToList(); - foreach (SlnProject duplicateProject in duplicateProjects) - { - slnFile.AddSolutionFolders(duplicateProject, new List() { Path.GetDirectoryName(duplicateProject.FilePath) }); - } - } - else - { - // If a project and solution folder have the same name, add it's own folder as a solution folder - // eg. foo\extensions.csproj and extensions\library\library.csproj would have a project and solution folder with conflicting names - var duplicateProject = slnFile.Projects.Where(p => string.Equals(p.Name, slnProject.Name, StringComparison.OrdinalIgnoreCase) - && p.TypeGuid == ProjectTypeGuids.SolutionFolderGuid).FirstOrDefault(); - if (duplicateProject != null) - { - // Try making a new folder for the project to put it under so we can still add it despite there being one with the same name already in the parent folder - slnFile.AddSolutionFolders(slnProject, new List() { Path.GetDirectoryName(relativeProjectPath) }); - } - } - // Even if we added a solution folder above for a duplicate, we still need to add the expected folder for the current project - slnFile.AddSolutionFolders(slnProject, solutionFolders); - } - } - - private static void AddDefaultBuildConfigurations(this SlnFile slnFile) - { - var configurationsSection = slnFile.SolutionConfigurationsSection; - - if (!configurationsSection.IsEmpty) - { - return; - } - - var defaultConfigurations = new List() - { - "Debug|Any CPU", - "Debug|x64", - "Debug|x86", - "Release|Any CPU", - "Release|x64", - "Release|x86", - }; - - foreach (var config in defaultConfigurations) - { - configurationsSection[config] = config; - } - } - - private static void MapSolutionConfigurationsToProject( - this SlnFile slnFile, - ProjectInstance projectInstance, - SlnPropertySet solutionProjectConfigs) - { - var (projectConfigurations, defaultProjectConfiguration) = GetKeysDictionary(projectInstance.GetConfigurations()); - var (projectPlatforms, defaultProjectPlatform) = GetKeysDictionary(projectInstance.GetPlatforms()); - - foreach (var solutionConfigKey in slnFile.SolutionConfigurationsSection.Keys) - { - var projectConfigKey = MapSolutionConfigKeyToProjectConfigKey( - solutionConfigKey, - projectConfigurations, - defaultProjectConfiguration, - projectPlatforms, - defaultProjectPlatform); - if (projectConfigKey == null) - { - continue; - } - - var activeConfigKey = $"{solutionConfigKey}.ActiveCfg"; - if (!solutionProjectConfigs.ContainsKey(activeConfigKey)) - { - solutionProjectConfigs[activeConfigKey] = projectConfigKey; - } - - var buildKey = $"{solutionConfigKey}.Build.0"; - if (!solutionProjectConfigs.ContainsKey(buildKey)) - { - solutionProjectConfigs[buildKey] = projectConfigKey; - } - } - } - - private static (Dictionary Keys, string DefaultKey) GetKeysDictionary(IEnumerable keys) - { - // A dictionary mapping key -> key is used instead of a HashSet so the original case of the key can be retrieved from the set - var dictionary = new Dictionary(StringComparer.CurrentCultureIgnoreCase); - - foreach (var key in keys) - { - dictionary[key] = key; - } - - return (dictionary, keys.FirstOrDefault()); - } - - private static string GetMatchingProjectKey(IDictionary projectKeys, string solutionKey) - { - string projectKey; - if (projectKeys.TryGetValue(solutionKey, out projectKey)) - { - return projectKey; - } - - var keyWithoutWhitespace = string.Concat(solutionKey.Where(c => !char.IsWhiteSpace(c))); - if (projectKeys.TryGetValue(keyWithoutWhitespace, out projectKey)) - { - return projectKey; - } - - return null; - } - - private static string MapSolutionConfigKeyToProjectConfigKey( - string solutionConfigKey, - Dictionary projectConfigurations, - string defaultProjectConfiguration, - Dictionary projectPlatforms, - string defaultProjectPlatform) - { - var pair = solutionConfigKey.Split(new char[] { '|' }, 2); - if (pair.Length != 2) - { - return null; - } - - var projectConfiguration = GetMatchingProjectKey(projectConfigurations, pair[0]) ?? defaultProjectConfiguration; - if (projectConfiguration == null) - { - return null; - } - - var projectPlatform = GetMatchingProjectKey(projectPlatforms, pair[1]) ?? defaultProjectPlatform; - if (projectPlatform == null) - { - return null; - } - - // VS stores "Any CPU" platform in the solution regardless of how it is named at the project level - return $"{projectConfiguration}|{(projectPlatform == "AnyCPU" ? "Any CPU" : projectPlatform)}"; - } - - private static void AddSolutionFolders(this SlnFile slnFile, SlnProject slnProject, IList solutionFolders) - { - if (solutionFolders.Any()) - { - var nestedProjectsSection = slnFile.Sections.GetOrCreateSection( - "NestedProjects", - SlnSectionType.PreProcess); - - var pathToGuidMap = slnFile.GetSolutionFolderPaths(nestedProjectsSection.Properties); - - if (slnFile.HasSolutionFolder(nestedProjectsSection.Properties, slnProject)) - { - return; - } - - string parentDirGuid = null; - var solutionFolderHierarchy = string.Empty; - foreach (var dir in solutionFolders) - { - solutionFolderHierarchy = Path.Combine(solutionFolderHierarchy, dir); - if (pathToGuidMap.ContainsKey(solutionFolderHierarchy)) - { - parentDirGuid = pathToGuidMap[solutionFolderHierarchy]; - } - else - { - - if(HasDuplicateNameForSameValueOfNestedProjects(nestedProjectsSection, dir, parentDirGuid, slnFile.Projects)) - { - throw new GracefulException(CommonLocalizableStrings.SolutionFolderAlreadyContainsProject, slnFile.FullPath, slnProject.Name, slnFile.Projects.FirstOrDefault(p => p.Id == parentDirGuid).Name); - } - - var solutionFolder = new SlnProject - { - Id = Guid.NewGuid().ToString("B").ToUpper(), - TypeGuid = ProjectTypeGuids.SolutionFolderGuid, - Name = dir, - FilePath = dir - }; - - slnFile.Projects.Add(solutionFolder); - - if (parentDirGuid != null) - { - nestedProjectsSection.Properties[solutionFolder.Id] = parentDirGuid; - } - parentDirGuid = solutionFolder.Id; - } - } - if (HasDuplicateNameForSameValueOfNestedProjects(nestedProjectsSection, slnProject.Name, parentDirGuid, slnFile.Projects)) - { - throw new GracefulException(CommonLocalizableStrings.SolutionFolderAlreadyContainsProject, slnFile.FullPath, slnProject.Name, slnFile.Projects.FirstOrDefault(p => p.Id == parentDirGuid).Name); - } - nestedProjectsSection.Properties[slnProject.Id] = parentDirGuid; - } - } - - private static bool HasDuplicateNameForSameValueOfNestedProjects(SlnSection nestedProjectsSection, string name, string value, IList projects) - { - foreach (var property in nestedProjectsSection.Properties) - { - if (property.Value == value) - { - var existingProject = projects.FirstOrDefault(p => p.Id == property.Key); - - if (existingProject != null && existingProject.Name == name) - { - return true; - } - } - } - return false; - } - - private static IDictionary GetSolutionFolderPaths( - this SlnFile slnFile, - SlnPropertySet nestedProjects) - { - var solutionFolderPaths = new Dictionary(StringComparer.OrdinalIgnoreCase); - - var solutionFolderProjects = slnFile.Projects.GetProjectsByType(ProjectTypeGuids.SolutionFolderGuid); - foreach (var slnProject in solutionFolderProjects) - { - var path = slnProject.FilePath; - var id = slnProject.Id; - while (nestedProjects.ContainsKey(id)) - { - id = nestedProjects[id]; - var parentSlnProject = solutionFolderProjects.Where(p => p.Id == id).SingleOrDefault(); - if (parentSlnProject == null) // see: https://github.com/dotnet/sdk/pull/28811 - throw new GracefulException(CommonLocalizableStrings.CorruptSolutionProjectFolderStructure, slnFile.FullPath, id); - path = Path.Combine(parentSlnProject.FilePath, path); - } - - solutionFolderPaths[path] = slnProject.Id; - } - - return solutionFolderPaths; - } - - private static bool HasSolutionFolder( - this SlnFile slnFile, - SlnPropertySet properties, - SlnProject slnProject) - { - return properties.ContainsKey(slnProject.Id); - } - - public static bool RemoveProject(this SlnFile slnFile, string projectPath) - { - if (string.IsNullOrEmpty(projectPath)) - { - throw new ArgumentException(); - } - - var projectPathNormalized = PathUtility.GetPathWithDirectorySeparator(projectPath); - - var projectsToRemove = slnFile.Projects.Where((p) => - string.Equals(p.FilePath, projectPathNormalized, StringComparison.OrdinalIgnoreCase)).ToList(); - - bool projectRemoved = false; - if (projectsToRemove.Count == 0) - { - Reporter.Output.WriteLine(string.Format( - CommonLocalizableStrings.ProjectNotFoundInTheSolution, - projectPath)); - } - else - { - foreach (var slnProject in projectsToRemove) - { - var buildConfigsToRemove = slnFile.ProjectConfigurationsSection.GetPropertySet(slnProject.Id); - if (buildConfigsToRemove != null) - { - slnFile.ProjectConfigurationsSection.Remove(buildConfigsToRemove); - } - - var nestedProjectsSection = slnFile.Sections.GetSection( - "NestedProjects", - SlnSectionType.PreProcess); - if (nestedProjectsSection != null && nestedProjectsSection.Properties.ContainsKey(slnProject.Id)) - { - nestedProjectsSection.Properties.Remove(slnProject.Id); - } - - slnFile.Projects.Remove(slnProject); - Reporter.Output.WriteLine( - string.Format(CommonLocalizableStrings.ProjectRemovedFromTheSolution, slnProject.FilePath)); - } - - foreach (var project in slnFile.Projects) - { - var dependencies = project.Dependencies; - if (dependencies == null) - { - continue; - } - - dependencies.SkipIfEmpty = true; - - foreach (var removed in projectsToRemove) - { - dependencies.Properties.Remove(removed.Id); - } - } - - projectRemoved = true; - } - - return projectRemoved; - } - - public static void RemoveEmptyConfigurationSections(this SlnFile slnFile) - { - if (slnFile.Projects.Count == 0) - { - var solutionConfigs = slnFile.Sections.GetSection("SolutionConfigurationPlatforms"); - if (solutionConfigs != null) - { - slnFile.Sections.Remove(solutionConfigs); - } - - var projectConfigs = slnFile.Sections.GetSection("ProjectConfigurationPlatforms"); - if (projectConfigs != null) - { - slnFile.Sections.Remove(projectConfigs); - } - } - } - - public static void RemoveEmptySolutionFolders(this SlnFile slnFile) - { - var solutionFolderProjects = slnFile.Projects - .GetProjectsByType(ProjectTypeGuids.SolutionFolderGuid) - .ToList(); - - if (solutionFolderProjects.Any()) - { - var nestedProjectsSection = slnFile.Sections.GetSection( - "NestedProjects", - SlnSectionType.PreProcess); - - if (nestedProjectsSection == null) - { - foreach (var solutionFolderProject in solutionFolderProjects) - { - if (solutionFolderProject.Sections.Count() == 0) - { - slnFile.Projects.Remove(solutionFolderProject); - } - } - } - else - { - var solutionFoldersInUse = slnFile.GetSolutionFoldersThatContainProjectsInItsHierarchy( - nestedProjectsSection.Properties); - - solutionFoldersInUse.UnionWith(slnFile.GetSolutionFoldersThatContainSolutionItemsInItsHierarchy( - nestedProjectsSection.Properties)); - - foreach (var solutionFolderProject in solutionFolderProjects) - { - if (!solutionFoldersInUse.Contains(solutionFolderProject.Id)) - { - nestedProjectsSection.Properties.Remove(solutionFolderProject.Id); - if (solutionFolderProject.Sections.Count() == 0) - { - slnFile.Projects.Remove(solutionFolderProject); - } - } - } - - if (nestedProjectsSection.IsEmpty) - { - slnFile.Sections.Remove(nestedProjectsSection); - } - } - } - } - - private static HashSet GetSolutionFoldersThatContainProjectsInItsHierarchy( - this SlnFile slnFile, - SlnPropertySet nestedProjects) - { - var solutionFoldersInUse = new HashSet(); - - IEnumerable nonSolutionFolderProjects; - nonSolutionFolderProjects = slnFile.Projects.GetProjectsNotOfType( - ProjectTypeGuids.SolutionFolderGuid); - - foreach (var nonSolutionFolderProject in nonSolutionFolderProjects) - { - var id = nonSolutionFolderProject.Id; - while (nestedProjects.ContainsKey(id)) - { - id = nestedProjects[id]; - solutionFoldersInUse.Add(id); - } - } - - return solutionFoldersInUse; - } - - private static HashSet GetSolutionFoldersThatContainSolutionItemsInItsHierarchy( - this SlnFile slnFile, - SlnPropertySet nestedProjects) - { - var solutionFoldersInUse = new HashSet(); - - var solutionItemsFolderProjects = slnFile.Projects - .GetProjectsByType(ProjectTypeGuids.SolutionFolderGuid) - .Where(ContainsSolutionItems); - - foreach (var solutionItemsFolderProject in solutionItemsFolderProjects) - { - var id = solutionItemsFolderProject.Id; - solutionFoldersInUse.Add(id); - - while (nestedProjects.ContainsKey(id)) - { - id = nestedProjects[id]; - solutionFoldersInUse.Add(id); - } - } - - return solutionFoldersInUse; - } - - private static bool ContainsSolutionItems(SlnProject project) - { - return project.Sections - .GetSection("SolutionItems", SlnSectionType.PreProcess) != null; - } - } -} diff --git a/src/Cli/dotnet/SlnFileFactory.cs b/src/Cli/dotnet/SlnFileFactory.cs index 49a33de4c782..9402883da500 100644 --- a/src/Cli/dotnet/SlnFileFactory.cs +++ b/src/Cli/dotnet/SlnFileFactory.cs @@ -1,14 +1,25 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.DotNet.Cli.Sln.Internal; using Microsoft.DotNet.Cli.Utils; +using Microsoft.VisualStudio.SolutionPersistence; +using Microsoft.VisualStudio.SolutionPersistence.Model; +using Microsoft.VisualStudio.SolutionPersistence.Serializer; namespace Microsoft.DotNet.Tools.Common { public static class SlnFileFactory { - public static SlnFile CreateFromFileOrDirectory(string fileOrDirectory) + public static string[] ListSolutionFilesInDirectory(string directory, bool includeSolutionFilterFiles = false, bool includeSolutionXmlFiles = true) + { + return [ + ..Directory.GetFiles(directory, "*.sln", SearchOption.TopDirectoryOnly), + ..(includeSolutionXmlFiles ? Directory.GetFiles(directory, "*.slnx", SearchOption.TopDirectoryOnly) : []), + ..(includeSolutionFilterFiles ? Directory.GetFiles(directory, "*.slnf", SearchOption.TopDirectoryOnly) : []) + ]; + } + + public static SolutionModel CreateFromFileOrDirectory(string fileOrDirectory, bool includeSolutionXmlFiles = true) { if (File.Exists(fileOrDirectory)) { @@ -16,18 +27,22 @@ public static SlnFile CreateFromFileOrDirectory(string fileOrDirectory) } else { - return FromDirectory(fileOrDirectory); + return FromDirectory(fileOrDirectory, includeSolutionXmlFiles); } } - private static SlnFile FromFile(string solutionPath) + private static SolutionModel FromFile(string solutionPath) { - SlnFile slnFile = null; + SolutionModel slnFile = null; try { - slnFile = SlnFile.Read(solutionPath); + ISolutionSerializer serializer = SolutionSerializers.GetSerializerByMoniker(solutionPath) ?? throw new GracefulException( + CommonLocalizableStrings.CouldNotFindSolutionOrDirectory, + solutionPath); + + slnFile = serializer.OpenAsync(solutionPath, CancellationToken.None).Result; } - catch (InvalidSolutionFormatException e) + catch (SolutionException e) { throw new GracefulException( CommonLocalizableStrings.InvalidSolutionFormatString, @@ -37,7 +52,7 @@ private static SlnFile FromFile(string solutionPath) return slnFile; } - private static SlnFile FromDirectory(string solutionDirectory) + private static SolutionModel FromDirectory(string solutionDirectory, bool includeSolutionXmlFiles) { DirectoryInfo dir; try @@ -57,7 +72,11 @@ private static SlnFile FromDirectory(string solutionDirectory) solutionDirectory); } - FileInfo[] files = dir.GetFiles("*.sln"); + FileInfo[] files = [ + ..dir.GetFiles("*.sln"), + ..(includeSolutionXmlFiles ? dir.GetFiles(".slnx") : []) + ]; + if (files.Length == 0) { throw new GracefulException( diff --git a/src/Cli/dotnet/SlnProjectCollectionExtensions.cs b/src/Cli/dotnet/SlnProjectCollectionExtensions.cs deleted file mode 100644 index f0d70ae4e640..000000000000 --- a/src/Cli/dotnet/SlnProjectCollectionExtensions.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.DotNet.Cli.Sln.Internal; - -namespace Microsoft.DotNet.Tools.Common -{ - internal static class SlnProjectCollectionExtensions - { - public static IEnumerable GetProjectsByType( - this SlnProjectCollection projects, - string typeGuid) - { - return projects.Where(p => p.TypeGuid == typeGuid); - } - - public static IEnumerable GetProjectsNotOfType( - this SlnProjectCollection projects, - string typeGuid) - { - return projects.Where(p => p.TypeGuid != typeGuid); - } - } -} diff --git a/src/Cli/dotnet/SlnProjectExtensions.cs b/src/Cli/dotnet/SlnProjectExtensions.cs deleted file mode 100644 index 405c3b43cb88..000000000000 --- a/src/Cli/dotnet/SlnProjectExtensions.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.DotNet.Cli.Sln.Internal; - -namespace Microsoft.DotNet.Tools.Common -{ - internal static class SlnProjectExtensions - { - public static string GetFullSolutionFolderPath(this SlnProject slnProject) - { - var slnFile = slnProject.ParentFile; - var nestedProjects = slnFile.Sections - .GetOrCreateSection("NestedProjects", SlnSectionType.PreProcess) - .Properties; - var solutionFolders = slnFile.Projects - .GetProjectsByType(ProjectTypeGuids.SolutionFolderGuid) - .ToArray(); - - string path = slnProject.Name; - string id = slnProject.Id; - - // If the nested projects contains this project's id then it has a parent - // Traverse from the project to each parent prepending the solution folder to the path - while (nestedProjects.ContainsKey(id)) - { - id = nestedProjects[id]; - - string solutionFolderPath = solutionFolders.Single(p => p.Id == id).FilePath; - path = Path.Combine(solutionFolderPath, path); - } - - return path; - } - } -} diff --git a/src/Cli/dotnet/commands/dotnet-list/dotnet-list-package/ListPackageReferencesCommand.cs b/src/Cli/dotnet/commands/dotnet-list/dotnet-list-package/ListPackageReferencesCommand.cs index 9ca3b27a500f..cbd10c1016f0 100644 --- a/src/Cli/dotnet/commands/dotnet-list/dotnet-list-package/ListPackageReferencesCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-list/dotnet-list-package/ListPackageReferencesCommand.cs @@ -4,6 +4,7 @@ using System.CommandLine; using Microsoft.DotNet.Cli; using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Tools.Common; using Microsoft.DotNet.Tools.NuGet; namespace Microsoft.DotNet.Tools.List.PackageReferences @@ -71,7 +72,7 @@ private string GetProjectOrSolution() if (Directory.Exists(resultPath)) { - var possibleSolutionPath = Directory.GetFiles(resultPath, "*.sln", SearchOption.TopDirectoryOnly); + string[] possibleSolutionPath = SlnFileFactory.ListSolutionFilesInDirectory(resultPath, false); //If more than a single sln file is found, an error is thrown since we can't determine which one to choose. if (possibleSolutionPath.Count() > 1) diff --git a/src/Cli/dotnet/commands/dotnet-new/PostActions/DotnetSlnPostActionProcessor.cs b/src/Cli/dotnet/commands/dotnet-new/PostActions/DotnetSlnPostActionProcessor.cs index 63afaeb19965..28143fd21d82 100644 --- a/src/Cli/dotnet/commands/dotnet-new/PostActions/DotnetSlnPostActionProcessor.cs +++ b/src/Cli/dotnet/commands/dotnet-new/PostActions/DotnetSlnPostActionProcessor.cs @@ -27,7 +27,8 @@ public DotnetSlnPostActionProcessor(Func, string?, internal static IReadOnlyList FindSolutionFilesAtOrAbovePath(IPhysicalFileSystem fileSystem, string outputBasePath) { - return FileFindHelpers.FindFilesAtOrAbovePath(fileSystem, outputBasePath, "*.sln"); + return FileFindHelpers.FindFilesAtOrAbovePath(fileSystem, outputBasePath, "*.sln") + ?? FileFindHelpers.FindFilesAtOrAbovePath(fileSystem, outputBasePath, "*.slnx"); } // The project files to add are a subset of the primary outputs, specifically the primary outputs indicated by the primaryOutputIndexes post action argument (semicolon separated) diff --git a/src/Cli/dotnet/commands/dotnet-sln/list/Program.cs b/src/Cli/dotnet/commands/dotnet-sln/list/Program.cs index 99b948207011..0a7522c46242 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/list/Program.cs +++ b/src/Cli/dotnet/commands/dotnet-sln/list/Program.cs @@ -3,7 +3,6 @@ using System.CommandLine; using Microsoft.DotNet.Cli; -using Microsoft.DotNet.Cli.Sln.Internal; using Microsoft.DotNet.Cli.Utils; using Microsoft.VisualStudio.SolutionPersistence; using Microsoft.VisualStudio.SolutionPersistence.Model; diff --git a/src/Cli/dotnet/commands/dotnet-workload/restore/WorkloadRestoreCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/restore/WorkloadRestoreCommand.cs index 41fa1049bf3b..f25690d52963 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/restore/WorkloadRestoreCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/restore/WorkloadRestoreCommand.cs @@ -8,6 +8,7 @@ using Microsoft.DotNet.Cli; using Microsoft.DotNet.Cli.NuGetPackageDownloader; using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Tools.Common; using Microsoft.DotNet.Workloads.Workload.Install; using Microsoft.DotNet.Workloads.Workload.Update; using Microsoft.Extensions.EnvironmentAbstractions; @@ -122,13 +123,13 @@ internal static List DiscoverAllProjects(string currentDirectory, var projectFiles = new List(); if (slnOrProjectArgument == null || !slnOrProjectArgument.Any()) { - slnFiles = Directory.GetFiles(currentDirectory, "*.sln").ToList(); + slnFiles = SlnFileFactory.ListSolutionFilesInDirectory(currentDirectory, false).ToList(); projectFiles.AddRange(Directory.GetFiles(currentDirectory, "*.*proj")); } else { slnFiles = slnOrProjectArgument - .Where(s => Path.GetExtension(s).Equals(".sln", StringComparison.OrdinalIgnoreCase)) + .Where(s => Path.GetExtension(s).Equals(".sln", StringComparison.OrdinalIgnoreCase) || Path.GetExtension(s).Equals(".slnx", StringComparison.OrdinalIgnoreCase)) .Select(Path.GetFullPath).ToList(); projectFiles = slnOrProjectArgument .Where(s => Path.GetExtension(s).EndsWith("proj", StringComparison.OrdinalIgnoreCase)) @@ -137,12 +138,8 @@ internal static List DiscoverAllProjects(string currentDirectory, foreach (string file in slnFiles) { - var solutionFile = SolutionFile.Parse(file); - var projects = solutionFile.ProjectsInOrder.Where(p => p.ProjectType != SolutionProjectType.SolutionFolder); - foreach (var p in projects) - { - projectFiles.Add(p.AbsolutePath); - } + var solutionFile = SlnFileFactory.CreateFromFileOrDirectory(file); + projectFiles.AddRange(solutionFile.SolutionProjects.Select(p => p.FilePath)); } if (projectFiles.Count == 0) diff --git a/src/Cli/dotnet/dotnet.csproj b/src/Cli/dotnet/dotnet.csproj index 82db3621e7fc..da9f09bd96c8 100644 --- a/src/Cli/dotnet/dotnet.csproj +++ b/src/Cli/dotnet/dotnet.csproj @@ -91,7 +91,6 @@ - diff --git a/src/WebSdk/Publish/Tasks/WebConfigTelemetry.cs b/src/WebSdk/Publish/Tasks/WebConfigTelemetry.cs index 80e0e4385e31..f6660fbd72ff 100644 --- a/src/WebSdk/Publish/Tasks/WebConfigTelemetry.cs +++ b/src/WebSdk/Publish/Tasks/WebConfigTelemetry.cs @@ -66,7 +66,10 @@ public static string GetProjectGuidFromSolutionFile(string solutionFileFullPath, return null; } - IEnumerable solutionFiles = Directory.EnumerateFiles(solutionDirectory, "*.sln", SearchOption.TopDirectoryOnly); + IEnumerable solutionFiles = [ + ..Directory.EnumerateFiles(solutionDirectory, "*.sln", SearchOption.TopDirectoryOnly), + ..Directory.EnumerateFiles(solutionDirectory, "*.slnx", SearchOption.TopDirectoryOnly) + ]; foreach (string solutionFile in solutionFiles) { string projectGuid = GetProjectGuid(solutionFile, projectFileFullPath); diff --git a/test/Microsoft.DotNet.Cli.Sln.Internal.Tests/Microsoft.DotNet.Cli.Sln.Internal.Tests.cs b/test/Microsoft.DotNet.Cli.Sln.Internal.Tests/Microsoft.DotNet.Cli.Sln.Internal.Tests.cs deleted file mode 100644 index 910eb8685f28..000000000000 --- a/test/Microsoft.DotNet.Cli.Sln.Internal.Tests/Microsoft.DotNet.Cli.Sln.Internal.Tests.cs +++ /dev/null @@ -1,530 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Runtime.CompilerServices; - -namespace Microsoft.DotNet.Cli.Sln.Internal.Tests -{ - public class GivenAnSlnFile : SdkTest - { - private const string SolutionModified = @" -Microsoft Visual Studio Solution File, Format Version 14.00 -# Visual Studio 16 -VisualStudioVersion = 16.0.26006.2 -MinimumVisualStudioVersion = 11.0.40219.1 -Project(""{7072A694-548F-4CAE-A58F-12D257D5F486}"") = ""AppModified"", ""AppModified\AppModified.csproj"", ""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.ActiveCfg = Debug|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.Build.0 = Debug|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.ActiveCfg = Debug|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.Build.0 = Debug|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.Build.0 = Release|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.ActiveCfg = Release|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.Build.0 = Release|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.ActiveCfg = Release|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.Build.0 = Release|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = TRUE - EndGlobalSection -EndGlobal -"; - - private const string SolutionWithAppAndLibProjects = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26006.2 -MinimumVisualStudioVersion = 10.0.40219.1 -Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""App"", ""App\App.csproj"", ""{7072A694-548F-4CAE-A58F-12D257D5F486}"" -EndProject -Project(""{13B669BE-BB05-4DDF-9536-439F39A36129}"") = ""Lib"", ""..\Lib\Lib.csproj"", ""{21D9159F-60E6-4F65-BC6B-D01B71B15FFC}"" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.ActiveCfg = Debug|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.Build.0 = Debug|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.ActiveCfg = Debug|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.Build.0 = Debug|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.Build.0 = Release|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.ActiveCfg = Release|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.Build.0 = Release|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.ActiveCfg = Release|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.Build.0 = Release|x86 - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Debug|x64.ActiveCfg = Debug|x64 - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Debug|x64.Build.0 = Debug|x64 - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Debug|x86.ActiveCfg = Debug|x86 - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Debug|x86.Build.0 = Debug|x86 - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Release|Any CPU.Build.0 = Release|Any CPU - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Release|x64.ActiveCfg = Release|x64 - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Release|x64.Build.0 = Release|x64 - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Release|x86.ActiveCfg = Release|x86 - {21D9159F-60E6-4F65-BC6B-D01B71B15FFC}.Release|x86.Build.0 = Release|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal -"; - - public GivenAnSlnFile(ITestOutputHelper log) : base(log) - { - } - - private string CreateFile([CallerMemberName] string callerName = null, string identifier = null) - { - var folder = _testAssetsManager.CreateTestDirectory(testName: callerName + identifier); - var filename = Path.Combine(folder.Path, Guid.NewGuid().ToString() + ".tmp"); - using (new FileStream(filename, FileMode.CreateNew)) { } - return filename; - } - - - [Fact] - public void WhenGivenAValidSlnFileItReadsAndVerifiesContents() - { - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionWithAppAndLibProjects); - - SlnFile slnFile = SlnFile.Read(tmpFile); - - Console.WriteLine(new - { - slnFile_FormatVersion = slnFile.FormatVersion, - slnFile_ProductDescription = slnFile.ProductDescription, - slnFile_VisualStudioVersion = slnFile.VisualStudioVersion, - slnFile_MinimumVisualStudioVersion = slnFile.MinimumVisualStudioVersion, - slnFile_BaseDirectory = slnFile.BaseDirectory, - slnFile_FullPath = slnFile.FullPath, - tmpFilePath = tmpFile - }.ToString()); - - slnFile.FormatVersion.Should().Be("12.00"); - slnFile.ProductDescription.Should().Be("Visual Studio 15"); - slnFile.VisualStudioVersion.Should().Be("15.0.26006.2"); - slnFile.MinimumVisualStudioVersion.Should().Be("10.0.40219.1"); - slnFile.BaseDirectory.Should().Be(Path.GetDirectoryName(tmpFile)); - slnFile.FullPath.Should().Be(Path.GetFullPath(tmpFile)); - - slnFile.Projects.Count.Should().Be(2); - var project = slnFile.Projects[0]; - project.Id.Should().Be("{7072A694-548F-4CAE-A58F-12D257D5F486}"); - project.TypeGuid.Should().Be("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"); - project.Name.Should().Be("App"); - project.FilePath.Should().Be(Path.Combine("App", "App.csproj")); - project = slnFile.Projects[1]; - project.Id.Should().Be("{21D9159F-60E6-4F65-BC6B-D01B71B15FFC}"); - project.TypeGuid.Should().Be("{13B669BE-BB05-4DDF-9536-439F39A36129}"); - project.Name.Should().Be("Lib"); - project.FilePath.Should().Be(Path.Combine("..", "Lib", "Lib.csproj")); - - slnFile.SolutionConfigurationsSection.Count.Should().Be(6); - slnFile.SolutionConfigurationsSection - .GetValue("Debug|Any CPU", string.Empty) - .Should().Be("Debug|Any CPU"); - slnFile.SolutionConfigurationsSection - .GetValue("Debug|x64", string.Empty) - .Should().Be("Debug|x64"); - slnFile.SolutionConfigurationsSection - .GetValue("Debug|x86", string.Empty) - .Should().Be("Debug|x86"); - slnFile.SolutionConfigurationsSection - .GetValue("Release|Any CPU", string.Empty) - .Should().Be("Release|Any CPU"); - slnFile.SolutionConfigurationsSection - .GetValue("Release|x64", string.Empty) - .Should().Be("Release|x64"); - slnFile.SolutionConfigurationsSection - .GetValue("Release|x86", string.Empty) - .Should().Be("Release|x86"); - - slnFile.ProjectConfigurationsSection.Count.Should().Be(2); - var projectConfigSection = slnFile - .ProjectConfigurationsSection - .GetPropertySet("{7072A694-548F-4CAE-A58F-12D257D5F486}"); - projectConfigSection.Count.Should().Be(12); - projectConfigSection - .GetValue("Debug|Any CPU.ActiveCfg", string.Empty) - .Should().Be("Debug|Any CPU"); - projectConfigSection - .GetValue("Debug|Any CPU.Build.0", string.Empty) - .Should().Be("Debug|Any CPU"); - projectConfigSection - .GetValue("Debug|x64.ActiveCfg", string.Empty) - .Should().Be("Debug|x64"); - projectConfigSection - .GetValue("Debug|x64.Build.0", string.Empty) - .Should().Be("Debug|x64"); - projectConfigSection - .GetValue("Debug|x86.ActiveCfg", string.Empty) - .Should().Be("Debug|x86"); - projectConfigSection - .GetValue("Debug|x86.Build.0", string.Empty) - .Should().Be("Debug|x86"); - projectConfigSection - .GetValue("Release|Any CPU.ActiveCfg", string.Empty) - .Should().Be("Release|Any CPU"); - projectConfigSection - .GetValue("Release|Any CPU.Build.0", string.Empty) - .Should().Be("Release|Any CPU"); - projectConfigSection - .GetValue("Release|x64.ActiveCfg", string.Empty) - .Should().Be("Release|x64"); - projectConfigSection - .GetValue("Release|x64.Build.0", string.Empty) - .Should().Be("Release|x64"); - projectConfigSection - .GetValue("Release|x86.ActiveCfg", string.Empty) - .Should().Be("Release|x86"); - projectConfigSection - .GetValue("Release|x86.Build.0", string.Empty) - .Should().Be("Release|x86"); - projectConfigSection = slnFile - .ProjectConfigurationsSection - .GetPropertySet("{21D9159F-60E6-4F65-BC6B-D01B71B15FFC}"); - projectConfigSection.Count.Should().Be(12); - projectConfigSection - .GetValue("Debug|Any CPU.ActiveCfg", string.Empty) - .Should().Be("Debug|Any CPU"); - projectConfigSection - .GetValue("Debug|Any CPU.Build.0", string.Empty) - .Should().Be("Debug|Any CPU"); - projectConfigSection - .GetValue("Debug|x64.ActiveCfg", string.Empty) - .Should().Be("Debug|x64"); - projectConfigSection - .GetValue("Debug|x64.Build.0", string.Empty) - .Should().Be("Debug|x64"); - projectConfigSection - .GetValue("Debug|x86.ActiveCfg", string.Empty) - .Should().Be("Debug|x86"); - projectConfigSection - .GetValue("Debug|x86.Build.0", string.Empty) - .Should().Be("Debug|x86"); - projectConfigSection - .GetValue("Release|Any CPU.ActiveCfg", string.Empty) - .Should().Be("Release|Any CPU"); - projectConfigSection - .GetValue("Release|Any CPU.Build.0", string.Empty) - .Should().Be("Release|Any CPU"); - projectConfigSection - .GetValue("Release|x64.ActiveCfg", string.Empty) - .Should().Be("Release|x64"); - projectConfigSection - .GetValue("Release|x64.Build.0", string.Empty) - .Should().Be("Release|x64"); - projectConfigSection - .GetValue("Release|x86.ActiveCfg", string.Empty) - .Should().Be("Release|x86"); - projectConfigSection - .GetValue("Release|x86.Build.0", string.Empty) - .Should().Be("Release|x86"); - - slnFile.Sections.Count.Should().Be(3); - var solutionPropertiesSection = slnFile.Sections.GetSection("SolutionProperties"); - solutionPropertiesSection.Properties.Count.Should().Be(1); - solutionPropertiesSection.Properties - .GetValue("HideSolutionNode", string.Empty) - .Should().Be("FALSE"); - } - - [Fact] - public void WhenGivenAValidReadOnlySlnFileItReadsContentsWithNoException() - { - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionWithAppAndLibProjects); - var attr = File.GetAttributes(tmpFile); - attr = attr | FileAttributes.ReadOnly; - File.SetAttributes(tmpFile, attr); - - Action act = () => SlnFile.Read(tmpFile); - act.Should().NotThrow("Because readonly file is not being modified."); - } - - [Fact] - public void WhenGivenAValidSlnFileItModifiesSavesAndVerifiesContents() - { - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionWithAppAndLibProjects); - - SlnFile slnFile = SlnFile.Read(tmpFile); - - slnFile.FormatVersion = "14.00"; - slnFile.ProductDescription = "Visual Studio 16"; - slnFile.VisualStudioVersion = "16.0.26006.2"; - slnFile.MinimumVisualStudioVersion = "11.0.40219.1"; - - slnFile.Projects.Count.Should().Be(2); - var project = slnFile.Projects[0]; - project.Id = "{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"; - project.TypeGuid = "{7072A694-548F-4CAE-A58F-12D257D5F486}"; - project.Name = "AppModified"; - project.FilePath = Path.Combine("AppModified", "AppModified.csproj"); - slnFile.Projects.Remove(slnFile.Projects[1]); - - slnFile.SolutionConfigurationsSection.Count.Should().Be(6); - slnFile.SolutionConfigurationsSection.Remove("Release|Any CPU"); - slnFile.SolutionConfigurationsSection.Remove("Release|x64"); - slnFile.SolutionConfigurationsSection.Remove("Release|x86"); - - slnFile.ProjectConfigurationsSection.Count.Should().Be(2); - var projectConfigSection = slnFile - .ProjectConfigurationsSection - .GetPropertySet("{21D9159F-60E6-4F65-BC6B-D01B71B15FFC}"); - slnFile.ProjectConfigurationsSection.Remove(projectConfigSection); - - slnFile.Sections.Count.Should().Be(3); - var solutionPropertiesSection = slnFile.Sections.GetSection("SolutionProperties"); - solutionPropertiesSection.Properties.Count.Should().Be(1); - solutionPropertiesSection.Properties.SetValue("HideSolutionNode", "TRUE"); - - slnFile.Write(); - - File.ReadAllText(tmpFile) - .Should().Be(SolutionModified); - } - - [Theory] - [InlineData("Microsoft Visual Studio Solution File, Format Version ", 1)] - [InlineData("First Line\nMicrosoft Visual Studio Solution File, Format Version ", 2)] - [InlineData("First Line\nMicrosoft Visual Studio Solution File, Format Version \nThird Line", 2)] - [InlineData("First Line\nSecondLine\nMicrosoft Visual Studio Solution File, Format Version \nFourth Line", 3)] - public void WhenGivenASolutionWithMissingHeaderVersionItThrows(string fileContents, int lineNum) - { - var tmpFile = CreateFile(identifier: fileContents.GetHashCode().ToString()); - File.WriteAllText(tmpFile, fileContents); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(FormatError(lineNum, LocalizableStrings.FileHeaderMissingVersionError)); - } - - [Theory] - [InlineData("Invalid Solution")] - [InlineData("Invalid Solution\nSpanning Multiple Lines")] - [InlineData("Microsoft Visual\nStudio Solution File,\nFormat Version ")] - public void WhenGivenASolutionWithMissingHeaderItThrows(string fileContents) - { - var tmpFile = CreateFile(identifier: fileContents.GetHashCode().ToString()); - File.WriteAllText(tmpFile, fileContents); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(LocalizableStrings.FileHeaderMissingError); - } - - [Fact] - public void WhenGivenASolutionWithMultipleGlobalSectionsItThrows() - { - const string SolutionFile = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -Global -EndGlobal -Global -EndGlobal -"; - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionFile); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(FormatError(5, LocalizableStrings.GlobalSectionMoreThanOnceError)); - } - - [Fact] - public void WhenGivenASolutionWithGlobalSectionNotClosedItThrows() - { - const string SolutionFile = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -Global -"; - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionFile); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(FormatError(3, LocalizableStrings.GlobalSectionNotClosedError)); - } - - [Fact] - public void WhenGivenASolutionWithProjectSectionNotClosedItThrows() - { - const string SolutionFile = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""App"", ""App\App.csproj"", ""{7072A694-548F-4CAE-A58F-12D257D5F486}"" -"; - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionFile); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(FormatError(3, LocalizableStrings.ProjectSectionNotClosedError)); - } - - [Fact] - public void WhenGivenASolutionWithInvalidProjectSectionItThrows() - { - const string SolutionFile = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -Project""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""App"", ""App\App.csproj"", ""{7072A694-548F-4CAE-A58F-12D257D5F486}"" -EndProject -"; - - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionFile); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(FormatError(3, LocalizableStrings.ProjectParsingErrorFormatString, "(", 0)); - } - - [Fact] - public void WhenGivenASolutionWithInvalidSectionTypeItThrows() - { - const string SolutionFile = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -Global - GlobalSection(SolutionConfigurationPlatforms) = thisIsUnknown - EndGlobalSection -EndGlobal -"; - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionFile); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(FormatError(4, LocalizableStrings.InvalidSectionTypeError, "thisIsUnknown")); - } - - [Fact] - public void WhenGivenASolutionWithMissingSectionIdTypeItThrows() - { - const string SolutionFile = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -Global - GlobalSection = preSolution - EndGlobalSection -EndGlobal -"; - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionFile); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(FormatError(4, LocalizableStrings.SectionIdMissingError)); - } - - [Fact] - public void WhenGivenASolutionWithSectionNotClosedItThrows() - { - const string SolutionFile = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution -EndGlobal -"; - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionFile); - - Action action = () => - { - SlnFile.Read(tmpFile); - }; - - action.Should().Throw() - .WithMessage(FormatError(6, LocalizableStrings.ClosingSectionTagNotFoundError)); - } - - [Fact] - public void WhenGivenASolutionWithInvalidPropertySetItThrows() - { - const string SolutionFile = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -Project(""{7072A694-548F-4CAE-A58F-12D257D5F486}"") = ""AppModified"", ""AppModified\AppModified.csproj"", ""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"" -EndProject -Global - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7072A694-548F-4CAE-A58F-12D257D5F486} Debug|Any CPU ActiveCfg = Debug|Any CPU - EndGlobalSection -EndGlobal -"; - var tmpFile = CreateFile(); - File.WriteAllText(tmpFile, SolutionFile); - - Action action = () => - { - var slnFile = SlnFile.Read(tmpFile); - if (slnFile.ProjectConfigurationsSection.Count == 0) - { - // Need to force loading of nested property sets - } - }; - - action.Should().Throw() - .WithMessage(FormatError(7, LocalizableStrings.InvalidPropertySetFormatString, ".")); - } - - private static string FormatError(int line, string format, params object[] args) - { - return string.Format( - LocalizableStrings.ErrorMessageFormatString, - line, - string.Format(format, args)); - } - } -} diff --git a/test/Microsoft.DotNet.Cli.Sln.Internal.Tests/Microsoft.DotNet.Cli.Sln.Internal.Tests.csproj b/test/Microsoft.DotNet.Cli.Sln.Internal.Tests/Microsoft.DotNet.Cli.Sln.Internal.Tests.csproj deleted file mode 100644 index 1c9566e18687..000000000000 --- a/test/Microsoft.DotNet.Cli.Sln.Internal.Tests/Microsoft.DotNet.Cli.Sln.Internal.Tests.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - Tests\$(MSBuildProjectName) - - - - - - $(ToolsetTargetFramework) - Exe - MicrosoftAspNetCore - - - - - - - - - - diff --git a/test/Msbuild.Tests.Utilities/Msbuild.Tests.Utilities.csproj b/test/Msbuild.Tests.Utilities/Msbuild.Tests.Utilities.csproj index 94c82028582a..8ec880dcddaf 100644 --- a/test/Msbuild.Tests.Utilities/Msbuild.Tests.Utilities.csproj +++ b/test/Msbuild.Tests.Utilities/Msbuild.Tests.Utilities.csproj @@ -9,7 +9,6 @@ - diff --git a/test/dotnet-list-package.Tests/GivenDotnetListPackage.cs b/test/dotnet-list-package.Tests/GivenDotnetListPackage.cs index bddc1d21aaff..46eaed94b8eb 100644 --- a/test/dotnet-list-package.Tests/GivenDotnetListPackage.cs +++ b/test/dotnet-list-package.Tests/GivenDotnetListPackage.cs @@ -117,6 +117,7 @@ public void ItRunOnSolution() .And.NotHaveStdErr(); new ListPackageCommand(Log) + .WithProject("App.sln") .WithWorkingDirectory(projectDirectory) .Execute() .Should() diff --git a/test/dotnet-sln.Tests/GivenDotnetSlnAdd.cs b/test/dotnet-sln.Tests/GivenDotnetSlnAdd.cs index 42061903efaa..0231bd518eaf 100644 --- a/test/dotnet-sln.Tests/GivenDotnetSlnAdd.cs +++ b/test/dotnet-sln.Tests/GivenDotnetSlnAdd.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.DotNet.Cli.Sln.Internal; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Tools; using Microsoft.DotNet.Tools.Common; @@ -12,6 +11,15 @@ namespace Microsoft.DotNet.Cli.Sln.Add.Tests { + public static class ProjectTypeGuids + { + public const string CSharpProjectTypeGuid = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"; + public const string FSharpProjectTypeGuid = "{F2A71F9B-5D33-465A-A702-920D77279786}"; + public const string VBProjectTypeGuid = "{F184B08F-C81C-45F6-A57F-5ABD9991F28F}"; + public const string SolutionFolderGuid = "{2150E333-8FDC-42A3-9474-1A3956D46DE8}"; + public const string SharedProjectGuid = "{D954291E-2A0B-460D-934E-DC6B0785DB48}"; + } + public class GivenDotnetSlnAdd : SdkTest { private Func HelpText = (defaultVal) => $@"Description: diff --git a/test/dotnet-sln.Tests/GivenDotnetSlnList.cs b/test/dotnet-sln.Tests/GivenDotnetSlnList.cs index f462ff1e6042..7cd5200208bd 100644 --- a/test/dotnet-sln.Tests/GivenDotnetSlnList.cs +++ b/test/dotnet-sln.Tests/GivenDotnetSlnList.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.DotNet.Cli.Sln.Internal; using Microsoft.DotNet.Tools; using Microsoft.DotNet.Tools.Common; using CommandLocalizableStrings = Microsoft.DotNet.Tools.Sln.LocalizableStrings; diff --git a/test/dotnet-sln.Tests/GivenDotnetSlnMigrate.cs b/test/dotnet-sln.Tests/GivenDotnetSlnMigrate.cs index 7af7267a2997..f18ac2d7fba5 100644 --- a/test/dotnet-sln.Tests/GivenDotnetSlnMigrate.cs +++ b/test/dotnet-sln.Tests/GivenDotnetSlnMigrate.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.DotNet.Cli.Sln.Internal; using Microsoft.DotNet.Tools; using Microsoft.DotNet.Tools.Common; using CommandLocalizableStrings = Microsoft.DotNet.Tools.Sln.LocalizableStrings; diff --git a/test/dotnet-sln.Tests/dotnet-sln.Tests.csproj b/test/dotnet-sln.Tests/dotnet-sln.Tests.csproj index ad45aa7b7e6c..8b9e3844a891 100644 --- a/test/dotnet-sln.Tests/dotnet-sln.Tests.csproj +++ b/test/dotnet-sln.Tests/dotnet-sln.Tests.csproj @@ -12,7 +12,6 @@ - diff --git a/test/dotnet.Tests/dotnet.Tests.csproj b/test/dotnet.Tests/dotnet.Tests.csproj index 4bb8bfdc1df5..75da805f7e39 100644 --- a/test/dotnet.Tests/dotnet.Tests.csproj +++ b/test/dotnet.Tests/dotnet.Tests.csproj @@ -110,7 +110,6 @@ -