1
// MSBuildProjectHandler.cs
4
// Lluis Sanchez Gual <lluis@novell.com>
6
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
8
// Permission is hereby granted, free of charge, to any person obtaining a copy
9
// of this software and associated documentation files (the "Software"), to deal
10
// in the Software without restriction, including without limitation the rights
11
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
// copies of the Software, and to permit persons to whom the Software is
13
// furnished to do so, subject to the following conditions:
15
// The above copyright notice and this permission notice shall be included in
16
// all copies or substantial portions of the Software.
18
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31
using System.Collections;
32
using System.Collections.Generic;
33
using System.Reflection;
34
using MonoDevelop.Core;
35
using MonoDevelop.Projects;
36
using MonoDevelop.Core.Serialization;
37
using MonoDevelop.Core.Assemblies;
38
using MonoDevelop.Projects.Formats.MD1;
39
using MonoDevelop.Projects.Extensions;
40
using MonoDevelop.Core.Execution;
43
using MonoDevelop.Core.Instrumentation;
45
namespace MonoDevelop.Projects.Formats.MSBuild
47
public class MSBuildProjectHandler: MSBuildHandler, IResourceHandler, IPathHandler, IAssemblyReferenceHandler
50
List<string> targetImports = new List<string> ();
51
IResourceHandler customResourceHandler;
52
List<string> subtypeGuids = new List<string> ();
53
const string Unspecified = null;
54
RemoteProjectBuilder projectBuilder;
55
TargetFramework lastBuildFx;
59
public MSBuildItem Item;
63
protected SolutionEntityItem EntityItem {
64
get { return (SolutionEntityItem) Item; }
67
public System.Collections.Generic.List<string> TargetImports {
72
targetImports = value;
76
public void SetCustomResourceHandler (IResourceHandler value)
78
customResourceHandler = value;
81
public List<string> SubtypeGuids {
87
public MSBuildProjectHandler ()
91
public MSBuildProjectHandler (string typeGuid, string import, string itemId)
93
Initialize (typeGuid, import, itemId);
96
internal void Initialize (string typeGuid, string import, string itemId)
98
base.Initialize (typeGuid, itemId);
99
if (import != null && import.Trim().Length > 0)
100
this.targetImports.AddRange (import.Split (':'));
102
Runtime.SystemAssemblyService.DefaultRuntimeChanged += OnDefaultRuntimeChanged;
105
void OnDefaultRuntimeChanged (object o, EventArgs args)
107
// If the default runtime changes, the project builder for this project may change
108
// so it has to be created again.
109
if (projectBuilder != null) {
110
projectBuilder.Dispose ();
111
projectBuilder = null;
115
RemoteProjectBuilder GetProjectBuilder ()
117
SolutionEntityItem item = (SolutionEntityItem) Item;
118
TargetRuntime runtime = null;
120
if (item is IAssemblyProject) {
121
runtime = ((IAssemblyProject) item).TargetRuntime;
122
fx = ((IAssemblyProject) item).TargetFramework;
125
runtime = Runtime.SystemAssemblyService.CurrentRuntime;
126
fx = Services.ProjectService.DefaultTargetFramework;
128
if (projectBuilder == null || lastBuildFx != fx) {
129
if (projectBuilder != null) {
130
projectBuilder.Dispose ();
131
projectBuilder = null;
133
projectBuilder = MSBuildProjectService.GetProjectBuilder (runtime, fx, item.FileName);
136
return projectBuilder;
139
public override void Dispose ()
142
if (projectBuilder != null) {
143
projectBuilder.Dispose ();
144
projectBuilder = null;
146
Runtime.SystemAssemblyService.DefaultRuntimeChanged -= OnDefaultRuntimeChanged;
149
IEnumerable<string> IAssemblyReferenceHandler.GetAssemblyReferences (ConfigurationSelector configuration)
151
if (PropertyService.Get ("MonoDevelop.Ide.BuildWithMSBuild", false)) {
152
// Get the references list from the msbuild project
153
SolutionEntityItem item = (SolutionEntityItem) Item;
154
RemoteProjectBuilder builder = GetProjectBuilder ();
155
SolutionItemConfiguration configObject = item.GetConfiguration (configuration);
156
foreach (string s in builder.GetAssemblyReferences (configObject.Name, configObject.Platform))
160
DotNetProject item = Item as DotNetProject;
163
foreach (ProjectReference pref in item.References.Where (pr => pr.ReferenceType != ReferenceType.Project)) {
164
foreach (string asm in pref.GetReferencedFileNames (configuration))
170
public override BuildResult RunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration)
172
if (PropertyService.Get ("MonoDevelop.Ide.BuildWithMSBuild", false)) {
173
SolutionEntityItem item = Item as SolutionEntityItem;
176
SolutionItemConfiguration configObject = item.GetConfiguration (configuration);
178
LogWriter logWriter = new LogWriter (monitor.Log);
179
RemoteProjectBuilder builder = GetProjectBuilder ();
180
MSBuildResult[] results = builder.RunTarget (target, configObject.Name, configObject.Platform, logWriter);
181
System.Runtime.Remoting.RemotingServices.Disconnect (logWriter);
183
BuildResult br = new BuildResult ();
184
foreach (MSBuildResult res in results) {
186
br.AddWarning (res.File, res.Line, res.Column, res.Code, res.Message);
188
br.AddError (res.File, res.Line, res.Column, res.Code, res.Message);
194
if (Item is DotNetProject) {
195
MD1DotNetProjectHandler handler = new MD1DotNetProjectHandler ((DotNetProject)Item);
196
return handler.RunTarget (monitor, target, configuration);
202
public string GetDefaultResourceId (ProjectFile file)
204
if (customResourceHandler != null)
205
return customResourceHandler.GetDefaultResourceId (file);
207
return MSBuildResourceHandler.Instance.GetDefaultResourceId (file);
210
public string EncodePath (string path, string oldPath)
212
string basePath = Path.GetDirectoryName (EntityItem.FileName);
213
return FileService.RelativeToAbsolutePath (basePath, path);
216
public string DecodePath (string path)
218
string basePath = Path.GetDirectoryName (EntityItem.FileName);
219
return FileService.AbsoluteToRelativePath (basePath, path);
222
public SolutionEntityItem Load (IProgressMonitor monitor, string fileName, string language, Type itemClass)
224
timer = Counters.ReadMSBuildProject.BeginTiming ();
226
timer.Trace ("Reading project file");
227
MSBuildProject p = new MSBuildProject ();
228
fileContent = File.ReadAllText (fileName);
229
p.LoadXml (fileContent);
231
timer.Trace ("Read project guids");
233
MSBuildPropertyGroup globalGroup = p.GetGlobalPropertyGroup ();
235
// Avoid crash if there is not global group
236
if (globalGroup == null)
237
globalGroup = p.AddNewPropertyGroup (false);
239
string itemGuid = globalGroup.GetPropertyValue ("ProjectGuid");
240
string projectTypeGuids = globalGroup.GetPropertyValue ("ProjectTypeGuids");
241
string itemType = globalGroup.GetPropertyValue ("ItemType");
243
subtypeGuids.Clear ();
244
if (projectTypeGuids != null) {
245
foreach (string guid in projectTypeGuids.Split (';')) {
246
string sguid = guid.Trim ();
247
if (sguid.Length > 0 && string.Compare (sguid, TypeGuid, true) != 0)
248
subtypeGuids.Add (guid);
253
timer.Trace ("Create item instance");
254
ProjectExtensionUtil.BeginLoadOperation ();
255
Item = CreateSolutionItem (language, projectTypeGuids, itemType, itemClass);
257
Item.SetItemHandler (this);
258
MSBuildProjectService.SetId (Item, itemGuid);
260
SolutionEntityItem it = (SolutionEntityItem) Item;
262
it.FileName = fileName;
263
it.Name = System.IO.Path.GetFileNameWithoutExtension (fileName);
269
ProjectExtensionUtil.EndLoadOperation ();
274
SolutionItem CreateSolutionItem (string language, string typeGuids, string itemType, Type itemClass)
276
// All the parameters are optional, but at least one must be provided.
278
SolutionItem item = null;
280
if (!string.IsNullOrEmpty (typeGuids)) {
281
DotNetProjectSubtypeNode st = MSBuildProjectService.GetDotNetProjectSubtype (typeGuids);
283
item = st.CreateInstance (language);
284
if (!string.IsNullOrEmpty (st.Import))
285
targetImports.AddRange (st.Import.Split (':'));
287
throw new InvalidOperationException ("Unknown solution item type.");
289
if (item == null && itemClass != null)
290
item = (SolutionItem) Activator.CreateInstance (itemClass);
292
if (item == null && !string.IsNullOrEmpty (language))
293
item = new DotNetAssemblyProject (language);
296
if (string.IsNullOrEmpty (itemType))
297
throw new InvalidOperationException ("Unknown solution item type.");
299
DataType dt = MSBuildProjectService.DataContext.GetConfigurationDataType (itemType);
301
throw new InvalidOperationException ("Unknown solution item type: " + itemType);
303
item = (SolutionItem) Activator.CreateInstance (dt.ValueType);
306
// Basic initialization
308
if (item is DotNetProject) {
309
DotNetProject p = (DotNetProject) item;
310
p.TargetFramework = Services.ProjectService.DefaultTargetFramework;
315
void Load (IProgressMonitor monitor, MSBuildProject msproject)
317
timer.Trace ("Initialize serialization");
319
MSBuildSerializer ser = CreateSerializer ();
320
ser.SerializationContext.BaseFile = EntityItem.FileName;
321
ser.SerializationContext.ProgressMonitor = monitor;
323
MSBuildPropertyGroup globalGroup = msproject.GetGlobalPropertyGroup ();
325
Item.SetItemHandler (this);
327
DotNetProject dotNetProject = Item as DotNetProject;
329
string frameworkVersion = null;
333
timer.Trace ("Read project items");
335
foreach (MSBuildItem buildItem in msproject.GetAllItems ()) {
336
ProjectItem it = ReadItem (ser, buildItem);
338
EntityItem.Items.Add (it);
339
int i = EntityItem.Items.IndexOf (it);
340
if (i != -1 && EntityItem.Items [i] != it && EntityItem.Items [i].Condition == it.Condition)
341
EntityItem.Items.RemoveAt (i); // Remove duplicates
345
timer.Trace ("Read configurations");
347
if (dotNetProject != null) {
348
frameworkVersion = globalGroup.GetPropertyValue ("TargetFrameworkVersion");
349
if (frameworkVersion != null && frameworkVersion.StartsWith ("v"))
350
frameworkVersion = frameworkVersion.Substring (1);
351
if (!string.IsNullOrEmpty (frameworkVersion))
352
dotNetProject.TargetFramework = Runtime.SystemAssemblyService.GetTargetFramework (frameworkVersion);
354
if (dotNetProject.LanguageParameters != null) {
355
DataItem data = ReadPropertyGroupMetadata (ser, globalGroup, dotNetProject.LanguageParameters);
356
ser.Deserialize (dotNetProject.LanguageParameters, data);
360
// Read configurations
362
List<ConfigData> configData = GetConfigData (msproject);
363
List<ConfigData> readConfigData = new List<ConfigData> ();
365
MSBuildPropertyGroup mergedToProjectProperties = ExtractMergedtoprojectProperties (ser, globalGroup, EntityItem.CreateConfiguration ("Dummy"));
366
configData.Insert (0, new ConfigData (Unspecified, Unspecified, mergedToProjectProperties));
368
foreach (ConfigData cgrp in configData) {
369
readConfigData.Add (cgrp);
371
string conf = cgrp.Config;
372
string platform = cgrp.Platform;
374
if (platform == Unspecified && conf != Unspecified && !ContainsSpecificPlatformConfiguration (configData, conf))
375
platform = string.Empty;
377
// It may be a partial configuration
378
if (conf == Unspecified || platform == Unspecified)
381
MSBuildPropertyGroup grp = CreateMergedConfiguration (readConfigData, conf, platform);
382
SolutionItemConfiguration config = EntityItem.CreateConfiguration (conf);
384
config.Platform = platform;
385
DataItem data = ReadPropertyGroupMetadata (ser, grp, config);
386
ser.Deserialize (config, data);
387
EntityItem.Configurations.Add (config);
389
if (config is DotNetProjectConfiguration) {
390
DotNetProjectConfiguration dpc = (DotNetProjectConfiguration) config;
391
if (dpc.CompilationParameters != null) {
392
data = ReadPropertyGroupMetadata (ser, grp, dpc.CompilationParameters);
393
ser.Deserialize (dpc.CompilationParameters, data);
398
// Read extended properties
400
timer.Trace ("Read extended properties");
402
DataItem globalData = ReadPropertyGroupMetadata (ser, globalGroup, Item);
404
string extendedData = msproject.GetProjectExtensions ("MonoDevelop");
405
if (!string.IsNullOrEmpty (extendedData)) {
406
StringReader sr = new StringReader (extendedData);
407
DataItem data = (DataItem) XmlConfigurationReader.DefaultReader.Read (new XmlTextReader (sr));
408
globalData.ItemData.AddRange (data.ItemData);
410
ser.Deserialize (Item, globalData);
412
// Final initializations
414
timer.Trace ("Final initializations");
416
if (dotNetProject != null && string.IsNullOrEmpty (frameworkVersion)) {
417
string fx = Item.ExtendedProperties ["InternalTargetFrameworkVersion"] as string;
419
dotNetProject.TargetFramework = Runtime.SystemAssemblyService.GetTargetFramework (fx);
420
Item.ExtendedProperties.Remove ("InternalTargetFrameworkVersion");
422
// If no framework is specified, it means the format is VS2005, so the default framework is 2.0.
423
dotNetProject.TargetFramework = Runtime.SystemAssemblyService.GetTargetFramework ("2.0");
427
Item.NeedsReload = false;
430
MSBuildPropertyGroup ExtractMergedtoprojectProperties (MSBuildSerializer ser, MSBuildPropertyGroup pgroup, object ob)
432
XmlDocument doc = new XmlDocument ();
433
MSBuildPropertyGroup res = new MSBuildPropertyGroup (doc.CreateElement ("PropGroup"));
435
foreach (string propName in GetMergeToProjectProperties (ser, ob)) {
436
MSBuildProperty bp = pgroup.GetProperty (propName);
438
res.SetPropertyValue (bp.Name, bp.Value);
443
IEnumerable<string> GetMergeToProjectProperties (MSBuildSerializer ser, object ob)
445
ClassDataType dt = (ClassDataType) ser.DataContext.GetConfigurationDataType (ob.GetType ());
446
foreach (ItemProperty prop in dt.GetProperties (ser.SerializationContext, ob)) {
447
if (IsMergeToProjectProperty (prop))
448
yield return prop.Name;
452
ProjectItem ReadItem (MSBuildSerializer ser, MSBuildItem buildItem)
454
Project project = Item as Project;
455
DotNetProject dotNetProject = Item as DotNetProject;
457
DataType dt = ser.DataContext.GetConfigurationDataType (buildItem.Name);
459
if (project != null) {
460
if (buildItem.Name == "Folder") {
462
string path = MSBuildProjectService.FromMSBuildPath (project.ItemDirectory, buildItem.Include);
463
return new ProjectFile () { Name = Path.GetDirectoryName (path), Subtype = Subtype.Directory };
465
else if (buildItem.Name == "Reference" && dotNetProject != null) {
466
ProjectReference pref;
467
if (buildItem.HasMetadata ("HintPath")) {
468
string hintPath = buildItem.GetMetadata ("HintPath");
470
if (!MSBuildProjectService.FromMSBuildPath (dotNetProject.ItemDirectory, hintPath, out path)) {
471
pref = new ProjectReference (ReferenceType.Assembly, path);
472
pref.SetInvalid (GettextCatalog.GetString ("Invalid file path"));
473
pref.ExtendedProperties ["_OriginalMSBuildReferenceInclude"] = buildItem.Include;
474
pref.ExtendedProperties ["_OriginalMSBuildReferenceHintPath"] = hintPath;
475
} else if (File.Exists (path)) {
476
pref = new ProjectReference (ReferenceType.Assembly, path);
477
if (MSBuildProjectService.IsAbsoluteMSBuildPath (hintPath))
478
pref.ExtendedProperties ["_OriginalMSBuildReferenceIsAbsolute"] = true;
480
pref = new ProjectReference (ReferenceType.Gac, buildItem.Include);
481
pref.ExtendedProperties ["_OriginalMSBuildReferenceHintPath"] = hintPath;
483
pref.LocalCopy = !buildItem.GetMetadataIsFalse ("Private");
485
string asm = buildItem.Include;
486
// This is a workaround for a VS bug. Looks like it is writing this assembly incorrectly
487
if (asm == "System.configuration")
488
asm = "System.Configuration";
489
else if (asm == "System.XML")
491
else if (asm == "system")
493
pref = new ProjectReference (ReferenceType.Gac, asm);
495
pref.Condition = buildItem.Condition;
496
pref.SpecificVersion = !buildItem.GetMetadataIsFalse ("SpecificVersion");
497
ReadBuildItemMetadata (ser, buildItem, pref, typeof(ProjectReference));
500
else if (buildItem.Name == "ProjectReference" && dotNetProject != null) {
501
// Get the project name from the path, since the Name attribute may other stuff other than the name
502
string path = MSBuildProjectService.FromMSBuildPath (project.ItemDirectory, buildItem.Include);
503
string name = Path.GetFileNameWithoutExtension (path);
504
ProjectReference pref = new ProjectReference (ReferenceType.Project, name);
505
pref.LocalCopy = !buildItem.GetMetadataIsFalse ("Private");
506
pref.Condition = buildItem.Condition;
509
else if (dt == null && !string.IsNullOrEmpty (buildItem.Include)) {
510
// Unknown item. Must be a file.
511
if (!UnsupportedItems.Contains (buildItem.Name) && IsValidFile (buildItem.Include))
512
return ReadProjectFile (ser, project, buildItem, typeof(ProjectFile));
516
if (dt != null && typeof(ProjectItem).IsAssignableFrom (dt.ValueType)) {
517
ProjectItem obj = (ProjectItem) Activator.CreateInstance (dt.ValueType);
518
ReadBuildItemMetadata (ser, buildItem, obj, dt.ValueType);
522
UnknownProjectItem uitem = new UnknownProjectItem (buildItem.Name, "");
523
ReadBuildItemMetadata (ser, buildItem, uitem, typeof(UnknownProjectItem));
528
bool IsValidFile (string path)
530
// If it is an absolute uri, it's not a valid file
532
return !Uri.IsWellFormedUriString (path, UriKind.Absolute);
534
// Old mono versions may crash in IsWellFormedUriString if the path
542
public ConfigData (string conf, string plt, MSBuildPropertyGroup grp)
549
public string Config;
550
public string Platform;
551
public MSBuildPropertyGroup Group;
554
MSBuildPropertyGroup CreateMergedConfiguration (List<ConfigData> configData, string conf, string platform)
556
MSBuildPropertyGroup merged = null;
558
foreach (ConfigData grp in configData) {
559
if ((grp.Config == conf || grp.Config == Unspecified) && (grp.Platform == platform || grp.Platform == Unspecified)) {
563
merged = MSBuildPropertyGroup.Merge (merged, grp.Group);
569
bool ContainsSpecificPlatformConfiguration (List<ConfigData> configData, string conf)
571
foreach (ConfigData grp in configData) {
572
if (grp.Config == conf && grp.Platform != Unspecified)
578
protected override void SaveItem (MonoDevelop.Core.IProgressMonitor monitor)
580
if (Item is UnknownProject || Item is UnknownSolutionItem)
583
bool newProject = false;
584
SolutionEntityItem eitem = EntityItem;
586
MSBuildSerializer ser = CreateSerializer ();
587
ser.SerializationContext.BaseFile = eitem.FileName;
588
ser.SerializationContext.ProgressMonitor = monitor;
590
DotNetProject dotNetProject = Item as DotNetProject;
592
MSBuildProject msproject = new MSBuildProject ();
593
if (fileContent != null) {
594
msproject.LoadXml (fileContent);
596
msproject.DefaultTargets = "Build";
602
MSBuildPropertyGroup globalGroup = msproject.GetGlobalPropertyGroup ();
603
if (globalGroup == null) {
604
globalGroup = msproject.AddNewPropertyGroup (false);
607
if (eitem.Configurations.Count > 0) {
608
ItemConfiguration conf = eitem.Configurations ["Debug"];
609
if (conf == null) conf = eitem.Configurations [0];
610
MSBuildProperty bprop = SetGroupProperty (globalGroup, "Configuration", conf.Name, false);
611
bprop.Condition = " '$(Configuration)' == '' ";
613
string platform = conf.Platform.Length == 0 ? "AnyCPU" : conf.Platform;
614
bprop = SetGroupProperty (globalGroup, "Platform", platform, false);
615
bprop.Condition = " '$(Platform)' == '' ";
618
if (TypeGuid == MSBuildProjectService.GenericItemGuid) {
619
DataType dt = MSBuildProjectService.DataContext.GetConfigurationDataType (Item.GetType ());
620
SetGroupProperty (globalGroup, "ItemType", dt.Name, false);
623
Item.ExtendedProperties ["ProjectGuid"] = Item.ItemId;
624
if (subtypeGuids.Count > 0) {
626
foreach (string sg in subtypeGuids) {
631
gg += ";" + TypeGuid;
632
Item.ExtendedProperties ["ProjectTypeGuids"] = gg.ToUpper ();
635
Item.ExtendedProperties.Remove ("ProjectTypeGuids");
637
string productVersion = (string) Item.ExtendedProperties ["ProductVersion"];
638
if (productVersion == null) {
639
Item.ExtendedProperties ["ProductVersion"] = TargetFormat.ProductVersion;
640
productVersion = TargetFormat.ProductVersion;
643
Item.ExtendedProperties ["SchemaVersion"] = "2.0";
645
if (TargetFormat.ToolsVersion != "2.0")
646
msproject.ToolsVersion = TargetFormat.ToolsVersion;
648
msproject.ToolsVersion = string.Empty;
651
string targetFramework = null;
652
IList supportedFrameworks = TargetFormat.FrameworkVersions;
654
if (dotNetProject != null) {
656
targetFramework = dotNetProject.TargetFramework.Id;
658
// If the file format does not support this framework version, store the highest version
659
// supported in the TargetFrameworkVersion property and the real one in the extended properties
660
if (!supportedFrameworks.Contains (targetFramework)) {
661
dotNetProject.ExtendedProperties ["InternalTargetFrameworkVersion"] = targetFramework;
662
targetFramework = FindClosestSupportedVersion (targetFramework);
664
dotNetProject.ExtendedProperties.Remove ("InternalTargetFrameworkVersion");
667
// This serialize call will write data to ser.InternalItemProperties and ser.ExternalItemProperties
668
ser.Serialize (Item, Item.GetType ());
670
object langParams = null;
672
if (dotNetProject != null && dotNetProject.LanguageParameters != null) {
673
// Remove all language parameters properties from the data item, since we are going to write them again.
674
ClassDataType dt = (ClassDataType) ser.DataContext.GetConfigurationDataType (dotNetProject.LanguageParameters.GetType ());
675
foreach (ItemProperty prop in dt.GetProperties (ser.SerializationContext, dotNetProject.LanguageParameters)) {
676
DataNode n = ser.InternalItemProperties.ItemData [prop.Name];
678
ser.InternalItemProperties.ItemData.Remove (n);
680
DataItem ditemComp = (DataItem) ser.Serialize (dotNetProject.LanguageParameters);
681
ser.InternalItemProperties.ItemData.AddRange (ditemComp.ItemData);
682
langParams = dotNetProject.LanguageParameters;
685
if (fileContent == null)
686
ser.InternalItemProperties.ItemData.Sort (globalConfigOrder);
688
WritePropertyGroupMetadata (globalGroup, ser.InternalItemProperties.ItemData, ser, Item, langParams);
690
// Convert debug property
692
foreach (SolutionItemConfiguration conf in eitem.Configurations) {
693
DotNetProjectConfiguration cp = conf as MonoDevelop.Projects.DotNetProjectConfiguration;
696
cp.ExtendedProperties ["ErrorReport"] = "prompt";
698
string debugType = (string) cp.ExtendedProperties ["DebugType"];
700
if (debugType != "full" && debugType != "pdbonly")
701
cp.ExtendedProperties ["DebugType"] = "full";
703
else if (debugType != "none" && debugType != "pdbonly")
704
cp.ExtendedProperties ["DebugType"] = "none";
710
if (eitem.Configurations.Count > 0) {
711
List<ConfigData> configData = GetConfigData (msproject);
712
Dictionary<string,string> mergeToProjectProperties = new Dictionary<string,string> ();
713
List<string> mergeToProjectPropertyNames = new List<string> (GetMergeToProjectProperties (ser, eitem.Configurations [0]));
714
List<string> mergeToProjectPropertyNamesCopy = new List<string> (mergeToProjectPropertyNames);
716
foreach (SolutionItemConfiguration conf in eitem.Configurations) {
717
bool newConf = false;
718
MSBuildPropertyGroup propGroup = FindPropertyGroup (configData, conf);
719
if (propGroup == null) {
720
propGroup = msproject.AddNewPropertyGroup (false);
721
propGroup.Condition = BuildConfigCondition (conf.Name, conf.Platform);
722
ConfigData cd = new ConfigData (conf.Name, conf.Platform, propGroup);
727
DotNetProjectConfiguration netConfig = conf as DotNetProjectConfiguration;
729
DataItem ditem = (DataItem) ser.Serialize (conf);
731
if (netConfig != null && netConfig.CompilationParameters != null) {
732
// Remove all compilation parameters properties from the data item, since we are going to write them again.
733
ClassDataType dt = (ClassDataType) ser.DataContext.GetConfigurationDataType (netConfig.CompilationParameters.GetType ());
734
foreach (ItemProperty prop in dt.GetProperties (ser.SerializationContext, netConfig.CompilationParameters)) {
735
DataNode n = ditem.ItemData [prop.Name];
737
ditem.ItemData.Remove (n);
739
DataItem ditemComp = (DataItem) ser.Serialize (netConfig.CompilationParameters);
740
ditem.ItemData.AddRange (ditemComp.ItemData);
744
ditem.ItemData.Sort (configOrder);
746
WritePropertyGroupMetadata (propGroup, ditem.ItemData, ser, conf, netConfig != null ? netConfig.CompilationParameters : null);
748
UnmergeBaseConfiguration (configData, propGroup, conf.Name, conf.Platform);
750
CollectMergetoprojectProperties (propGroup, mergeToProjectPropertyNames, mergeToProjectProperties);
753
// Move properties with common values from configurations to the main
755
foreach (KeyValuePair<string,string> prop in mergeToProjectProperties)
756
globalGroup.SetPropertyValue (prop.Key, prop.Value);
757
foreach (string prop in mergeToProjectPropertyNamesCopy) {
758
if (!mergeToProjectProperties.ContainsKey (prop))
759
globalGroup.RemoveProperty (prop);
761
foreach (SolutionItemConfiguration conf in eitem.Configurations) {
762
MSBuildPropertyGroup propGroup = FindPropertyGroup (configData, conf);
763
foreach (string mp in mergeToProjectProperties.Keys)
764
propGroup.RemoveProperty (mp);
769
Dictionary<string,ItemInfo> oldItems = new Dictionary<string, ItemInfo> ();
770
foreach (MSBuildItem item in msproject.GetAllItems ())
771
oldItems [item.Name + "<" + item.Include] = new ItemInfo () { Item=item };
774
foreach (object ob in ((SolutionEntityItem)Item).Items)
775
SaveItem (monitor, ser, msproject, ob, oldItems);
777
foreach (ItemInfo itemInfo in oldItems.Values) {
779
msproject.RemoveItem (itemInfo.Item);
782
if (dotNetProject != null) {
784
// If the format only supports one fx version, there is no need to store it
785
if (supportedFrameworks.Count > 1)
786
SetGroupProperty (globalGroup, "TargetFrameworkVersion", "v" + targetFramework, false);
788
globalGroup.RemoveProperty ("TargetFrameworkVersion");
792
// Impdate the imports section
794
List<string> currentImports = msproject.Imports;
795
List<string> imports = new List<string> (currentImports);
796
UpdateImports (imports);
797
foreach (string imp in imports) {
798
if (!currentImports.Contains (imp)) {
799
msproject.AddNewImport (imp, null);
800
currentImports.Add (imp);
803
foreach (string imp in currentImports) {
804
if (!imports.Contains (imp))
805
msproject.RemoveImport (imp);
808
DataItem extendedData = ser.ExternalItemProperties;
809
if (extendedData.HasItemData) {
810
extendedData.Name = "Properties";
811
StringWriter sw = new StringWriter ();
812
XmlConfigurationWriter.DefaultWriter.Write (new XmlTextWriter (sw), extendedData);
813
msproject.SetProjectExtensions ("MonoDevelop", sw.ToString ());
815
msproject.RemoveProjectExtensions ("MonoDevelop");
817
msproject.Save (eitem.FileName);
820
void CollectMergetoprojectProperties (MSBuildPropertyGroup pgroup, List<String> propertyNames, Dictionary<string,string> mergeToProjectProperties)
822
// This method checks every property in pgroup which has the MergeToProject flag.
823
// If the value of this property is the same as the one stored in mergeToProjectProperties
824
// it means that the property can be merged to the main project property group (so far).
826
foreach (string pname in new List<String> (propertyNames)) {
827
MSBuildProperty prop = pgroup.GetProperty (pname);
830
if (!mergeToProjectProperties.TryGetValue (pname, out mvalue)) {
832
// This is the first time the value is checked. Just assign it.
833
mergeToProjectProperties.Add (pname, prop.Value);
836
// If there is no value, it can't be merged
838
else if (prop != null && prop.Value == mvalue)
839
// Same value. It can be merged.
842
// The property can't be merged because different configurations have different
843
// values for it. Remove it from the list.
844
propertyNames.Remove (pname);
845
mergeToProjectProperties.Remove (pname);
850
void SaveItem (MonoDevelop.Core.IProgressMonitor monitor, MSBuildSerializer ser, MSBuildProject msproject, object ob, Dictionary<string,ItemInfo> oldItems)
852
if (ob is ProjectReference) {
853
SaveReference (monitor, ser, msproject, (ProjectReference) ob, oldItems);
855
else if (ob is ProjectFile) {
856
SaveProjectFile (ser, msproject, (ProjectFile) ob, oldItems);
860
if (ob is UnknownProjectItem)
861
itemName = ((UnknownProjectItem)ob).ItemName;
863
DataType dt = ser.DataContext.GetConfigurationDataType (ob.GetType ());
866
MSBuildItem buildItem = msproject.AddNewItem (itemName, "");
867
WriteBuildItemMetadata (ser, buildItem, ob, oldItems);
871
void SaveProjectFile (MSBuildSerializer ser, MSBuildProject msproject, ProjectFile file, Dictionary<string,ItemInfo> oldItems)
873
string itemName = (file.Subtype == Subtype.Directory)? "Folder" : file.BuildAction;
875
string path = MSBuildProjectService.ToMSBuildPath (Item.ItemDirectory, file.FilePath);
876
if (path.Length == 0)
879
//directory paths must end with '/'
880
if ((file.Subtype == Subtype.Directory) && path[path.Length-1] != '\\')
883
MSBuildItem buildItem = AddOrGetBuildItem (msproject, oldItems, itemName, path);
884
WriteBuildItemMetadata (ser, buildItem, file, oldItems);
886
if (!string.IsNullOrEmpty (file.DependsOn))
887
buildItem.SetMetadata ("DependentUpon", MSBuildProjectService.ToMSBuildPath (Path.GetDirectoryName (file.FilePath), file.DependsOn));
888
if (!string.IsNullOrEmpty (file.ContentType))
889
buildItem.SetMetadata ("SubType", file.ContentType);
891
if (!string.IsNullOrEmpty (file.Generator))
892
buildItem.SetMetadata ("Generator", file.Generator);
894
buildItem.UnsetMetadata ("Generator");
896
if (!string.IsNullOrEmpty (file.CustomToolNamespace))
897
buildItem.SetMetadata ("CustomToolNamespace", file.CustomToolNamespace);
899
buildItem.UnsetMetadata ("CustomToolNamespace");
901
if (!string.IsNullOrEmpty (file.LastGenOutput))
902
buildItem.SetMetadata ("LastGenOutput", file.LastGenOutput);
904
buildItem.UnsetMetadata ("LastGenOutput");
906
if (!string.IsNullOrEmpty (file.Link))
907
buildItem.SetMetadata ("Link", MSBuildProjectService.ToMSBuildPathRelative (Item.ItemDirectory, file.Link));
909
buildItem.UnsetMetadata ("Link");
911
buildItem.Condition = file.Condition;
913
if (file.CopyToOutputDirectory == FileCopyMode.None) {
914
buildItem.UnsetMetadata ("CopyToOutputDirectory");
916
buildItem.SetMetadata ("CopyToOutputDirectory", file.CopyToOutputDirectory.ToString ());
920
buildItem.SetMetadata ("Visible", "False");
922
buildItem.UnsetMetadata ("Visible");
925
if (file.BuildAction == BuildAction.EmbeddedResource) {
926
//Emit LogicalName only when it does not match the default Id
927
if (GetDefaultResourceId (file) != file.ResourceId)
928
buildItem.SetMetadata ("LogicalName", file.ResourceId);
932
void SaveReference (MonoDevelop.Core.IProgressMonitor monitor, MSBuildSerializer ser, MSBuildProject msproject, ProjectReference pref, Dictionary<string,ItemInfo> oldItems)
934
MSBuildItem buildItem;
935
if (pref.ReferenceType == ReferenceType.Assembly) {
937
string hintPath = null;
938
if (pref.ExtendedProperties.Contains ("_OriginalMSBuildReferenceInclude")) {
939
asm = (string) pref.ExtendedProperties ["_OriginalMSBuildReferenceInclude"];
940
hintPath = (string) pref.ExtendedProperties ["_OriginalMSBuildReferenceHintPath"];
943
if (File.Exists (pref.Reference)) {
945
asm = AssemblyName.GetAssemblyName (pref.Reference).FullName;
946
} catch (Exception ex) {
947
string msg = string.Format ("Could not get full name for assembly '{0}'.", pref.Reference);
948
monitor.ReportWarning (msg);
949
LoggingService.LogError (msg, ex);
952
string basePath = Item.ItemDirectory;
953
if (pref.ExtendedProperties.Contains ("_OriginalMSBuildReferenceIsAbsolute"))
955
hintPath = MSBuildProjectService.ToMSBuildPath (basePath, pref.Reference);
958
asm = Path.GetFileNameWithoutExtension (pref.Reference);
960
buildItem = AddOrGetBuildItem (msproject, oldItems, "Reference", asm);
961
if (!pref.SpecificVersion)
962
buildItem.SetMetadata ("SpecificVersion", "False");
964
buildItem.UnsetMetadata ("SpecificVersion");
965
buildItem.SetMetadata ("HintPath", hintPath);
967
buildItem.SetMetadata ("Private", "False");
969
buildItem.UnsetMetadata ("Private");
971
else if (pref.ReferenceType == ReferenceType.Gac) {
972
string include = pref.StoredReference;
973
SystemPackage pkg = pref.Package;
974
if (pkg != null && pkg.IsFrameworkPackage) {
975
int i = include.IndexOf (',');
977
include = include.Substring (0, i).Trim ();
979
buildItem = AddOrGetBuildItem (msproject, oldItems, "Reference", include);
980
if (!pref.SpecificVersion)
981
buildItem.SetMetadata ("SpecificVersion", "False");
983
buildItem.UnsetMetadata ("SpecificVersion");
984
IList supportedFrameworks = TargetFormat.FrameworkVersions;
985
if (pkg != null && pkg.IsFrameworkPackage && supportedFrameworks.Contains (pkg.TargetFramework) && pkg.TargetFramework != "2.0" && supportedFrameworks.Count > 1) {
986
TargetFramework fx = Runtime.SystemAssemblyService.GetTargetFramework (pkg.TargetFramework);
987
buildItem.SetMetadata ("RequiredTargetFramework", fx.Id);
989
buildItem.UnsetMetadata ("RequiredTargetFramework");
990
string hintPath = (string) pref.ExtendedProperties ["_OriginalMSBuildReferenceHintPath"];
991
if (hintPath != null)
992
buildItem.SetMetadata ("HintPath", hintPath);
994
buildItem.UnsetMetadata ("HintPath");
996
else if (pref.ReferenceType == ReferenceType.Project) {
997
Project refProj = Item.ParentSolution.FindProjectByName (pref.Reference);
998
if (refProj != null) {
999
buildItem = AddOrGetBuildItem (msproject, oldItems, "ProjectReference", MSBuildProjectService.ToMSBuildPath (Item.ItemDirectory, refProj.FileName));
1000
MSBuildProjectHandler handler = refProj.ItemHandler as MSBuildProjectHandler;
1001
if (handler != null)
1002
buildItem.SetMetadata ("Project", handler.Item.ItemId);
1004
buildItem.UnsetMetadata ("Project");
1005
buildItem.SetMetadata ("Name", refProj.Name);
1006
if (!pref.LocalCopy)
1007
buildItem.SetMetadata ("Private", "False");
1009
buildItem.UnsetMetadata ("Private");
1011
monitor.ReportWarning (GettextCatalog.GetString ("Reference to unknown project '{0}' ignored.", pref.Reference));
1017
DataType dt = ser.DataContext.GetConfigurationDataType (pref.GetType ());
1018
buildItem = AddOrGetBuildItem (msproject, oldItems, dt.Name, pref.Reference);
1020
WriteBuildItemMetadata (ser, buildItem, pref, oldItems);
1021
buildItem.Condition = pref.Condition;
1024
void UpdateImports (List<string> imports)
1026
if (targetImports != null) {
1027
foreach (string imp in targetImports)
1028
if (!imports.Contains (imp))
1031
foreach (IMSBuildImportProvider ip in AddinManager.GetExtensionObjects ("/MonoDevelop/ProjectModel/MSBuildImportProviders")) {
1032
ip.UpdateImports (EntityItem, imports);
1036
void UnmergeBaseConfiguration (List<ConfigData> configData, MSBuildPropertyGroup propGroup, string conf, string platform)
1038
MSBuildPropertyGroup baseGroup = null;
1040
foreach (ConfigData data in configData) {
1041
if (data.Group == propGroup)
1043
if ((data.Config == conf || data.Config == Unspecified) && (data.Platform == platform || data.Platform == Unspecified)) {
1044
if (baseGroup == null)
1045
baseGroup = data.Group;
1047
baseGroup = MSBuildPropertyGroup.Merge (baseGroup, data.Group);
1050
if (baseGroup != null)
1051
propGroup.UnMerge (baseGroup);
1054
void ReadBuildItemMetadata (DataSerializer ser, MSBuildItem buildItem, object dataItem, Type extendedType)
1056
DataItem ditem = new DataItem ();
1057
foreach (ItemProperty prop in ser.GetProperties (dataItem)) {
1058
string name = ToMsbuildItemName (prop.Name);
1059
if (name == "Include")
1060
ditem.ItemData.Add (new DataValue ("Include", buildItem.Include));
1061
else if (buildItem.HasMetadata (name)) {
1062
string data = buildItem.GetMetadata (name);
1063
ditem.ItemData.Add (GetDataNode (prop, data));
1066
ConvertFromMsbuildFormat (ditem);
1067
ser.Deserialize (dataItem, ditem);
1070
void WriteBuildItemMetadata (DataSerializer ser, MSBuildItem buildItem, object dataItem, Dictionary<string,ItemInfo> oldItems)
1072
var notWrittenProps = new HashSet<string> ();
1073
foreach (ItemProperty prop in ser.GetProperties (dataItem))
1074
notWrittenProps.Add (prop.Name);
1076
DataItem ditem = (DataItem) ser.Serialize (dataItem, dataItem.GetType ());
1077
if (ditem.HasItemData) {
1078
foreach (DataNode node in ditem.ItemData) {
1079
notWrittenProps.Remove (node.Name);
1080
if (node.Name == "Include" && node is DataValue)
1081
buildItem.Include = ((DataValue) node).Value;
1083
ConvertToMsbuildFormat (node);
1084
buildItem.SetMetadata (node.Name, GetXmlString (node), node is DataItem);
1088
foreach (string prop in notWrittenProps)
1089
buildItem.UnsetMetadata (prop);
1092
MSBuildItem AddOrGetBuildItem (MSBuildProject msproject, Dictionary<string,ItemInfo> oldItems, string name, string include)
1095
string key = name + "<" + include;
1096
if (oldItems.TryGetValue (key, out itemInfo)) {
1097
if (!itemInfo.Added) {
1098
itemInfo.Added = true;
1099
oldItems [key] = itemInfo;
1101
return itemInfo.Item;
1103
return msproject.AddNewItem (name, include);
1106
DataItem ReadPropertyGroupMetadata (DataSerializer ser, MSBuildPropertyGroup propGroup, object dataItem)
1108
DataItem ditem = new DataItem ();
1110
foreach (MSBuildProperty bprop in propGroup.Properties) {
1111
DataNode node = null;
1112
foreach (XmlNode xnode in bprop.Element.ChildNodes) {
1113
if (xnode is XmlElement) {
1114
node = XmlConfigurationReader.DefaultReader.Read ((XmlElement)xnode);
1119
node = new DataValue (bprop.Name, bprop.Value);
1121
ConvertFromMsbuildFormat (node);
1122
ditem.ItemData.Add (node);
1128
void WritePropertyGroupMetadata (MSBuildPropertyGroup propGroup, DataCollection itemData, MSBuildSerializer ser, params object[] itemsToReplace)
1130
var notWrittenProps = new HashSet<string> ();
1132
foreach (object ob in itemsToReplace) {
1135
ClassDataType dt = (ClassDataType) ser.DataContext.GetConfigurationDataType (ob.GetType ());
1136
foreach (ItemProperty prop in dt.GetProperties (ser.SerializationContext, ob))
1137
notWrittenProps.Add (prop.Name);
1140
foreach (DataNode node in itemData) {
1141
notWrittenProps.Remove (node.Name);
1142
ConvertToMsbuildFormat (node);
1143
SetGroupProperty (propGroup, node.Name, GetXmlString (node), node is DataItem);
1145
foreach (string prop in notWrittenProps)
1146
propGroup.RemoveProperty (prop);
1149
string ToMsbuildItemName (string name)
1151
return name.Replace ('.', '-');
1154
void ConvertToMsbuildFormat (DataNode node)
1156
ReplaceChar (node, true, '.', '-');
1159
void ConvertFromMsbuildFormat (DataNode node)
1161
ReplaceChar (node, true, '-', '.');
1164
void ReplaceChar (DataNode node, bool force, char oldChar, char newChar)
1166
DataItem it = node as DataItem;
1167
if ((force || it != null) && node.Name != null)
1168
node.Name = node.Name.Replace (oldChar, newChar);
1170
foreach (DataNode cnode in it.ItemData)
1171
ReplaceChar (cnode, !it.UniqueNames, oldChar, newChar);
1175
List<ConfigData> GetConfigData (MSBuildProject msproject)
1177
List<ConfigData> configData = new List<ConfigData> ();
1178
foreach (MSBuildPropertyGroup cgrp in msproject.PropertyGroups) {
1179
string conf, platform;
1180
if (ParseConfigCondition (cgrp.Condition, out conf, out platform))
1181
configData.Add (new ConfigData (conf, platform, cgrp));
1186
MSBuildProperty SetGroupProperty (MSBuildPropertyGroup propGroup, string name, string value, bool isLiteral)
1188
propGroup.SetPropertyValue (name, value);
1189
return propGroup.GetProperty (name);
1192
MSBuildPropertyGroup FindPropertyGroup (List<ConfigData> configData, SolutionItemConfiguration config)
1194
foreach (ConfigData data in configData) {
1195
if (data.Config == config.Name && data.Platform == config.Platform)
1201
ProjectFile ReadProjectFile (DataSerializer ser, Project project, MSBuildItem buildItem, Type type)
1203
string path = MSBuildProjectService.FromMSBuildPath (project.ItemDirectory, buildItem.Include);
1204
ProjectFile file = (ProjectFile) Activator.CreateInstance (type);
1206
file.BuildAction = buildItem.Name;
1208
ReadBuildItemMetadata (ser, buildItem, file, type);
1210
string dependentFile = buildItem.GetMetadata ("DependentUpon");
1211
if (!string.IsNullOrEmpty (dependentFile)) {
1212
dependentFile = MSBuildProjectService.FromMSBuildPath (Path.GetDirectoryName (path), dependentFile);
1213
file.DependsOn = dependentFile;
1216
string copyToOutputDirectory = buildItem.GetMetadata ("CopyToOutputDirectory");
1217
if (!string.IsNullOrEmpty (copyToOutputDirectory)) {
1218
switch (copyToOutputDirectory) {
1220
case "Always": file.CopyToOutputDirectory = FileCopyMode.Always; break;
1221
case "PreserveNewest": file.CopyToOutputDirectory = FileCopyMode.PreserveNewest; break;
1223
MonoDevelop.Core.LoggingService.LogWarning (
1224
"Unrecognised value {0} for CopyToOutputDirectory MSBuild property",
1225
copyToOutputDirectory);
1230
if (buildItem.GetMetadataIsFalse ("Visible"))
1231
file.Visible = false;
1234
string resourceId = buildItem.GetMetadata ("LogicalName");
1235
if (!string.IsNullOrEmpty (resourceId))
1236
file.ResourceId = resourceId;
1238
string contentType = buildItem.GetMetadata ("SubType");
1239
if (!string.IsNullOrEmpty (contentType))
1240
file.ContentType = contentType;
1242
string generator = buildItem.GetMetadata ("Generator");
1243
if (!string.IsNullOrEmpty (generator))
1244
file.Generator = generator;
1246
string customToolNamespace = buildItem.GetMetadata ("CustomToolNamespace");
1247
if (!string.IsNullOrEmpty (customToolNamespace))
1248
file.CustomToolNamespace = customToolNamespace;
1250
string lastGenOutput = buildItem.GetMetadata ("LastGenOutput");
1251
if (!string.IsNullOrEmpty (lastGenOutput))
1252
file.LastGenOutput = lastGenOutput;
1254
string link = buildItem.GetMetadata ("Link");
1255
if (!string.IsNullOrEmpty (link))
1256
file.Link = MSBuildProjectService.FromMSBuildPathRelative (project.ItemDirectory, link);
1258
file.Condition = buildItem.Condition;
1262
bool ParseConfigCondition (string cond, out string config, out string platform)
1264
config = platform = null;
1265
int i = cond.IndexOf ("==");
1268
if (cond.Substring (0, i).Trim () == "'$(Configuration)|$(Platform)'") {
1269
cond = cond.Substring (i+2).Trim (' ','\'');
1270
i = cond.IndexOf ('|');
1272
config = cond.Substring (0, i);
1273
platform = cond.Substring (i+1);
1275
// Invalid configuration
1278
if (platform == "AnyCPU")
1279
platform = string.Empty;
1282
else if (cond.Substring (0, i).Trim () == "'$(Configuration)'") {
1283
config = cond.Substring (i+2).Trim (' ','\'');
1284
platform = Unspecified;
1287
else if (cond.Substring (0, i).Trim () == "'$(Platform)'") {
1288
config = Unspecified;
1289
platform = cond.Substring (i+2).Trim (' ','\'');
1290
if (platform == "AnyCPU")
1291
platform = string.Empty;
1297
string BuildConfigCondition (string config, string platform)
1299
if (platform.Length == 0)
1300
platform = "AnyCPU";
1301
return " '$(Configuration)|$(Platform)' == '" + config + "|" + platform + "' ";
1304
bool IsMergeToProjectProperty (ItemProperty prop)
1306
foreach (object at in prop.CustomAttributes) {
1307
if (at is MergeToProjectAttribute)
1313
string FindClosestSupportedVersion (string version)
1315
TargetFramework sfx = Runtime.SystemAssemblyService.GetTargetFramework (version);
1316
if (!string.IsNullOrEmpty (sfx.SubsetOfFramework) && ((IList)TargetFormat.FrameworkVersions).Contains (sfx.SubsetOfFramework))
1317
return sfx.SubsetOfFramework;
1319
foreach (string supv in TargetFormat.FrameworkVersions) {
1320
TargetFramework fx = Runtime.SystemAssemblyService.GetTargetFramework (supv);
1321
if (fx.IsCompatibleWithFramework (version))
1324
return TargetFormat.FrameworkVersions [TargetFormat.FrameworkVersions.Length - 1];
1327
string GetXmlString (DataNode node)
1329
if (node is DataValue)
1330
return ((DataValue)node).Value;
1332
StringWriter sw = new StringWriter ();
1333
XmlTextWriter xw = new XmlTextWriter (sw);
1334
XmlConfigurationWriter.DefaultWriter.Write (xw, node);
1335
return sw.ToString ();
1339
DataNode GetDataNode (ItemProperty prop, string xmlString)
1341
if (prop.DataType.IsSimpleType)
1342
return new DataValue (prop.Name, xmlString);
1344
StringReader sr = new StringReader (xmlString);
1345
return XmlConfigurationReader.DefaultReader.Read (new XmlTextReader (sr));
1349
internal virtual MSBuildSerializer CreateSerializer ()
1351
return new MSBuildSerializer (EntityItem.FileName);
1354
static readonly MSBuildElementOrder globalConfigOrder = new MSBuildElementOrder (
1355
"Configuration","Platform","ProductVersion","SchemaVersion","ProjectGuid","ProjectTypeGuids", "OutputType",
1356
"AppDesignerFolder","RootNamespace","AssemblyName","StartupObject"
1358
static readonly MSBuildElementOrder configOrder = new MSBuildElementOrder (
1359
"DebugSymbols","DebugType","Optimize","OutputPath","DefineConstants","ErrorReport","WarningLevel",
1360
"TreatWarningsAsErrors","DocumentationFile"
1363
// Those are properties which are dynamically set by this file format
1365
internal static readonly ItemMember[] ExtendedMSBuildProperties = new ItemMember [] {
1366
new ItemMember (typeof(SolutionEntityItem), "ProductVersion"),
1367
new ItemMember (typeof(SolutionEntityItem), "SchemaVersion"),
1368
new ItemMember (typeof(SolutionEntityItem), "ProjectGuid"),
1369
new ItemMember (typeof(SolutionEntityItem), "ProjectTypeGuids"),
1370
new ItemMember (typeof(DotNetProjectConfiguration), "DebugType"),
1371
new ItemMember (typeof(DotNetProjectConfiguration), "ErrorReport"),
1372
new ItemMember (typeof(DotNetProjectConfiguration), "TargetFrameworkVersion"),
1373
new ItemMember (typeof(ProjectReference), "RequiredTargetFramework"),
1374
new ItemMember (typeof(Project), "InternalTargetFrameworkVersion", true),
1377
// Items generated by VS but which MD is not using and should be ignored
1379
internal static readonly IList<string> UnsupportedItems = new string[] {
1380
"BootstrapperFile", "AppDesigner", "WebReferences", "WebReferenceUrl", "Service"
1384
class MSBuildSerializer: DataSerializer
1386
public DataItem InternalItemProperties = new DataItem ();
1387
public DataItem ExternalItemProperties = new DataItem ();
1389
public MSBuildSerializer (string baseFile): base (MSBuildProjectService.DataContext)
1391
// Use windows separators
1392
SerializationContext.BaseFile = baseFile;
1393
SerializationContext.DirectorySeparatorChar = '\\';
1396
internal protected override bool CanHandleProperty (ItemProperty prop, SerializationContext serCtx, object instance)
1398
if (instance is Project) {
1399
if (prop.Name == "Contents")
1402
if (instance is DotNetProject) {
1403
if (prop.Name == "References" || prop.Name == "LanguageParameters")
1406
if (instance is SolutionEntityItem) {
1407
if (prop.IsExtendedProperty (typeof(SolutionEntityItem)))
1409
return prop.Name != "name" && prop.Name != "Configurations";
1411
if (instance is SolutionFolder) {
1412
if (prop.Name == "Files")
1415
if (instance is ProjectFile)
1416
return prop.IsExtendedProperty (typeof(ProjectFile));
1417
if (instance is ProjectReference)
1418
return prop.IsExtendedProperty (typeof(ProjectReference)) || prop.Name == "Package";
1419
if (instance is DotNetProjectConfiguration)
1420
if (prop.Name == "CodeGeneration")
1422
if (instance is ItemConfiguration)
1423
if (prop.Name == "name")
1428
internal protected override DataNode OnSerializeProperty (ItemProperty prop, SerializationContext serCtx, object instance, object value)
1430
DataNode data = base.OnSerializeProperty (prop, serCtx, instance, value);
1431
if (instance is SolutionEntityItem && data != null) {
1432
if (prop.IsExternal)
1433
ExternalItemProperties.ItemData.Add (data);
1435
InternalItemProperties.ItemData.Add (data);
1441
class MSBuildElementOrder: Dictionary<string, int>
1443
public MSBuildElementOrder (params string[] elements)
1445
for (int n=0; n<elements.Length; n++)
1446
this [elements [n]] = n;