diff --git a/TestAssets/NonRestoredTestProjects/PJAppWithSlnAndXprojRefs/TestApp/TestApp.sln b/TestAssets/NonRestoredTestProjects/PJAppWithSlnAndXprojRefs/TestApp/TestApp.sln
index bc8214876..3dc27a305 100644
--- a/TestAssets/NonRestoredTestProjects/PJAppWithSlnAndXprojRefs/TestApp/TestApp.sln
+++ b/TestAssets/NonRestoredTestProjects/PJAppWithSlnAndXprojRefs/TestApp/TestApp.sln
@@ -17,12 +17,16 @@ Global
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|Any CPU.Build.0 = Release|Any CPU
{DC0B35D0-8A36-4B52-8A11-B86739F055D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DC0B35D0-8A36-4B52-8A11-B86739F055D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|Any CPU.Build.0 = Release|Any CPU
{DC0B35D0-8A36-4B52-8A11-B86739F055D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DC0B35D0-8A36-4B52-8A11-B86739F055D2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F8F96F4A-F10C-4C54-867C-A9EFF55494C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F8F96F4A-F10C-4C54-867C-A9EFF55494C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F8F96F4A-F10C-4C54-867C-A9EFF55494C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F8F96F4A-F10C-4C54-867C-A9EFF55494C8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/TestAssets/NonRestoredTestProjects/PJAppWithSlnAndXprojRefsAndUnrelatedCsproj/TestApp/TestApp.sln b/TestAssets/NonRestoredTestProjects/PJAppWithSlnAndXprojRefsAndUnrelatedCsproj/TestApp/TestApp.sln
index bc8214876..3dc27a305 100644
--- a/TestAssets/NonRestoredTestProjects/PJAppWithSlnAndXprojRefsAndUnrelatedCsproj/TestApp/TestApp.sln
+++ b/TestAssets/NonRestoredTestProjects/PJAppWithSlnAndXprojRefsAndUnrelatedCsproj/TestApp/TestApp.sln
@@ -17,12 +17,16 @@ Global
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|Any CPU.Build.0 = Release|Any CPU
{DC0B35D0-8A36-4B52-8A11-B86739F055D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DC0B35D0-8A36-4B52-8A11-B86739F055D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|Any CPU.Build.0 = Release|Any CPU
{DC0B35D0-8A36-4B52-8A11-B86739F055D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DC0B35D0-8A36-4B52-8A11-B86739F055D2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F8F96F4A-F10C-4C54-867C-A9EFF55494C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F8F96F4A-F10C-4C54-867C-A9EFF55494C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F8F96F4A-F10C-4C54-867C-A9EFF55494C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F8F96F4A-F10C-4C54-867C-A9EFF55494C8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/TestAssets/TestProjects/SlnFileWithNoProjectReferences/SlnFileWithNoProjectReferences.sln b/TestAssets/TestProjects/SlnFileWithNoProjectReferences/SlnFileWithNoProjectReferences.sln
deleted file mode 100644
index 5b61df887..000000000
--- a/TestAssets/TestProjects/SlnFileWithNoProjectReferences/SlnFileWithNoProjectReferences.sln
+++ /dev/null
@@ -1,18 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.26006.2
-MinimumVisualStudioVersion = 10.0.40219.1
-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(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/TestAssets/TestProjects/TestAppWithEmptySln/App.sln b/TestAssets/TestProjects/TestAppWithEmptySln/App.sln
new file mode 100644
index 000000000..8eca25366
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithEmptySln/App.sln
@@ -0,0 +1,5 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26006.2
+MinimumVisualStudioVersion = 10.0.40219.1
diff --git a/TestAssets/TestProjects/TestAppWithEmptySln/App/App.csproj b/TestAssets/TestProjects/TestAppWithEmptySln/App/App.csproj
new file mode 100644
index 000000000..423ceb827
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithEmptySln/App/App.csproj
@@ -0,0 +1,19 @@
+
+
+ Exe
+ netcoreapp1.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TestAssets/TestProjects/TestAppWithEmptySln/App/Program.cs b/TestAssets/TestProjects/TestAppWithEmptySln/App/Program.cs
new file mode 100644
index 000000000..abb853a4a
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithEmptySln/App/Program.cs
@@ -0,0 +1,10 @@
+using System;
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Hello from the main app");
+ Console.WriteLine(Lib.Library.GetMessage());
+ }
+}
diff --git a/TestAssets/TestProjects/TestAppWithEmptySln/Lib/Lib.csproj b/TestAssets/TestProjects/TestAppWithEmptySln/Lib/Lib.csproj
new file mode 100644
index 000000000..f47b49f65
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithEmptySln/Lib/Lib.csproj
@@ -0,0 +1,15 @@
+
+
+
+ netstandard1.4
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TestAssets/TestProjects/TestAppWithEmptySln/Lib/Library.cs b/TestAssets/TestProjects/TestAppWithEmptySln/Lib/Library.cs
new file mode 100644
index 000000000..205c42a01
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithEmptySln/Lib/Library.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Lib
+{
+ public class Library
+ {
+ public static string GetMessage()
+ {
+ return "Message from Lib";
+ }
+ }
+}
diff --git a/TestAssets/TestProjects/TestAppWithSlnAndCsprojToRemove/App.sln b/TestAssets/TestProjects/TestAppWithSlnAndCsprojToRemove/App.sln
new file mode 100644
index 000000000..6af5ab783
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithSlnAndCsprojToRemove/App.sln
@@ -0,0 +1,45 @@
+
+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
+EndGlobal
diff --git a/TestAssets/TestProjects/TestAppWithSlnAndCsprojToRemove/App/App.csproj b/TestAssets/TestProjects/TestAppWithSlnAndCsprojToRemove/App/App.csproj
new file mode 100644
index 000000000..c1313e358
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithSlnAndCsprojToRemove/App/App.csproj
@@ -0,0 +1,15 @@
+
+
+ Exe
+ netcoreapp1.0
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TestAssets/TestProjects/TestAppWithSlnAndCsprojToRemove/App/Program.cs b/TestAssets/TestProjects/TestAppWithSlnAndCsprojToRemove/App/Program.cs
new file mode 100644
index 000000000..acdf5839d
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithSlnAndCsprojToRemove/App/Program.cs
@@ -0,0 +1,9 @@
+using System;
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Hello from the main app");
+ }
+}
diff --git a/TestAssets/TestProjects/TestAppWithSlnAndCsprojToRemove/Lib/Lib.csproj b/TestAssets/TestProjects/TestAppWithSlnAndCsprojToRemove/Lib/Lib.csproj
new file mode 100644
index 000000000..f47b49f65
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithSlnAndCsprojToRemove/Lib/Lib.csproj
@@ -0,0 +1,15 @@
+
+
+
+ netstandard1.4
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TestAssets/TestProjects/TestAppWithSlnAndCsprojToRemove/Lib/Library.cs b/TestAssets/TestProjects/TestAppWithSlnAndCsprojToRemove/Lib/Library.cs
new file mode 100644
index 000000000..205c42a01
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithSlnAndCsprojToRemove/Lib/Library.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Lib
+{
+ public class Library
+ {
+ public static string GetMessage()
+ {
+ return "Message from Lib";
+ }
+ }
+}
diff --git a/build/Microsoft.DotNet.Cli.DependencyVersions.props b/build/Microsoft.DotNet.Cli.DependencyVersions.props
index b16c3e15c..b5f1c45df 100644
--- a/build/Microsoft.DotNet.Cli.DependencyVersions.props
+++ b/build/Microsoft.DotNet.Cli.DependencyVersions.props
@@ -2,7 +2,7 @@
15.1.0-preview-000458-02
- 1.0.0-alpha-20161221-2
+ 1.0.0-alpha-20161230-1
1.0.0-alpha-20161205-1-154
15.0.0-preview-20161227-02
diff --git a/src/dotnet/commands/dotnet-add/dotnet-add-proj/Program.cs b/src/dotnet/commands/dotnet-add/dotnet-add-proj/Program.cs
index c29c871d8..858bc2a90 100644
--- a/src/dotnet/commands/dotnet-add/dotnet-add-proj/Program.cs
+++ b/src/dotnet/commands/dotnet-add/dotnet-add-proj/Program.cs
@@ -8,6 +8,7 @@ using Microsoft.DotNet.Cli.Sln.Internal;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Common;
using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -103,10 +104,69 @@ namespace Microsoft.DotNet.Tools.Add.ProjectToSolution
FilePath = projectPathNormalized
};
+ AddDefaultBuildConfigurations(slnFile, slnProject);
+
slnFile.Projects.Add(slnProject);
+
Reporter.Output.WriteLine(
string.Format(CommonLocalizableStrings.ProjectAddedToTheSolution, projectPath));
}
}
+
+ private void AddDefaultBuildConfigurations(SlnFile slnFile, SlnProject slnProject)
+ {
+ var defaultConfigurations = new List()
+ {
+ "Debug|Any CPU",
+ "Debug|x64",
+ "Debug|x86",
+ "Release|Any CPU",
+ "Release|x64",
+ "Release|x86",
+ };
+
+ // 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.
+ AddDefaultSolutionConfigurations(defaultConfigurations, slnFile.SolutionConfigurationsSection);
+ AddDefaultProjectConfigurations(
+ defaultConfigurations,
+ slnFile.ProjectConfigurationsSection.GetOrCreatePropertySet(slnProject.Id));
+ }
+
+ private void AddDefaultSolutionConfigurations(
+ List defaultConfigurations,
+ SlnPropertySet solutionConfigs)
+ {
+ foreach (var config in defaultConfigurations)
+ {
+ if (!solutionConfigs.ContainsKey(config))
+ {
+ solutionConfigs[config] = config;
+ }
+ }
+ }
+
+ private void AddDefaultProjectConfigurations(
+ List defaultConfigurations,
+ SlnPropertySet projectConfigs)
+ {
+ foreach (var config in defaultConfigurations)
+ {
+ var activeCfgKey = $"{config}.ActiveCfg";
+ if (!projectConfigs.ContainsKey(activeCfgKey))
+ {
+ projectConfigs[activeCfgKey] = config;
+ }
+
+ var build0Key = $"{config}.Build.0";
+ if (!projectConfigs.ContainsKey(build0Key))
+ {
+ projectConfigs[build0Key] = config;
+ }
+ }
+ }
}
}
diff --git a/src/dotnet/commands/dotnet-remove/dotnet-remove-proj/Program.cs b/src/dotnet/commands/dotnet-remove/dotnet-remove-proj/Program.cs
index be386d7af..719c585a8 100644
--- a/src/dotnet/commands/dotnet-remove/dotnet-remove-proj/Program.cs
+++ b/src/dotnet/commands/dotnet-remove/dotnet-remove-proj/Program.cs
@@ -49,6 +49,8 @@ namespace Microsoft.DotNet.Tools.Remove.ProjectFromSolution
slnChanged |= RemoveProject(slnFile, path);
}
+ RemoveEmptyConfigurationSections(slnFile);
+
if (slnChanged)
{
slnFile.Write();
@@ -75,6 +77,11 @@ namespace Microsoft.DotNet.Tools.Remove.ProjectFromSolution
{
foreach (var slnProject in projectsToRemove)
{
+ var buildConfigsToRemove = slnFile.ProjectConfigurationsSection.GetPropertySet(slnProject.Id);
+ if (buildConfigsToRemove != null)
+ {
+ slnFile.ProjectConfigurationsSection.Remove(buildConfigsToRemove);
+ }
slnFile.Projects.Remove(slnProject);
Reporter.Output.WriteLine(
string.Format(CommonLocalizableStrings.ProjectReferenceRemoved, slnProject.FilePath));
@@ -85,5 +92,23 @@ namespace Microsoft.DotNet.Tools.Remove.ProjectFromSolution
return projectRemoved;
}
+
+ private void RemoveEmptyConfigurationSections(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);
+ }
+ }
+ }
}
}
diff --git a/test/dotnet-add-proj.Tests/GivenDotnetAddProj.cs b/test/dotnet-add-proj.Tests/GivenDotnetAddProj.cs
index 7ea309909..ce804eaf8 100644
--- a/test/dotnet-add-proj.Tests/GivenDotnetAddProj.cs
+++ b/test/dotnet-add-proj.Tests/GivenDotnetAddProj.cs
@@ -28,6 +28,89 @@ Additional Arguments:
Projects to add to solution
";
+ private const string ExpectedSlnFileAfterAddingLibProj = @"
+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"", ""__PROJECTGUID__""
+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
+ __PROJECTGUID__.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ __PROJECTGUID__.Debug|Any CPU.Build.0 = Debug|Any CPU
+ __PROJECTGUID__.Debug|x64.ActiveCfg = Debug|x64
+ __PROJECTGUID__.Debug|x64.Build.0 = Debug|x64
+ __PROJECTGUID__.Debug|x86.ActiveCfg = Debug|x86
+ __PROJECTGUID__.Debug|x86.Build.0 = Debug|x86
+ __PROJECTGUID__.Release|Any CPU.ActiveCfg = Release|Any CPU
+ __PROJECTGUID__.Release|Any CPU.Build.0 = Release|Any CPU
+ __PROJECTGUID__.Release|x64.ActiveCfg = Release|x64
+ __PROJECTGUID__.Release|x64.Build.0 = Release|x64
+ __PROJECTGUID__.Release|x86.ActiveCfg = Release|x86
+ __PROJECTGUID__.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
+";
+
+ private const string ExpectedSlnFileAfterAddingLibProjToEmptySln = @"
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26006.2
+MinimumVisualStudioVersion = 10.0.40219.1
+Project(""{13B669BE-BB05-4DDF-9536-439F39A36129}"") = ""Lib"", ""Lib\Lib.csproj"", ""__PROJECTGUID__""
+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
+ __PROJECTGUID__.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ __PROJECTGUID__.Debug|Any CPU.Build.0 = Debug|Any CPU
+ __PROJECTGUID__.Debug|x64.ActiveCfg = Debug|x64
+ __PROJECTGUID__.Debug|x64.Build.0 = Debug|x64
+ __PROJECTGUID__.Debug|x86.ActiveCfg = Debug|x86
+ __PROJECTGUID__.Debug|x86.Build.0 = Debug|x86
+ __PROJECTGUID__.Release|Any CPU.ActiveCfg = Release|Any CPU
+ __PROJECTGUID__.Release|Any CPU.Build.0 = Release|Any CPU
+ __PROJECTGUID__.Release|x64.ActiveCfg = Release|x64
+ __PROJECTGUID__.Release|x64.Build.0 = Release|x64
+ __PROJECTGUID__.Release|x86.ActiveCfg = Release|x86
+ __PROJECTGUID__.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+EndGlobal
+";
+
[Theory]
[InlineData("--help")]
[InlineData("-h")]
@@ -171,11 +254,51 @@ Additional Arguments:
}
[Theory]
- [InlineData("TestAppWithSlnAndCsprojFiles", "")]
- [InlineData("TestAppWithSlnAndCsprojProjectGuidFiles", "{84A45D44-B677-492D-A6DA-B3A71135AB8E}")]
- public void WhenValidProjectIsPassedItGetsNormalizedAndAddedAndSlnBuilds(
+ [InlineData("TestAppWithSlnAndCsprojFiles", ExpectedSlnFileAfterAddingLibProj, "")]
+ [InlineData("TestAppWithSlnAndCsprojProjectGuidFiles", ExpectedSlnFileAfterAddingLibProj, "{84A45D44-B677-492D-A6DA-B3A71135AB8E}")]
+ [InlineData("TestAppWithEmptySln", ExpectedSlnFileAfterAddingLibProjToEmptySln, "")]
+ public void WhenValidProjectIsPassedBuildConfigsAreAdded(
string testAsset,
- string projectGuid)
+ string expectedSlnContentsTemplate,
+ string expectedProjectGuid)
+ {
+ var projectDirectory = TestAssets
+ .Get(testAsset)
+ .CreateInstance()
+ .WithSourceFiles()
+ .Root
+ .FullName;
+
+ var projectToAdd = "Lib/Lib.csproj";
+ var cmd = new DotnetCommand()
+ .WithWorkingDirectory(projectDirectory)
+ .ExecuteWithCapturedOutput($"add App.sln project {projectToAdd}");
+ cmd.Should().Pass();
+
+ var slnPath = Path.Combine(projectDirectory, "App.sln");
+
+ if (string.IsNullOrEmpty(expectedProjectGuid))
+ {
+ var slnFile = SlnFile.Read(slnPath);
+ var matchingProjects = slnFile.Projects
+ .Where((p) => p.Name == "Lib")
+ .ToList();
+
+ matchingProjects.Count.Should().Be(1);
+ var slnProject = matchingProjects[0];
+ expectedProjectGuid = slnProject.Id;
+ }
+
+ var expectedSlnContents = expectedSlnContentsTemplate.Replace("__PROJECTGUID__", expectedProjectGuid);
+ File.ReadAllText(slnPath)
+ .Should().BeVisuallyEquivalentTo(expectedSlnContents);
+ }
+
+ [Theory]
+ [InlineData("TestAppWithSlnAndCsprojFiles")]
+ [InlineData("TestAppWithSlnAndCsprojProjectGuidFiles")]
+ [InlineData("TestAppWithEmptySln")]
+ public void WhenValidProjectIsPassedItGetsAdded(string testAsset)
{
var projectDirectory = TestAssets
.Get(testAsset)
@@ -192,29 +315,56 @@ Additional Arguments:
cmd.Should().Pass();
cmd.StdOut.Should().Be($"Project `{projectPath}` added to the solution.");
cmd.StdErr.Should().BeEmpty();
+ }
- var slnFile = SlnFile.Read(Path.Combine(projectDirectory, "App.sln"));
- var matchingProjects = slnFile.Projects
- .Where((p) => p.Name == "Lib")
- .ToList();
+ //ISSUE: https://github.com/dotnet/sdk/issues/545
+ //[Theory]
+ //[InlineData("TestAppWithSlnAndCsprojFiles")]
+ //[InlineData("TestAppWithSlnAndCsprojProjectGuidFiles")]
+ //[InlineData("TestAppWithEmptySln")]
+ public void WhenValidProjectIsPassedTheSlnBuilds(string testAsset)
+ {
+ var projectDirectory = TestAssets
+ .Get(testAsset)
+ .CreateInstance()
+ .WithSourceFiles()
+ .Root
+ .FullName;
- matchingProjects.Count.Should().Be(1);
- var slnProject = matchingProjects[0];
- slnProject.FilePath.Should().Be(projectPath);
- slnProject.TypeGuid.Should().Be(ProjectTypeGuids.CPSProjectTypeGuid);
- if (!string.IsNullOrEmpty(projectGuid))
- {
- slnProject.Id.Should().Be(projectGuid);
- }
-
- var restoreCmd = new DotnetCommand()
+ var cmd = new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
- .Execute($"restore {Path.Combine("App", "App.csproj")}");
+ .ExecuteWithCapturedOutput(@"add App.sln project App/App.csproj Lib/Lib.csproj");
+ cmd.Should().Pass();
- var buildCmd = new DotnetCommand()
+ var slnPath = Path.Combine(projectDirectory, "App.sln");
+
+ new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
- .Execute("build App.sln");
- buildCmd.Should().Pass();
+ .Execute($"restore App.sln")
+ .Should().Pass();
+
+ new DotnetCommand()
+ .WithWorkingDirectory(projectDirectory)
+ .Execute("build App.sln --configuration Release")
+ .Should().Pass();
+
+ var reasonString = "should be built in release mode, otherwise it means build configurations are missing from the sln file";
+
+ var appReleaseDirectory = Directory.EnumerateDirectories(
+ Path.Combine(projectDirectory, "App", "bin"),
+ "Release",
+ SearchOption.AllDirectories);
+ appReleaseDirectory.Count().Should().Be(1, $"App {reasonString}");
+ Directory.EnumerateFiles(appReleaseDirectory.Single(), "App.dll", SearchOption.AllDirectories)
+ .Count().Should().Be(1, $"App {reasonString}");
+
+ var libReleaseDirectory = Directory.EnumerateDirectories(
+ Path.Combine(projectDirectory, "Lib", "bin"),
+ "Release",
+ SearchOption.AllDirectories);
+ libReleaseDirectory.Count().Should().Be(1, $"Lib {reasonString}");
+ Directory.EnumerateFiles(libReleaseDirectory.Single(), "Lib.dll", SearchOption.AllDirectories)
+ .Count().Should().Be(1, $"Lib {reasonString}");
}
[Fact]
@@ -258,7 +408,7 @@ Additional Arguments:
cmd.StdErr.Should().Be("Project `idonotexist.csproj` does not exist.");
File.ReadAllText(slnFullPath)
- .Should().BeEquivalentTo(contentBefore);
+ .Should().BeVisuallyEquivalentTo(contentBefore);
}
}
}
diff --git a/test/dotnet-list-proj.Tests/GivenDotnetListProj.cs b/test/dotnet-list-proj.Tests/GivenDotnetListProj.cs
index 877450467..26e3a316b 100644
--- a/test/dotnet-list-proj.Tests/GivenDotnetListProj.cs
+++ b/test/dotnet-list-proj.Tests/GivenDotnetListProj.cs
@@ -147,7 +147,7 @@ Options:
public void WhenNoProjectReferencesArePresentInTheSolutionItPrintsANoProjectMessage()
{
var projectDirectory = TestAssets
- .Get("SlnFileWithNoProjectReferences")
+ .Get("TestAppWithEmptySln")
.CreateInstance()
.WithSourceFiles()
.Root
diff --git a/test/dotnet-migrate.Tests/GivenThatIWantToMigrateSolutions.cs b/test/dotnet-migrate.Tests/GivenThatIWantToMigrateSolutions.cs
index a73b1b61c..37620c979 100644
--- a/test/dotnet-migrate.Tests/GivenThatIWantToMigrateSolutions.cs
+++ b/test/dotnet-migrate.Tests/GivenThatIWantToMigrateSolutions.cs
@@ -57,7 +57,7 @@ namespace Microsoft.DotNet.Migration.Tests
new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
- .Execute($"restore \"{Path.Combine("TestApp", "TestApp.csproj")}\"")
+ .Execute($"restore \"{solutionRelPath}\"")
.Should().Pass();
//ISSUE: https://github.com/dotnet/sdk/issues/545
diff --git a/test/dotnet-remove-proj.Tests/GivenDotnetRemoveProj.cs b/test/dotnet-remove-proj.Tests/GivenDotnetRemoveProj.cs
index c9da242d2..208d5df58 100644
--- a/test/dotnet-remove-proj.Tests/GivenDotnetRemoveProj.cs
+++ b/test/dotnet-remove-proj.Tests/GivenDotnetRemoveProj.cs
@@ -6,6 +6,7 @@ using Microsoft.DotNet.Cli.Sln.Internal;
using Microsoft.DotNet.Tools.Test.Utilities;
using System;
using System.IO;
+using System.Linq;
using Xunit;
namespace Microsoft.DotNet.Cli.Remove.Project.Tests
@@ -26,6 +27,48 @@ Additional Arguments:
Projects to remove from a solution
";
+ private const string ExpectedSlnContentsAfterRemove = @"
+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
+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
+ EndGlobalSection
+EndGlobal
+";
+
+ private const string ExpectedSlnContentsAfterRemoveAllProjects = @"
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26006.2
+MinimumVisualStudioVersion = 10.0.40219.1
+Global
+EndGlobal
+";
+
[Theory]
[InlineData("--help")]
[InlineData("-h")]
@@ -186,7 +229,7 @@ Additional Arguments:
cmd.Should().Pass();
cmd.StdOut.Should().Be("Project reference `referenceDoesNotExistInSln.csproj` could not be found.");
File.ReadAllText(solutionPath)
- .Should().Be(contentBefore);
+ .Should().BeVisuallyEquivalentTo(contentBefore);
}
[Fact]
@@ -273,5 +316,97 @@ Project reference `idontexisteither.csproj` could not be found.";
slnFile.Projects.Count.Should().Be(1);
slnFile.Projects[0].FilePath.Should().Be(Path.Combine("App", "App.csproj"));
}
+
+ [Fact]
+ public void WhenReferenceIsRemovedBuildConfigsAreAlsoRemoved()
+ {
+ var projectDirectory = TestAssets
+ .Get("TestAppWithSlnAndCsprojToRemove")
+ .CreateInstance()
+ .WithSourceFiles()
+ .Root
+ .FullName;
+
+ var solutionPath = Path.Combine(projectDirectory, "App.sln");
+ SlnFile slnFile = SlnFile.Read(solutionPath);
+ slnFile.Projects.Count.Should().Be(2);
+
+ var projectToRemove = Path.Combine("Lib", "Lib.csproj");
+ var cmd = new DotnetCommand()
+ .WithWorkingDirectory(projectDirectory)
+ .ExecuteWithCapturedOutput($"remove project {projectToRemove}");
+ cmd.Should().Pass();
+
+ File.ReadAllText(solutionPath)
+ .Should().BeVisuallyEquivalentTo(ExpectedSlnContentsAfterRemove);
+ }
+
+ //ISSUE: https://github.com/dotnet/sdk/issues/545
+ //[Fact]
+ public void WhenReferenceIsRemovedSlnBuilds()
+ {
+ var projectDirectory = TestAssets
+ .Get("TestAppWithSlnAndCsprojToRemove")
+ .CreateInstance()
+ .WithSourceFiles()
+ .Root
+ .FullName;
+
+ var solutionPath = Path.Combine(projectDirectory, "App.sln");
+ SlnFile slnFile = SlnFile.Read(solutionPath);
+ slnFile.Projects.Count.Should().Be(2);
+
+ var projectToRemove = Path.Combine("Lib", "Lib.csproj");
+ var cmd = new DotnetCommand()
+ .WithWorkingDirectory(projectDirectory)
+ .ExecuteWithCapturedOutput($"remove project {projectToRemove}");
+ cmd.Should().Pass();
+
+ new DotnetCommand()
+ .WithWorkingDirectory(projectDirectory)
+ .Execute($"restore App.sln")
+ .Should().Pass();
+
+ new DotnetCommand()
+ .WithWorkingDirectory(projectDirectory)
+ .Execute("build App.sln --configuration Release")
+ .Should().Pass();
+
+ var reasonString = "should be built in release mode, otherwise it means build configurations are missing from the sln file";
+
+ var releaseDirectory = Directory.EnumerateDirectories(
+ Path.Combine(projectDirectory, "App", "bin"),
+ "Release",
+ SearchOption.AllDirectories);
+ releaseDirectory.Count().Should().Be(1, $"App {reasonString}");
+ Directory.EnumerateFiles(releaseDirectory.Single(), "App.dll", SearchOption.AllDirectories)
+ .Count().Should().Be(1, $"App {reasonString}");
+ }
+
+ [Fact]
+ public void WhenFinalReferenceIsRemovedEmptySectionsAreRemoved()
+ {
+ var projectDirectory = TestAssets
+ .Get("TestAppWithSlnAndCsprojToRemove")
+ .CreateInstance()
+ .WithSourceFiles()
+ .Root
+ .FullName;
+
+ var solutionPath = Path.Combine(projectDirectory, "App.sln");
+ SlnFile slnFile = SlnFile.Read(solutionPath);
+ slnFile.Projects.Count.Should().Be(2);
+
+ var appPath = Path.Combine("App", "App.csproj");
+ var libPath = Path.Combine("Lib", "Lib.csproj");
+ var projectsToRemove = $"{libPath} {appPath}";
+ var cmd = new DotnetCommand()
+ .WithWorkingDirectory(projectDirectory)
+ .ExecuteWithCapturedOutput($"remove project {projectsToRemove}");
+ cmd.Should().Pass();
+
+ File.ReadAllText(solutionPath)
+ .Should().BeVisuallyEquivalentTo(ExpectedSlnContentsAfterRemoveAllProjects);
+ }
}
}