12 changed files with 327 additions and 273 deletions
@ -0,0 +1,250 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
|
||||||
|
using ICSharpCode.NRefactory; |
||||||
|
using ICSharpCode.SharpDevelop.Dom; |
||||||
|
using Microsoft.Build.Construction; |
||||||
|
|
||||||
|
namespace ICSharpCode.SharpDevelop.Project |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// The collection for <see cref="MSBuildBasedProject.ConfigurationNames"/> and <see cref="MSBuildBasedProject.PlatformNames"/>.
|
||||||
|
/// </summary>
|
||||||
|
class MSBuildConfigurationOrPlatformNameCollection : IConfigurationOrPlatformNameCollection |
||||||
|
{ |
||||||
|
public event ModelCollectionChangedEventHandler<string> CollectionChanged; |
||||||
|
|
||||||
|
volatile IReadOnlyList<string> listSnapshot = EmptyList<string>.Instance; |
||||||
|
readonly MSBuildBasedProject project; |
||||||
|
readonly bool isPlatform; |
||||||
|
|
||||||
|
public MSBuildConfigurationOrPlatformNameCollection(MSBuildBasedProject project, bool isPlatform) |
||||||
|
{ |
||||||
|
this.project = project; |
||||||
|
this.isPlatform = isPlatform; |
||||||
|
} |
||||||
|
|
||||||
|
internal void SetContents(IEnumerable<string> updatedItems) |
||||||
|
{ |
||||||
|
this.listSnapshot = updatedItems.ToArray(); |
||||||
|
} |
||||||
|
|
||||||
|
internal void OnCollectionChanged(IReadOnlyCollection<string> oldItems, IReadOnlyCollection<string> newItems) |
||||||
|
{ |
||||||
|
if (oldItems.SequenceEqual(newItems)) |
||||||
|
return; |
||||||
|
var eh = CollectionChanged; |
||||||
|
if (eh != null) |
||||||
|
eh(oldItems, newItems); |
||||||
|
} |
||||||
|
|
||||||
|
#region IReadOnlyCollection implementation
|
||||||
|
|
||||||
|
public IReadOnlyCollection<string> CreateSnapshot() |
||||||
|
{ |
||||||
|
return listSnapshot; |
||||||
|
} |
||||||
|
|
||||||
|
public int Count { |
||||||
|
get { |
||||||
|
return listSnapshot.Count; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public IEnumerator<string> GetEnumerator() |
||||||
|
{ |
||||||
|
return listSnapshot.GetEnumerator(); |
||||||
|
} |
||||||
|
|
||||||
|
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() |
||||||
|
{ |
||||||
|
return listSnapshot.GetEnumerator(); |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public string ValidateName(string name) |
||||||
|
{ |
||||||
|
if (name == null) |
||||||
|
return null; |
||||||
|
name = name.Trim(); |
||||||
|
if (!ConfigurationAndPlatform.IsValidName(name)) |
||||||
|
return null; |
||||||
|
if (isPlatform) |
||||||
|
return MSBuildInternals.FixPlatformNameForProject(name); |
||||||
|
else |
||||||
|
return name; |
||||||
|
} |
||||||
|
|
||||||
|
string GetName(ConfigurationAndPlatform config) |
||||||
|
{ |
||||||
|
return isPlatform ? config.Platform : config.Configuration; |
||||||
|
} |
||||||
|
|
||||||
|
bool HasName(ConfigurationAndPlatform config, string name) |
||||||
|
{ |
||||||
|
return ConfigurationAndPlatform.ConfigurationNameComparer.Equals(GetName(config), name); |
||||||
|
} |
||||||
|
|
||||||
|
ConfigurationAndPlatform SetName(ConfigurationAndPlatform config, string newName) |
||||||
|
{ |
||||||
|
if (isPlatform) |
||||||
|
return new ConfigurationAndPlatform(config.Configuration, newName); |
||||||
|
else |
||||||
|
return new ConfigurationAndPlatform(newName, config.Platform); |
||||||
|
} |
||||||
|
|
||||||
|
void IConfigurationOrPlatformNameCollection.Add(string newName, string copyFrom) |
||||||
|
{ |
||||||
|
SD.MainThread.VerifyAccess(); |
||||||
|
newName = ValidateName(newName); |
||||||
|
if (newName == null) |
||||||
|
throw new ArgumentException(); |
||||||
|
lock (project.SyncRoot) { |
||||||
|
var projectFile = project.MSBuildProjectFile; |
||||||
|
var userProjectFile = project.MSBuildUserProjectFile; |
||||||
|
bool copiedGroupInMainFile = false; |
||||||
|
if (copyFrom != null) { |
||||||
|
foreach (ProjectPropertyGroupElement g in projectFile.PropertyGroups.ToList()) { |
||||||
|
var gConfig = ConfigurationAndPlatform.FromCondition(g.Condition); |
||||||
|
if (HasName(gConfig, copyFrom)) { |
||||||
|
CopyProperties(projectFile, g, SetName(gConfig, newName)); |
||||||
|
copiedGroupInMainFile = true; |
||||||
|
} |
||||||
|
} |
||||||
|
foreach (ProjectPropertyGroupElement g in userProjectFile.PropertyGroups.ToList()) { |
||||||
|
var gConfig = ConfigurationAndPlatform.FromCondition(g.Condition); |
||||||
|
if (HasName(gConfig, copyFrom)) { |
||||||
|
CopyProperties(userProjectFile, g, SetName(gConfig, newName)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (!copiedGroupInMainFile) { |
||||||
|
projectFile.AddPropertyGroup().Condition = (isPlatform ? new ConfigurationAndPlatform(null, newName) : new ConfigurationAndPlatform(newName, null)).ToCondition(); |
||||||
|
} |
||||||
|
project.LoadConfigurationPlatformNamesFromMSBuild(); |
||||||
|
|
||||||
|
// Adjust mapping:
|
||||||
|
// If the new config/platform already exists in the solution and is mapped to some old project config/platform,
|
||||||
|
// re-map it to the new config/platform.
|
||||||
|
var mapping = project.ConfigurationMapping; |
||||||
|
if (isPlatform) { |
||||||
|
string newNameForSolution = MSBuildInternals.FixPlatformNameForSolution(newName); |
||||||
|
if (project.ParentSolution.PlatformNames.Contains(newNameForSolution, ConfigurationAndPlatform.ConfigurationNameComparer)) { |
||||||
|
foreach (string solutionConfiguration in project.ParentSolution.ConfigurationNames) { |
||||||
|
var solutionConfig = new ConfigurationAndPlatform(solutionConfiguration, newNameForSolution); |
||||||
|
var projectConfig = mapping.GetProjectConfiguration(solutionConfig); |
||||||
|
mapping.SetProjectConfiguration(solutionConfig, SetName(projectConfig, newName)); |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
if (project.ParentSolution.ConfigurationNames.Contains(newName, ConfigurationAndPlatform.ConfigurationNameComparer)) { |
||||||
|
foreach (string solutionPlatform in project.ParentSolution.PlatformNames) { |
||||||
|
var solutionConfig = new ConfigurationAndPlatform(newName, solutionPlatform); |
||||||
|
var projectConfig = mapping.GetProjectConfiguration(solutionConfig); |
||||||
|
mapping.SetProjectConfiguration(solutionConfig, SetName(projectConfig, newName)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
project.ActiveConfiguration = mapping.GetProjectConfiguration(project.ParentSolution.ActiveConfiguration); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// copy properties from g into a new property group for newConfiguration and newPlatform
|
||||||
|
/// </summary>
|
||||||
|
void CopyProperties(ProjectRootElement project, ProjectPropertyGroupElement g, ConfigurationAndPlatform newConfig) |
||||||
|
{ |
||||||
|
ProjectPropertyGroupElement ng = project.AddPropertyGroup(); |
||||||
|
ng.Condition = newConfig.ToCondition(); |
||||||
|
foreach (var p in g.Properties) { |
||||||
|
ng.AddProperty(p.Name, p.Value).Condition = p.Condition; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finds the <Configuration> or <Platform> element in this property group.
|
||||||
|
/// </summary>
|
||||||
|
ProjectPropertyElement FindConfigElement(ProjectPropertyGroupElement g) |
||||||
|
{ |
||||||
|
return g.Properties.FirstOrDefault(p => MSBuildInternals.PropertyNameComparer.Equals(p.Name, isPlatform ? "Platform" : "Configuration")); |
||||||
|
} |
||||||
|
|
||||||
|
void IConfigurationOrPlatformNameCollection.Remove(string name) |
||||||
|
{ |
||||||
|
SD.MainThread.VerifyAccess(); |
||||||
|
lock (project.SyncRoot) { |
||||||
|
string otherName = null; |
||||||
|
foreach (string configName in this) { |
||||||
|
if (!ConfigurationAndPlatform.ConfigurationNameComparer.Equals(configName, name)) { |
||||||
|
otherName = name; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
if (otherName == null) { |
||||||
|
throw new InvalidOperationException("cannot remove the last configuration/platform"); |
||||||
|
} |
||||||
|
foreach (ProjectPropertyGroupElement g in project.MSBuildProjectFile.PropertyGroups.Concat(project.MSBuildUserProjectFile.PropertyGroups).ToList()) { |
||||||
|
ProjectPropertyElement prop = FindConfigElement(g); |
||||||
|
if (prop != null && ConfigurationAndPlatform.ConfigurationNameComparer.Equals(prop.Value, name)) { |
||||||
|
prop.Value = otherName; |
||||||
|
} |
||||||
|
|
||||||
|
var gConfig = ConfigurationAndPlatform.FromCondition(g.Condition); |
||||||
|
if (HasName(gConfig, name)) { |
||||||
|
g.Parent.RemoveChild(g); |
||||||
|
} |
||||||
|
} |
||||||
|
project.LoadConfigurationPlatformNamesFromMSBuild(); |
||||||
|
|
||||||
|
AdjustMapping(name, otherName); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void IConfigurationOrPlatformNameCollection.Rename(string oldName, string newName) |
||||||
|
{ |
||||||
|
newName = ValidateName(newName); |
||||||
|
if (newName == null) |
||||||
|
throw new ArgumentException(); |
||||||
|
|
||||||
|
lock (project.SyncRoot) { |
||||||
|
foreach (ProjectPropertyGroupElement g in project.MSBuildProjectFile.PropertyGroups.Concat(project.MSBuildUserProjectFile.PropertyGroups)) { |
||||||
|
// Rename the default configuration setting
|
||||||
|
ProjectPropertyElement prop = FindConfigElement(g); |
||||||
|
if (prop != null && ConfigurationAndPlatform.ConfigurationNameComparer.Equals(prop.Value, oldName)) { |
||||||
|
prop.Value = newName; |
||||||
|
} |
||||||
|
|
||||||
|
// Rename the configuration in conditions
|
||||||
|
var gConfig = ConfigurationAndPlatform.FromCondition(g.Condition); |
||||||
|
if (HasName(gConfig, oldName)) { |
||||||
|
g.Condition = SetName(gConfig, newName).ToCondition(); |
||||||
|
} |
||||||
|
} |
||||||
|
project.LoadConfigurationPlatformNamesFromMSBuild(); |
||||||
|
|
||||||
|
AdjustMapping(oldName, newName); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void AdjustMapping(string oldName, string newName) |
||||||
|
{ |
||||||
|
var mapping = project.ConfigurationMapping; |
||||||
|
foreach (string solutionConfiguration in project.ParentSolution.ConfigurationNames) { |
||||||
|
foreach (string solutionPlatform in project.ParentSolution.PlatformNames) { |
||||||
|
var solutionConfig = new ConfigurationAndPlatform(solutionConfiguration, solutionPlatform); |
||||||
|
var projectConfig = mapping.GetProjectConfiguration(solutionConfig); |
||||||
|
if (HasName(projectConfig, oldName)) |
||||||
|
mapping.SetProjectConfiguration(solutionConfig, SetName(projectConfig, newName)); |
||||||
|
} |
||||||
|
} |
||||||
|
// Adjust active configuration:
|
||||||
|
if (HasName(project.ActiveConfiguration, oldName)) |
||||||
|
project.ActiveConfiguration = SetName(project.ActiveConfiguration, newName); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue