Merge pull request #8285 from peterhuene/sln-add-map-project-configurations

Map solution configurations to existing project configurations on add.
This commit is contained in:
Peter Huene 2018-01-08 14:18:42 -08:00 committed by GitHub
commit 28d929a6d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 440 additions and 65 deletions

View file

@ -0,0 +1,21 @@

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
Foo Bar|Any CPU = Foo Bar|Any CPU
Foo Bar|x64 = Foo Bar|x64
Foo Bar|x86 = Foo Bar|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,15 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace ProjectWithAdditionalConfigs
{
public static class Library
{
public static string GetMessage()
{
return "Hello World!";
}
}
}

View file

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<ProjectGuid>{A302325B-D680-4C0E-8680-7AE283981624}</ProjectGuid>
<Platforms>AnyCPU;x64;x86;AdditionalPlatform</Platforms>
<Configurations>Debug;Release;FooBar;AdditionalConfiguration</Configurations>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,15 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace ProjectWithMatchingConfigs
{
public static class Library
{
public static string GetMessage()
{
return "Hello World!";
}
}
}

View file

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<ProjectGuid>{C9601CA2-DB64-4FB6-B463-368C7764BF0D}</ProjectGuid>
<Platforms>AnyCPU;x64;x86</Platforms>
<Configurations>Debug;Release;FooBar</Configurations>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,15 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace ProjectWithoutMatchingConfigs
{
public static class Library
{
public static string GetMessage()
{
return "Hello World!";
}
}
}

View file

@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<ProjectGuid>{C49B64DE-4401-4825-8A88-10DCB5950E57}</ProjectGuid>
</PropertyGroup>
</Project>

View file

@ -14,7 +14,7 @@ done
REPO_ROOT="$( cd -P "$( dirname "$SOURCE" )/../" && pwd )"
uname=$(uname)
if [ "$(uname)" == "Darwin" ]
if [ "$(uname)" = "Darwin" ]
then
RID=osx.10.13-x64
else

View file

@ -4,6 +4,7 @@
using Microsoft.Build.Execution;
using Microsoft.DotNet.Cli.Sln.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.DotNet.Tools.Common
@ -45,5 +46,25 @@ namespace Microsoft.DotNet.Tools.Common
return projectTypeGuid;
}
public static IEnumerable<string> GetPlatforms(this ProjectInstance projectInstance)
{
return (projectInstance.GetPropertyValue("Platforms") ?? "")
.Split(
new char[] { ';' },
StringSplitOptions.RemoveEmptyEntries)
.Where(p => !string.IsNullOrWhiteSpace(p))
.DefaultIfEmpty("AnyCPU");
}
public static IEnumerable<string> GetConfigurations(this ProjectInstance projectInstance)
{
return (projectInstance.GetPropertyValue("Configurations") ?? "Debug;Release")
.Split(
new char[] { ';' },
StringSplitOptions.RemoveEmptyEntries)
.Where(c => !string.IsNullOrWhiteSpace(c))
.DefaultIfEmpty("Debug");
}
}
}

View file

@ -59,7 +59,16 @@ namespace Microsoft.DotNet.Tools.Common
FilePath = relativeProjectPath
};
slnFile.AddDefaultBuildConfigurations(slnProject);
// 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.
slnFile.AddDefaultBuildConfigurations();
slnFile.MapSolutionConfigurationsToProject(
projectInstance,
slnFile.ProjectConfigurationsSection.GetOrCreatePropertySet(slnProject.Id));
slnFile.AddSolutionFolders(slnProject);
@ -70,11 +79,13 @@ namespace Microsoft.DotNet.Tools.Common
}
}
public static void AddDefaultBuildConfigurations(this SlnFile slnFile, SlnProject slnProject)
private static void AddDefaultBuildConfigurations(this SlnFile slnFile)
{
if (slnProject == null)
var configurationsSection = slnFile.SolutionConfigurationsSection;
if (!configurationsSection.IsEmpty)
{
throw new ArgumentException();
return;
}
var defaultConfigurations = new List<string>()
@ -87,57 +98,108 @@ namespace Microsoft.DotNet.Tools.Common
"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 static void AddDefaultSolutionConfigurations(
List<string> defaultConfigurations,
SlnPropertySet solutionConfigs)
{
foreach (var config in defaultConfigurations)
{
if (!solutionConfigs.ContainsKey(config))
configurationsSection[config] = config;
}
}
private static void MapSolutionConfigurationsToProject(
this SlnFile slnFile,
ProjectInstance projectInstance,
SlnPropertySet solutionProjectConfigs)
{
solutionConfigs[config] = config;
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 void AddDefaultProjectConfigurations(
List<string> defaultConfigurations,
SlnPropertySet projectConfigs)
private static (Dictionary<string, string> Keys, string DefaultKey) GetKeysDictionary(IEnumerable<string> keys)
{
foreach (var config in defaultConfigurations)
// 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<string, string>(StringComparer.CurrentCultureIgnoreCase);
foreach (var key in keys)
{
var activeCfgKey = $"{config}.ActiveCfg";
if (!projectConfigs.ContainsKey(activeCfgKey))
{
projectConfigs[activeCfgKey] = config;
dictionary[key] = key;
}
var build0Key = $"{config}.Build.0";
if (!projectConfigs.ContainsKey(build0Key))
{
projectConfigs[build0Key] = config;
}
}
return (dictionary, keys.FirstOrDefault());
}
public static void AddSolutionFolders(this SlnFile slnFile, SlnProject slnProject)
private static string GetMatchingProjectKey(IDictionary<string, string> projectKeys, string solutionKey)
{
if (slnProject == null)
string projectKey;
if (projectKeys.TryGetValue(solutionKey, out projectKey))
{
throw new ArgumentException();
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<string, string> projectConfigurations,
string defaultProjectConfiguration,
Dictionary<string, string> 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)
{
var solutionFolders = slnProject.GetSolutionFoldersFromProject();
if (solutionFolders.Any())

View file

@ -81,16 +81,16 @@ Global
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.Build.0 = Release|x86
__LIB_PROJECT_GUID__.Debug|Any CPU.ActiveCfg = Debug|Any CPU
__LIB_PROJECT_GUID__.Debug|Any CPU.Build.0 = Debug|Any CPU
__LIB_PROJECT_GUID__.Debug|x64.ActiveCfg = Debug|x64
__LIB_PROJECT_GUID__.Debug|x64.Build.0 = Debug|x64
__LIB_PROJECT_GUID__.Debug|x86.ActiveCfg = Debug|x86
__LIB_PROJECT_GUID__.Debug|x86.Build.0 = Debug|x86
__LIB_PROJECT_GUID__.Debug|x64.ActiveCfg = Debug|Any CPU
__LIB_PROJECT_GUID__.Debug|x64.Build.0 = Debug|Any CPU
__LIB_PROJECT_GUID__.Debug|x86.ActiveCfg = Debug|Any CPU
__LIB_PROJECT_GUID__.Debug|x86.Build.0 = Debug|Any CPU
__LIB_PROJECT_GUID__.Release|Any CPU.ActiveCfg = Release|Any CPU
__LIB_PROJECT_GUID__.Release|Any CPU.Build.0 = Release|Any CPU
__LIB_PROJECT_GUID__.Release|x64.ActiveCfg = Release|x64
__LIB_PROJECT_GUID__.Release|x64.Build.0 = Release|x64
__LIB_PROJECT_GUID__.Release|x86.ActiveCfg = Release|x86
__LIB_PROJECT_GUID__.Release|x86.Build.0 = Release|x86
__LIB_PROJECT_GUID__.Release|x64.ActiveCfg = Release|Any CPU
__LIB_PROJECT_GUID__.Release|x64.Build.0 = Release|Any CPU
__LIB_PROJECT_GUID__.Release|x86.ActiveCfg = Release|Any CPU
__LIB_PROJECT_GUID__.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -117,16 +117,16 @@ Global
GlobalSection(ProjectConfigurationPlatforms) = postSolution
__LIB_PROJECT_GUID__.Debug|Any CPU.ActiveCfg = Debug|Any CPU
__LIB_PROJECT_GUID__.Debug|Any CPU.Build.0 = Debug|Any CPU
__LIB_PROJECT_GUID__.Debug|x64.ActiveCfg = Debug|x64
__LIB_PROJECT_GUID__.Debug|x64.Build.0 = Debug|x64
__LIB_PROJECT_GUID__.Debug|x86.ActiveCfg = Debug|x86
__LIB_PROJECT_GUID__.Debug|x86.Build.0 = Debug|x86
__LIB_PROJECT_GUID__.Debug|x64.ActiveCfg = Debug|Any CPU
__LIB_PROJECT_GUID__.Debug|x64.Build.0 = Debug|Any CPU
__LIB_PROJECT_GUID__.Debug|x86.ActiveCfg = Debug|Any CPU
__LIB_PROJECT_GUID__.Debug|x86.Build.0 = Debug|Any CPU
__LIB_PROJECT_GUID__.Release|Any CPU.ActiveCfg = Release|Any CPU
__LIB_PROJECT_GUID__.Release|Any CPU.Build.0 = Release|Any CPU
__LIB_PROJECT_GUID__.Release|x64.ActiveCfg = Release|x64
__LIB_PROJECT_GUID__.Release|x64.Build.0 = Release|x64
__LIB_PROJECT_GUID__.Release|x86.ActiveCfg = Release|x86
__LIB_PROJECT_GUID__.Release|x86.Build.0 = Release|x86
__LIB_PROJECT_GUID__.Release|x64.ActiveCfg = Release|Any CPU
__LIB_PROJECT_GUID__.Release|x64.Build.0 = Release|Any CPU
__LIB_PROJECT_GUID__.Release|x86.ActiveCfg = Release|Any CPU
__LIB_PROJECT_GUID__.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
";
@ -166,16 +166,16 @@ Global
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.Build.0 = Release|x86
__LIB_PROJECT_GUID__.Debug|Any CPU.ActiveCfg = Debug|Any CPU
__LIB_PROJECT_GUID__.Debug|Any CPU.Build.0 = Debug|Any CPU
__LIB_PROJECT_GUID__.Debug|x64.ActiveCfg = Debug|x64
__LIB_PROJECT_GUID__.Debug|x64.Build.0 = Debug|x64
__LIB_PROJECT_GUID__.Debug|x86.ActiveCfg = Debug|x86
__LIB_PROJECT_GUID__.Debug|x86.Build.0 = Debug|x86
__LIB_PROJECT_GUID__.Debug|x64.ActiveCfg = Debug|Any CPU
__LIB_PROJECT_GUID__.Debug|x64.Build.0 = Debug|Any CPU
__LIB_PROJECT_GUID__.Debug|x86.ActiveCfg = Debug|Any CPU
__LIB_PROJECT_GUID__.Debug|x86.Build.0 = Debug|Any CPU
__LIB_PROJECT_GUID__.Release|Any CPU.ActiveCfg = Release|Any CPU
__LIB_PROJECT_GUID__.Release|Any CPU.Build.0 = Release|Any CPU
__LIB_PROJECT_GUID__.Release|x64.ActiveCfg = Release|x64
__LIB_PROJECT_GUID__.Release|x64.Build.0 = Release|x64
__LIB_PROJECT_GUID__.Release|x86.ActiveCfg = Release|x86
__LIB_PROJECT_GUID__.Release|x86.Build.0 = Release|x86
__LIB_PROJECT_GUID__.Release|x64.ActiveCfg = Release|Any CPU
__LIB_PROJECT_GUID__.Release|x64.Build.0 = Release|Any CPU
__LIB_PROJECT_GUID__.Release|x86.ActiveCfg = Release|Any CPU
__LIB_PROJECT_GUID__.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -184,6 +184,141 @@ Global
__LIB_PROJECT_GUID__ = __SRC_FOLDER_GUID__
EndGlobalSection
EndGlobal
";
private const string ExpectedSlnFileAfterAddingProjectWithoutMatchingConfigs = @"
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26006.2
MinimumVisualStudioVersion = 10.0.40219.1
Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""ProjectWithoutMatchingConfigs"", ""ProjectWithoutMatchingConfigs\ProjectWithoutMatchingConfigs.csproj"", ""{C49B64DE-4401-4825-8A88-10DCB5950E57}""
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
Foo Bar|Any CPU = Foo Bar|Any CPU
Foo Bar|x64 = Foo Bar|x64
Foo Bar|x86 = Foo Bar|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|x64.ActiveCfg = Debug|Any CPU
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|x64.Build.0 = Debug|Any CPU
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|x86.ActiveCfg = Debug|Any CPU
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|x86.Build.0 = Debug|Any CPU
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|Any CPU.Build.0 = Release|Any CPU
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|x64.ActiveCfg = Release|Any CPU
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|x64.Build.0 = Release|Any CPU
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|x86.ActiveCfg = Release|Any CPU
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|x86.Build.0 = Release|Any CPU
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|Any CPU.ActiveCfg = Debug|Any CPU
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|Any CPU.Build.0 = Debug|Any CPU
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|x64.ActiveCfg = Debug|Any CPU
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|x64.Build.0 = Debug|Any CPU
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|x86.ActiveCfg = Debug|Any CPU
{C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|x86.Build.0 = Debug|Any CPU
EndGlobalSection
EndGlobal
";
private const string ExpectedSlnFileAfterAddingProjectWithMatchingConfigs = @"
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26006.2
MinimumVisualStudioVersion = 10.0.40219.1
Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""ProjectWithMatchingConfigs"", ""ProjectWithMatchingConfigs\ProjectWithMatchingConfigs.csproj"", ""{C9601CA2-DB64-4FB6-B463-368C7764BF0D}""
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
Foo Bar|Any CPU = Foo Bar|Any CPU
Foo Bar|x64 = Foo Bar|x64
Foo Bar|x86 = Foo Bar|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|x64.ActiveCfg = Debug|x64
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|x64.Build.0 = Debug|x64
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|x86.ActiveCfg = Debug|x86
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|x86.Build.0 = Debug|x86
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|Any CPU.Build.0 = Release|Any CPU
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|x64.ActiveCfg = Release|x64
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|x64.Build.0 = Release|x64
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|x86.ActiveCfg = Release|x86
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|x86.Build.0 = Release|x86
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|Any CPU.ActiveCfg = FooBar|Any CPU
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|Any CPU.Build.0 = FooBar|Any CPU
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|x64.ActiveCfg = FooBar|x64
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|x64.Build.0 = FooBar|x64
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|x86.ActiveCfg = FooBar|x86
{C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|x86.Build.0 = FooBar|x86
EndGlobalSection
EndGlobal
";
private const string ExpectedSlnFileAfterAddingProjectWithAdditionalConfigs = @"
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26006.2
MinimumVisualStudioVersion = 10.0.40219.1
Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""ProjectWithAdditionalConfigs"", ""ProjectWithAdditionalConfigs\ProjectWithAdditionalConfigs.csproj"", ""{A302325B-D680-4C0E-8680-7AE283981624}""
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
Foo Bar|Any CPU = Foo Bar|Any CPU
Foo Bar|x64 = Foo Bar|x64
Foo Bar|x86 = Foo Bar|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A302325B-D680-4C0E-8680-7AE283981624}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A302325B-D680-4C0E-8680-7AE283981624}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A302325B-D680-4C0E-8680-7AE283981624}.Debug|x64.ActiveCfg = Debug|x64
{A302325B-D680-4C0E-8680-7AE283981624}.Debug|x64.Build.0 = Debug|x64
{A302325B-D680-4C0E-8680-7AE283981624}.Debug|x86.ActiveCfg = Debug|x86
{A302325B-D680-4C0E-8680-7AE283981624}.Debug|x86.Build.0 = Debug|x86
{A302325B-D680-4C0E-8680-7AE283981624}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A302325B-D680-4C0E-8680-7AE283981624}.Release|Any CPU.Build.0 = Release|Any CPU
{A302325B-D680-4C0E-8680-7AE283981624}.Release|x64.ActiveCfg = Release|x64
{A302325B-D680-4C0E-8680-7AE283981624}.Release|x64.Build.0 = Release|x64
{A302325B-D680-4C0E-8680-7AE283981624}.Release|x86.ActiveCfg = Release|x86
{A302325B-D680-4C0E-8680-7AE283981624}.Release|x86.Build.0 = Release|x86
{A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|Any CPU.ActiveCfg = FooBar|Any CPU
{A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|Any CPU.Build.0 = FooBar|Any CPU
{A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|x64.ActiveCfg = FooBar|x64
{A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|x64.Build.0 = FooBar|x64
{A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|x86.ActiveCfg = FooBar|x86
{A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|x86.Build.0 = FooBar|x86
EndGlobalSection
EndGlobal
";
[Theory]
@ -788,6 +923,69 @@ EndGlobal
solutionFolderProjects.Count().Should().Be(1);
}
[Fact]
public void WhenProjectWithoutMatchingConfigurationsIsAddedSolutionMapsToFirstAvailable()
{
var slnDirectory = TestAssets
.Get("TestAppWithSlnAndProjectConfigs")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var slnFullPath = Path.Combine(slnDirectory, "App.sln");
var result = new DotnetCommand()
.WithWorkingDirectory(slnDirectory)
.ExecuteWithCapturedOutput($"sln add ProjectWithoutMatchingConfigs");
result.Should().Pass();
File.ReadAllText(slnFullPath)
.Should().BeVisuallyEquivalentTo(ExpectedSlnFileAfterAddingProjectWithoutMatchingConfigs);
}
[Fact]
public void WhenProjectWithMatchingConfigurationsIsAddedSolutionMapsAll()
{
var slnDirectory = TestAssets
.Get("TestAppWithSlnAndProjectConfigs")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var slnFullPath = Path.Combine(slnDirectory, "App.sln");
var result = new DotnetCommand()
.WithWorkingDirectory(slnDirectory)
.ExecuteWithCapturedOutput($"sln add ProjectWithMatchingConfigs");
result.Should().Pass();
File.ReadAllText(slnFullPath)
.Should().BeVisuallyEquivalentTo(ExpectedSlnFileAfterAddingProjectWithMatchingConfigs);
}
[Fact]
public void WhenProjectWithAdditionalConfigurationsIsAddedSolutionDoesNotMapThem()
{
var slnDirectory = TestAssets
.Get("TestAppWithSlnAndProjectConfigs")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
var slnFullPath = Path.Combine(slnDirectory, "App.sln");
var result = new DotnetCommand()
.WithWorkingDirectory(slnDirectory)
.ExecuteWithCapturedOutput($"sln add ProjectWithAdditionalConfigs");
result.Should().Pass();
File.ReadAllText(slnFullPath)
.Should().BeVisuallyEquivalentTo(ExpectedSlnFileAfterAddingProjectWithAdditionalConfigs);
}
private string GetExpectedSlnContents(
string slnPath,
string slnTemplate,