~ubuntu-branches/ubuntu/saucy/monodevelop/saucy-proposed

« back to all changes in this revision

Viewing changes to src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectHandler.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2010-09-10 16:54:48 UTC
  • mfrom: (19.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20100910165448-0rybfk25zd4o9431
Tags: 2.4+dfsg-2
* debian/patches/inject_Mono.Debugger.Soft_source.patch,
  debian/patches/use_system_Mono.Debugger.Soft.patch,
  debian/control:
  + Build against system Soft Debugger, since we now have a new
    enough Mono to match MonoDevelop's required API

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// MSBuildProjectHandler.cs
 
2
//
 
3
// Author:
 
4
//   Lluis Sanchez Gual <lluis@novell.com>
 
5
//
 
6
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
 
7
//
 
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:
 
14
//
 
15
// The above copyright notice and this permission notice shall be included in
 
16
// all copies or substantial portions of the Software.
 
17
//
 
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
 
24
// THE SOFTWARE.
 
25
//
 
26
//
 
27
 
 
28
using System;
 
29
using System.Xml;
 
30
using System.IO;
 
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;
 
41
using Mono.Addins;
 
42
using System.Linq;
 
43
using MonoDevelop.Core.Instrumentation;
 
44
 
 
45
namespace MonoDevelop.Projects.Formats.MSBuild
 
46
{
 
47
        public class MSBuildProjectHandler: MSBuildHandler, IResourceHandler, IPathHandler, IAssemblyReferenceHandler
 
48
        {
 
49
                string fileContent;
 
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;
 
56
                ITimeTracker timer;
 
57
                
 
58
                struct ItemInfo {
 
59
                        public MSBuildItem Item;
 
60
                        public bool Added;
 
61
                }
 
62
                
 
63
                protected SolutionEntityItem EntityItem {
 
64
                        get { return (SolutionEntityItem) Item; }
 
65
                }
 
66
                
 
67
                public System.Collections.Generic.List<string> TargetImports {
 
68
                        get {
 
69
                                return targetImports;
 
70
                        }
 
71
                        set {
 
72
                                targetImports = value;
 
73
                        }
 
74
                }
 
75
 
 
76
                public void SetCustomResourceHandler (IResourceHandler value)
 
77
                {
 
78
                        customResourceHandler = value;
 
79
                }
 
80
 
 
81
                public List<string> SubtypeGuids {
 
82
                        get {
 
83
                                return subtypeGuids;
 
84
                        }
 
85
                }
 
86
                
 
87
                public MSBuildProjectHandler ()
 
88
                {
 
89
                }
 
90
                
 
91
                public MSBuildProjectHandler (string typeGuid, string import, string itemId)
 
92
                {
 
93
                        Initialize (typeGuid, import, itemId);
 
94
                }
 
95
                
 
96
                internal void Initialize (string typeGuid, string import, string itemId)
 
97
                {
 
98
                        base.Initialize (typeGuid, itemId);
 
99
                        if (import != null && import.Trim().Length > 0)
 
100
                                this.targetImports.AddRange (import.Split (':'));
 
101
                        
 
102
                        Runtime.SystemAssemblyService.DefaultRuntimeChanged += OnDefaultRuntimeChanged;
 
103
                }
 
104
                
 
105
                void OnDefaultRuntimeChanged (object o, EventArgs args)
 
106
                {
 
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;
 
112
                        }
 
113
                }
 
114
                
 
115
                RemoteProjectBuilder GetProjectBuilder ()
 
116
                {
 
117
                        SolutionEntityItem item = (SolutionEntityItem) Item;
 
118
                        TargetRuntime runtime = null;
 
119
                        TargetFramework fx;
 
120
                        if (item is IAssemblyProject) {
 
121
                                runtime = ((IAssemblyProject) item).TargetRuntime;
 
122
                                fx = ((IAssemblyProject) item).TargetFramework;
 
123
                        }
 
124
                        else {
 
125
                                runtime = Runtime.SystemAssemblyService.CurrentRuntime;
 
126
                                fx = Services.ProjectService.DefaultTargetFramework;
 
127
                        }
 
128
                        if (projectBuilder == null || lastBuildFx != fx) {
 
129
                                if (projectBuilder != null) {
 
130
                                        projectBuilder.Dispose ();
 
131
                                        projectBuilder = null;
 
132
                                }
 
133
                                projectBuilder = MSBuildProjectService.GetProjectBuilder (runtime, fx, item.FileName);
 
134
                                lastBuildFx = fx;
 
135
                        }
 
136
                        return projectBuilder;
 
137
                }
 
138
                
 
139
                public override void Dispose ()
 
140
                {
 
141
                        base.Dispose ();
 
142
                        if (projectBuilder != null) {
 
143
                                projectBuilder.Dispose ();
 
144
                                projectBuilder = null;
 
145
                        }
 
146
                        Runtime.SystemAssemblyService.DefaultRuntimeChanged -= OnDefaultRuntimeChanged;
 
147
                }
 
148
                
 
149
                IEnumerable<string> IAssemblyReferenceHandler.GetAssemblyReferences (ConfigurationSelector configuration)
 
150
                {
 
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))
 
157
                                        yield return s;
 
158
                        }
 
159
                        else {
 
160
                                DotNetProject item = Item as DotNetProject;
 
161
                                if (item == null)
 
162
                                        yield break;
 
163
                                foreach (ProjectReference pref in item.References.Where (pr => pr.ReferenceType != ReferenceType.Project)) {
 
164
                                        foreach (string asm in pref.GetReferencedFileNames (configuration))
 
165
                                                yield return asm;
 
166
                                }
 
167
                        }
 
168
                }
 
169
                
 
170
                public override BuildResult RunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration)
 
171
                {
 
172
                        if (PropertyService.Get ("MonoDevelop.Ide.BuildWithMSBuild", false)) {
 
173
                                SolutionEntityItem item = Item as SolutionEntityItem;
 
174
                                if (item != null) {
 
175
                                        
 
176
                                        SolutionItemConfiguration configObject = item.GetConfiguration (configuration);
 
177
                                
 
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);
 
182
                                        
 
183
                                        BuildResult br = new BuildResult ();
 
184
                                        foreach (MSBuildResult res in results) {
 
185
                                                if (res.IsWarning)
 
186
                                                        br.AddWarning (res.File, res.Line, res.Column, res.Code, res.Message);
 
187
                                                else
 
188
                                                        br.AddError (res.File, res.Line, res.Column, res.Code, res.Message);
 
189
                                        }
 
190
                                        return br;
 
191
                                }
 
192
                        }
 
193
                        else {
 
194
                                if (Item is DotNetProject) {
 
195
                                        MD1DotNetProjectHandler handler = new MD1DotNetProjectHandler ((DotNetProject)Item);
 
196
                                        return handler.RunTarget (monitor, target, configuration);
 
197
                                }
 
198
                        }
 
199
                        return null;
 
200
                }
 
201
                
 
202
                public string GetDefaultResourceId (ProjectFile file)
 
203
                {
 
204
                        if (customResourceHandler != null)
 
205
                                return customResourceHandler.GetDefaultResourceId (file);
 
206
                        else
 
207
                                return MSBuildResourceHandler.Instance.GetDefaultResourceId (file);
 
208
                }
 
209
                
 
210
                public string EncodePath (string path, string oldPath)
 
211
                {
 
212
                        string basePath = Path.GetDirectoryName (EntityItem.FileName);
 
213
                        return FileService.RelativeToAbsolutePath (basePath, path);
 
214
                }
 
215
                
 
216
                public string DecodePath (string path)
 
217
                {
 
218
                        string basePath = Path.GetDirectoryName (EntityItem.FileName);
 
219
                        return FileService.AbsoluteToRelativePath (basePath, path);
 
220
                }
 
221
 
 
222
                public SolutionEntityItem Load (IProgressMonitor monitor, string fileName, string language, Type itemClass)
 
223
                {
 
224
                        timer = Counters.ReadMSBuildProject.BeginTiming ();
 
225
                        
 
226
                        timer.Trace ("Reading project file");
 
227
                        MSBuildProject p = new MSBuildProject ();
 
228
                        fileContent = File.ReadAllText (fileName);
 
229
                        p.LoadXml (fileContent);
 
230
                        
 
231
                        timer.Trace ("Read project guids");
 
232
                        
 
233
                        MSBuildPropertyGroup globalGroup = p.GetGlobalPropertyGroup ();
 
234
                        
 
235
                        // Avoid crash if there is not global group
 
236
                        if (globalGroup == null)
 
237
                                globalGroup = p.AddNewPropertyGroup (false);
 
238
                        
 
239
                        string itemGuid = globalGroup.GetPropertyValue ("ProjectGuid");
 
240
                        string projectTypeGuids = globalGroup.GetPropertyValue ("ProjectTypeGuids");
 
241
                        string itemType = globalGroup.GetPropertyValue ("ItemType");
 
242
 
 
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);
 
249
                                }
 
250
                        }
 
251
                        
 
252
                        try {
 
253
                                timer.Trace ("Create item instance");
 
254
                                ProjectExtensionUtil.BeginLoadOperation ();
 
255
                                Item = CreateSolutionItem (language, projectTypeGuids, itemType, itemClass);
 
256
        
 
257
                                Item.SetItemHandler (this);
 
258
                                MSBuildProjectService.SetId (Item, itemGuid);
 
259
                                
 
260
                                SolutionEntityItem it = (SolutionEntityItem) Item;
 
261
                                
 
262
                                it.FileName = fileName;
 
263
                                it.Name = System.IO.Path.GetFileNameWithoutExtension (fileName);
 
264
                        
 
265
                                Load (monitor, p);
 
266
                                return it;
 
267
                                
 
268
                        } finally {
 
269
                                ProjectExtensionUtil.EndLoadOperation ();
 
270
                                timer.End ();
 
271
                        }
 
272
                }
 
273
                
 
274
                SolutionItem CreateSolutionItem (string language, string typeGuids, string itemType, Type itemClass)
 
275
                {
 
276
                        // All the parameters are optional, but at least one must be provided.
 
277
                        
 
278
                        SolutionItem item = null;
 
279
                        
 
280
                        if (!string.IsNullOrEmpty (typeGuids)) {
 
281
                                DotNetProjectSubtypeNode st = MSBuildProjectService.GetDotNetProjectSubtype (typeGuids);
 
282
                                if (st != null) {
 
283
                                        item = st.CreateInstance (language);
 
284
                                        if (!string.IsNullOrEmpty (st.Import))
 
285
                                                targetImports.AddRange (st.Import.Split (':'));
 
286
                                } else
 
287
                                        throw new InvalidOperationException ("Unknown solution item type.");
 
288
                        }
 
289
                        if (item == null && itemClass != null)
 
290
                                item = (SolutionItem) Activator.CreateInstance (itemClass);
 
291
                        
 
292
                        if (item == null && !string.IsNullOrEmpty (language))
 
293
                                item = new DotNetAssemblyProject (language);
 
294
                        
 
295
                        if (item == null) {
 
296
                                if (string.IsNullOrEmpty (itemType))
 
297
                                        throw new InvalidOperationException ("Unknown solution item type.");
 
298
                                        
 
299
                                DataType dt = MSBuildProjectService.DataContext.GetConfigurationDataType (itemType);
 
300
                                if (dt == null)
 
301
                                        throw new InvalidOperationException ("Unknown solution item type: " + itemType);
 
302
                                        
 
303
                                item = (SolutionItem) Activator.CreateInstance (dt.ValueType);
 
304
                        }
 
305
                        
 
306
                        // Basic initialization
 
307
                        
 
308
                        if (item is DotNetProject) {
 
309
                                DotNetProject p = (DotNetProject) item;
 
310
                                p.TargetFramework = Services.ProjectService.DefaultTargetFramework;
 
311
                        }
 
312
                        return item;
 
313
                }
 
314
                
 
315
                void Load (IProgressMonitor monitor, MSBuildProject msproject)
 
316
                {
 
317
                        timer.Trace ("Initialize serialization");
 
318
                        
 
319
                        MSBuildSerializer ser = CreateSerializer ();
 
320
                        ser.SerializationContext.BaseFile = EntityItem.FileName;
 
321
                        ser.SerializationContext.ProgressMonitor = monitor;
 
322
                        
 
323
                        MSBuildPropertyGroup globalGroup = msproject.GetGlobalPropertyGroup ();
 
324
                        
 
325
                        Item.SetItemHandler (this);
 
326
                        
 
327
                        DotNetProject dotNetProject = Item as DotNetProject;
 
328
                        
 
329
                        string frameworkVersion = null;
 
330
                        
 
331
                        // Read all items
 
332
                        
 
333
                        timer.Trace ("Read project items");
 
334
                        
 
335
                        foreach (MSBuildItem buildItem in msproject.GetAllItems ()) {
 
336
                                ProjectItem it = ReadItem (ser, buildItem);
 
337
                                if (it != null) {
 
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
 
342
                                }
 
343
                        }
 
344
                        
 
345
                        timer.Trace ("Read configurations");
 
346
                        
 
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);
 
353
                                
 
354
                                if (dotNetProject.LanguageParameters != null) {
 
355
                                        DataItem data = ReadPropertyGroupMetadata (ser, globalGroup, dotNetProject.LanguageParameters);
 
356
                                        ser.Deserialize (dotNetProject.LanguageParameters, data);
 
357
                                }
 
358
                        }
 
359
                        
 
360
                        // Read configurations
 
361
                        
 
362
                        List<ConfigData> configData = GetConfigData (msproject);
 
363
                        List<ConfigData> readConfigData = new List<ConfigData> ();
 
364
                        
 
365
                        MSBuildPropertyGroup mergedToProjectProperties = ExtractMergedtoprojectProperties (ser, globalGroup, EntityItem.CreateConfiguration ("Dummy"));
 
366
                        configData.Insert (0, new ConfigData (Unspecified, Unspecified, mergedToProjectProperties));
 
367
                        
 
368
                        foreach (ConfigData cgrp in configData) {
 
369
                                readConfigData.Add (cgrp);
 
370
 
 
371
                                string conf = cgrp.Config;
 
372
                                string platform = cgrp.Platform;
 
373
 
 
374
                                if (platform == Unspecified && conf != Unspecified && !ContainsSpecificPlatformConfiguration (configData, conf))
 
375
                                        platform = string.Empty;
 
376
 
 
377
                                // It may be a partial configuration
 
378
                                if (conf == Unspecified || platform == Unspecified)
 
379
                                        continue;
 
380
                                
 
381
                                MSBuildPropertyGroup grp = CreateMergedConfiguration (readConfigData, conf, platform);
 
382
                                SolutionItemConfiguration config = EntityItem.CreateConfiguration (conf);
 
383
                                
 
384
                                config.Platform = platform;
 
385
                                DataItem data = ReadPropertyGroupMetadata (ser, grp, config);
 
386
                                ser.Deserialize (config, data);
 
387
                                EntityItem.Configurations.Add (config);
 
388
                                
 
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);
 
394
                                        }
 
395
                                }
 
396
                        }
 
397
                        
 
398
                        // Read extended properties
 
399
                        
 
400
                        timer.Trace ("Read extended properties");
 
401
                        
 
402
                        DataItem globalData = ReadPropertyGroupMetadata (ser, globalGroup, Item);
 
403
                        
 
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);
 
409
                        }
 
410
                        ser.Deserialize (Item, globalData);
 
411
 
 
412
                        // Final initializations
 
413
                        
 
414
                        timer.Trace ("Final initializations");
 
415
                        
 
416
                        if (dotNetProject != null && string.IsNullOrEmpty (frameworkVersion)) {
 
417
                                string fx = Item.ExtendedProperties ["InternalTargetFrameworkVersion"] as string;
 
418
                                if (fx != null) {
 
419
                                        dotNetProject.TargetFramework = Runtime.SystemAssemblyService.GetTargetFramework (fx);
 
420
                                        Item.ExtendedProperties.Remove ("InternalTargetFrameworkVersion");
 
421
                                } else {
 
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");
 
424
                                }
 
425
                        }
 
426
                        
 
427
                        Item.NeedsReload = false;
 
428
                }
 
429
 
 
430
                MSBuildPropertyGroup ExtractMergedtoprojectProperties (MSBuildSerializer ser, MSBuildPropertyGroup pgroup, object ob)
 
431
                {
 
432
                        XmlDocument doc = new XmlDocument ();
 
433
                        MSBuildPropertyGroup res = new MSBuildPropertyGroup (doc.CreateElement ("PropGroup"));
 
434
                        
 
435
                        foreach (string propName in GetMergeToProjectProperties (ser, ob)) {
 
436
                                MSBuildProperty bp = pgroup.GetProperty (propName);
 
437
                                if (bp != null)
 
438
                                        res.SetPropertyValue (bp.Name, bp.Value);
 
439
                        }
 
440
                        return res;
 
441
                }
 
442
                
 
443
                IEnumerable<string> GetMergeToProjectProperties (MSBuildSerializer ser, object ob)
 
444
                {
 
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;
 
449
                        }
 
450
                }
 
451
 
 
452
                ProjectItem ReadItem (MSBuildSerializer ser, MSBuildItem buildItem)
 
453
                {
 
454
                        Project project = Item as Project;
 
455
                        DotNetProject dotNetProject = Item as DotNetProject;
 
456
                        
 
457
                        DataType dt = ser.DataContext.GetConfigurationDataType (buildItem.Name);
 
458
                        
 
459
                        if (project != null) {
 
460
                                if (buildItem.Name == "Folder") {
 
461
                                        // Read folders
 
462
                                        string path = MSBuildProjectService.FromMSBuildPath (project.ItemDirectory, buildItem.Include);
 
463
                                        return new ProjectFile () { Name = Path.GetDirectoryName (path), Subtype = Subtype.Directory };
 
464
                                }
 
465
                                else if (buildItem.Name == "Reference" && dotNetProject != null) {
 
466
                                        ProjectReference pref;
 
467
                                        if (buildItem.HasMetadata ("HintPath")) {
 
468
                                                string hintPath = buildItem.GetMetadata ("HintPath");
 
469
                                                string path;
 
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;
 
479
                                                } else {
 
480
                                                        pref = new ProjectReference (ReferenceType.Gac, buildItem.Include);
 
481
                                                        pref.ExtendedProperties ["_OriginalMSBuildReferenceHintPath"] = hintPath;
 
482
                                                }
 
483
                                                pref.LocalCopy = !buildItem.GetMetadataIsFalse ("Private");
 
484
                                        } else {
 
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")
 
490
                                                        asm = "System.Xml";
 
491
                                                else if (asm == "system")
 
492
                                                        asm = "System";
 
493
                                                pref = new ProjectReference (ReferenceType.Gac, asm);
 
494
                                        }
 
495
                                        pref.Condition = buildItem.Condition;
 
496
                                        pref.SpecificVersion = !buildItem.GetMetadataIsFalse ("SpecificVersion");
 
497
                                        ReadBuildItemMetadata (ser, buildItem, pref, typeof(ProjectReference));
 
498
                                        return pref;
 
499
                                }
 
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;
 
507
                                        return pref;
 
508
                                }
 
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));
 
513
                                }
 
514
                        }
 
515
                        
 
516
                        if (dt != null && typeof(ProjectItem).IsAssignableFrom (dt.ValueType)) {
 
517
                                ProjectItem obj = (ProjectItem) Activator.CreateInstance (dt.ValueType);
 
518
                                ReadBuildItemMetadata (ser, buildItem, obj, dt.ValueType);
 
519
                                return obj;
 
520
                        }
 
521
                        
 
522
                        UnknownProjectItem uitem = new UnknownProjectItem (buildItem.Name, "");
 
523
                        ReadBuildItemMetadata (ser, buildItem, uitem, typeof(UnknownProjectItem));
 
524
                        
 
525
                        return uitem;
 
526
                }
 
527
 
 
528
                bool IsValidFile (string path)
 
529
                {
 
530
                        // If it is an absolute uri, it's not a valid file
 
531
                        try {
 
532
                                return !Uri.IsWellFormedUriString (path, UriKind.Absolute);
 
533
                        } catch {
 
534
                                // Old mono versions may crash in IsWellFormedUriString if the path
 
535
                                // is not an uri.
 
536
                                return true;
 
537
                        }
 
538
                }
 
539
                
 
540
                class ConfigData
 
541
                {
 
542
                        public ConfigData (string conf, string plt, MSBuildPropertyGroup grp)
 
543
                        {
 
544
                                Config = conf;
 
545
                                Platform = plt;
 
546
                                Group = grp;
 
547
                        }
 
548
                        
 
549
                        public string Config;
 
550
                        public string Platform;
 
551
                        public MSBuildPropertyGroup Group;
 
552
                }
 
553
 
 
554
                MSBuildPropertyGroup CreateMergedConfiguration (List<ConfigData> configData, string conf, string platform)
 
555
                {
 
556
                        MSBuildPropertyGroup merged = null;
 
557
                        
 
558
                        foreach (ConfigData grp in configData) {
 
559
                                if ((grp.Config == conf || grp.Config == Unspecified) && (grp.Platform == platform || grp.Platform == Unspecified)) {
 
560
                                        if (merged == null)
 
561
                                                merged = grp.Group;
 
562
                                        else
 
563
                                                merged = MSBuildPropertyGroup.Merge (merged, grp.Group);
 
564
                                }
 
565
                        }
 
566
                        return merged;
 
567
                }
 
568
 
 
569
                bool ContainsSpecificPlatformConfiguration (List<ConfigData> configData, string conf)
 
570
                {
 
571
                        foreach (ConfigData grp in configData) {
 
572
                                if (grp.Config == conf && grp.Platform != Unspecified)
 
573
                                        return true;
 
574
                        }
 
575
                        return false;
 
576
                }
 
577
 
 
578
                protected override void SaveItem (MonoDevelop.Core.IProgressMonitor monitor)
 
579
                {
 
580
                        if (Item is UnknownProject || Item is UnknownSolutionItem)
 
581
                                return;
 
582
                        
 
583
                        bool newProject = false;
 
584
                        SolutionEntityItem eitem = EntityItem;
 
585
                        
 
586
                        MSBuildSerializer ser = CreateSerializer ();
 
587
                        ser.SerializationContext.BaseFile = eitem.FileName;
 
588
                        ser.SerializationContext.ProgressMonitor = monitor;
 
589
                        
 
590
                        DotNetProject dotNetProject = Item as DotNetProject;
 
591
                        
 
592
                        MSBuildProject msproject = new MSBuildProject ();
 
593
                        if (fileContent != null) {
 
594
                                msproject.LoadXml (fileContent);
 
595
                        } else {
 
596
                                msproject.DefaultTargets = "Build";
 
597
                                newProject = true;
 
598
                        }
 
599
 
 
600
                        // Global properties
 
601
                        
 
602
                        MSBuildPropertyGroup globalGroup = msproject.GetGlobalPropertyGroup ();
 
603
                        if (globalGroup == null) {
 
604
                                globalGroup = msproject.AddNewPropertyGroup (false);
 
605
                        }
 
606
                        
 
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)' == '' ";
 
612
                                
 
613
                                string platform = conf.Platform.Length == 0 ? "AnyCPU" : conf.Platform;
 
614
                                bprop = SetGroupProperty (globalGroup, "Platform", platform, false);
 
615
                                bprop.Condition = " '$(Platform)' == '' ";
 
616
                        }
 
617
                        
 
618
                        if (TypeGuid == MSBuildProjectService.GenericItemGuid) {
 
619
                                DataType dt = MSBuildProjectService.DataContext.GetConfigurationDataType (Item.GetType ());
 
620
                                SetGroupProperty (globalGroup, "ItemType", dt.Name, false);
 
621
                        }
 
622
 
 
623
                        Item.ExtendedProperties ["ProjectGuid"] = Item.ItemId;
 
624
                        if (subtypeGuids.Count > 0) {
 
625
                                string gg = "";
 
626
                                foreach (string sg in subtypeGuids) {
 
627
                                        if (gg.Length > 0)
 
628
                                                gg += ";";
 
629
                                        gg += sg;
 
630
                                }
 
631
                                gg += ";" + TypeGuid;
 
632
                                Item.ExtendedProperties ["ProjectTypeGuids"] = gg.ToUpper ();
 
633
                        }
 
634
                        else
 
635
                                Item.ExtendedProperties.Remove ("ProjectTypeGuids");
 
636
 
 
637
                        string productVersion = (string) Item.ExtendedProperties ["ProductVersion"];
 
638
                        if (productVersion == null) {
 
639
                                Item.ExtendedProperties ["ProductVersion"] = TargetFormat.ProductVersion;
 
640
                                productVersion = TargetFormat.ProductVersion;
 
641
                        }
 
642
 
 
643
                        Item.ExtendedProperties ["SchemaVersion"] = "2.0";
 
644
                        
 
645
                        if (TargetFormat.ToolsVersion != "2.0")
 
646
                                msproject.ToolsVersion = TargetFormat.ToolsVersion;
 
647
                        else
 
648
                                msproject.ToolsVersion = string.Empty;
 
649
 
 
650
                        
 
651
                        string targetFramework = null;
 
652
                        IList supportedFrameworks = TargetFormat.FrameworkVersions;
 
653
                        
 
654
                        if (dotNetProject != null) {
 
655
 
 
656
                                targetFramework = dotNetProject.TargetFramework.Id;
 
657
 
 
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);
 
663
                                } else
 
664
                                        dotNetProject.ExtendedProperties.Remove ("InternalTargetFrameworkVersion");
 
665
                        }
 
666
 
 
667
                        // This serialize call will write data to ser.InternalItemProperties and ser.ExternalItemProperties
 
668
                        ser.Serialize (Item, Item.GetType ());
 
669
                        
 
670
                        object langParams = null;
 
671
                        
 
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];
 
677
                                        if (n != null)
 
678
                                                ser.InternalItemProperties.ItemData.Remove (n);
 
679
                                }
 
680
                                DataItem ditemComp = (DataItem) ser.Serialize (dotNetProject.LanguageParameters);
 
681
                                ser.InternalItemProperties.ItemData.AddRange (ditemComp.ItemData);
 
682
                                langParams = dotNetProject.LanguageParameters;
 
683
                        }
 
684
                        
 
685
                        if (fileContent == null)
 
686
                                ser.InternalItemProperties.ItemData.Sort (globalConfigOrder);
 
687
 
 
688
                        WritePropertyGroupMetadata (globalGroup, ser.InternalItemProperties.ItemData, ser, Item, langParams);
 
689
                        
 
690
                        // Convert debug property
 
691
                        
 
692
                        foreach (SolutionItemConfiguration conf in eitem.Configurations) {
 
693
                                DotNetProjectConfiguration cp = conf as MonoDevelop.Projects.DotNetProjectConfiguration;
 
694
                                if (cp != null) {
 
695
                                        if (newProject)
 
696
                                                cp.ExtendedProperties ["ErrorReport"] = "prompt";
 
697
                                        
 
698
                                        string debugType = (string) cp.ExtendedProperties ["DebugType"];
 
699
                                        if (cp.DebugMode) {
 
700
                                                if (debugType != "full" && debugType != "pdbonly")
 
701
                                                        cp.ExtendedProperties ["DebugType"] = "full";
 
702
                                        }
 
703
                                        else if (debugType != "none" && debugType != "pdbonly")
 
704
                                                cp.ExtendedProperties ["DebugType"] = "none";
 
705
                                }
 
706
                        }
 
707
                        
 
708
                        // Configurations
 
709
 
 
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);
 
715
                                
 
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);
 
723
                                                configData.Add (cd);
 
724
                                                newConf = true;
 
725
                                        }
 
726
                                        
 
727
                                        DotNetProjectConfiguration netConfig = conf as DotNetProjectConfiguration;
 
728
                                        
 
729
                                        DataItem ditem = (DataItem) ser.Serialize (conf);
 
730
                                        
 
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];
 
736
                                                        if (n != null)
 
737
                                                                ditem.ItemData.Remove (n);
 
738
                                                }
 
739
                                                DataItem ditemComp = (DataItem) ser.Serialize (netConfig.CompilationParameters);
 
740
                                                ditem.ItemData.AddRange (ditemComp.ItemData);
 
741
                                        }
 
742
        
 
743
                                        if (newConf)
 
744
                                                ditem.ItemData.Sort (configOrder);
 
745
                                        
 
746
                                        WritePropertyGroupMetadata (propGroup, ditem.ItemData, ser, conf, netConfig != null ? netConfig.CompilationParameters : null);
 
747
                                        
 
748
                                        UnmergeBaseConfiguration (configData, propGroup, conf.Name, conf.Platform);
 
749
                                        
 
750
                                        CollectMergetoprojectProperties (propGroup, mergeToProjectPropertyNames, mergeToProjectProperties);
 
751
                                }
 
752
                                
 
753
                                // Move properties with common values from configurations to the main
 
754
                                // property group
 
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);
 
760
                                }
 
761
                                foreach (SolutionItemConfiguration conf in eitem.Configurations) {
 
762
                                        MSBuildPropertyGroup propGroup = FindPropertyGroup (configData, conf);
 
763
                                        foreach (string mp in mergeToProjectProperties.Keys)
 
764
                                                propGroup.RemoveProperty (mp);
 
765
                                }
 
766
                        }
 
767
                        
 
768
                        // Remove old items
 
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 };
 
772
                        
 
773
                        // Add the new items
 
774
                        foreach (object ob in ((SolutionEntityItem)Item).Items)
 
775
                                SaveItem (monitor, ser, msproject, ob, oldItems);
 
776
                        
 
777
                        foreach (ItemInfo itemInfo in oldItems.Values) {
 
778
                                if (!itemInfo.Added)
 
779
                                        msproject.RemoveItem (itemInfo.Item);
 
780
                        }
 
781
                
 
782
                        if (dotNetProject != null) {
 
783
 
 
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);
 
787
                                else
 
788
                                        globalGroup.RemoveProperty ("TargetFrameworkVersion");
 
789
                                
 
790
                        }
 
791
 
 
792
                        // Impdate the imports section
 
793
                        
 
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);
 
801
                                }
 
802
                        }
 
803
                        foreach (string imp in currentImports) {
 
804
                                if (!imports.Contains (imp))
 
805
                                        msproject.RemoveImport (imp);
 
806
                        }
 
807
                        
 
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 ());
 
814
                        } else
 
815
                                msproject.RemoveProjectExtensions ("MonoDevelop");
 
816
                        
 
817
                        msproject.Save (eitem.FileName);
 
818
                }
 
819
 
 
820
                void CollectMergetoprojectProperties (MSBuildPropertyGroup pgroup, List<String> propertyNames, Dictionary<string,string> mergeToProjectProperties)
 
821
                {
 
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).
 
825
                        
 
826
                        foreach (string pname in new List<String> (propertyNames)) {
 
827
                                MSBuildProperty prop = pgroup.GetProperty (pname);
 
828
                                
 
829
                                string mvalue;
 
830
                                if (!mergeToProjectProperties.TryGetValue (pname, out mvalue)) {
 
831
                                        if (prop != null) {
 
832
                                                // This is the first time the value is checked. Just assign it.
 
833
                                                mergeToProjectProperties.Add (pname, prop.Value);
 
834
                                                continue;
 
835
                                        }
 
836
                                        // If there is no value, it can't be merged
 
837
                                }
 
838
                                else if (prop != null && prop.Value == mvalue)
 
839
                                        // Same value. It can be merged.
 
840
                                        continue;
 
841
 
 
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);
 
846
                        }
 
847
                }
 
848
 
 
849
                
 
850
                void SaveItem (MonoDevelop.Core.IProgressMonitor monitor, MSBuildSerializer ser, MSBuildProject msproject, object ob, Dictionary<string,ItemInfo> oldItems)
 
851
                {
 
852
                        if (ob is ProjectReference) {
 
853
                                SaveReference (monitor, ser, msproject, (ProjectReference) ob, oldItems);
 
854
                        }
 
855
                        else if (ob is ProjectFile) {
 
856
                                SaveProjectFile (ser, msproject, (ProjectFile) ob, oldItems);
 
857
                        }
 
858
                        else {
 
859
                                string itemName;
 
860
                                if (ob is UnknownProjectItem)
 
861
                                        itemName = ((UnknownProjectItem)ob).ItemName;
 
862
                                else {
 
863
                                        DataType dt = ser.DataContext.GetConfigurationDataType (ob.GetType ());
 
864
                                        itemName = dt.Name;
 
865
                                }
 
866
                                MSBuildItem buildItem = msproject.AddNewItem (itemName, "");
 
867
                                WriteBuildItemMetadata (ser, buildItem, ob, oldItems);
 
868
                        }
 
869
                }
 
870
                
 
871
                void SaveProjectFile (MSBuildSerializer ser, MSBuildProject msproject, ProjectFile file, Dictionary<string,ItemInfo> oldItems)
 
872
                {
 
873
                        string itemName = (file.Subtype == Subtype.Directory)? "Folder" : file.BuildAction;
 
874
 
 
875
                        string path = MSBuildProjectService.ToMSBuildPath (Item.ItemDirectory, file.FilePath);
 
876
                        if (path.Length == 0)
 
877
                                return;
 
878
                        
 
879
                        //directory paths must end with '/'
 
880
                        if ((file.Subtype == Subtype.Directory) && path[path.Length-1] != '\\')
 
881
                                path = path + "\\";
 
882
                        
 
883
                        MSBuildItem buildItem = AddOrGetBuildItem (msproject, oldItems, itemName, path);
 
884
                        WriteBuildItemMetadata (ser, buildItem, file, oldItems);
 
885
                        
 
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);
 
890
                        
 
891
                        if (!string.IsNullOrEmpty (file.Generator))
 
892
                                buildItem.SetMetadata ("Generator", file.Generator);
 
893
                        else
 
894
                                buildItem.UnsetMetadata ("Generator");
 
895
                        
 
896
                        if (!string.IsNullOrEmpty (file.CustomToolNamespace))
 
897
                                buildItem.SetMetadata ("CustomToolNamespace", file.CustomToolNamespace);
 
898
                        else
 
899
                                buildItem.UnsetMetadata ("CustomToolNamespace");
 
900
                        
 
901
                        if (!string.IsNullOrEmpty (file.LastGenOutput))
 
902
                                buildItem.SetMetadata ("LastGenOutput", file.LastGenOutput);
 
903
                        else
 
904
                                buildItem.UnsetMetadata ("LastGenOutput");
 
905
                        
 
906
                        if (!string.IsNullOrEmpty (file.Link))
 
907
                                buildItem.SetMetadata ("Link", MSBuildProjectService.ToMSBuildPathRelative (Item.ItemDirectory, file.Link));
 
908
                        else
 
909
                                buildItem.UnsetMetadata ("Link");
 
910
                        
 
911
                        buildItem.Condition = file.Condition;
 
912
                        
 
913
                        if (file.CopyToOutputDirectory == FileCopyMode.None) {
 
914
                                buildItem.UnsetMetadata ("CopyToOutputDirectory");
 
915
                        } else {
 
916
                                buildItem.SetMetadata ("CopyToOutputDirectory", file.CopyToOutputDirectory.ToString ());
 
917
                        }
 
918
                        
 
919
                        if (!file.Visible) {
 
920
                                buildItem.SetMetadata ("Visible", "False");
 
921
                        } else {
 
922
                                buildItem.UnsetMetadata ("Visible");
 
923
                        }
 
924
                        
 
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);
 
929
                        }
 
930
                }
 
931
                
 
932
                void SaveReference (MonoDevelop.Core.IProgressMonitor monitor, MSBuildSerializer ser, MSBuildProject msproject, ProjectReference pref, Dictionary<string,ItemInfo> oldItems)
 
933
                {
 
934
                        MSBuildItem buildItem;
 
935
                        if (pref.ReferenceType == ReferenceType.Assembly) {
 
936
                                string asm = null;
 
937
                                string hintPath = null;
 
938
                                if (pref.ExtendedProperties.Contains ("_OriginalMSBuildReferenceInclude")) {
 
939
                                        asm = (string) pref.ExtendedProperties ["_OriginalMSBuildReferenceInclude"];
 
940
                                        hintPath = (string) pref.ExtendedProperties ["_OriginalMSBuildReferenceHintPath"];
 
941
                                }
 
942
                                else {
 
943
                                        if (File.Exists (pref.Reference)) {
 
944
                                                try {
 
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);
 
950
                                                }
 
951
                                        }
 
952
                                        string basePath = Item.ItemDirectory;
 
953
                                        if (pref.ExtendedProperties.Contains ("_OriginalMSBuildReferenceIsAbsolute"))
 
954
                                                basePath = null;
 
955
                                        hintPath = MSBuildProjectService.ToMSBuildPath (basePath, pref.Reference);
 
956
                                }
 
957
                                if (asm == null)
 
958
                                        asm = Path.GetFileNameWithoutExtension (pref.Reference);
 
959
                                
 
960
                                buildItem = AddOrGetBuildItem (msproject, oldItems, "Reference", asm);
 
961
                                if (!pref.SpecificVersion)
 
962
                                        buildItem.SetMetadata ("SpecificVersion", "False");
 
963
                                else
 
964
                                        buildItem.UnsetMetadata ("SpecificVersion");
 
965
                                buildItem.SetMetadata ("HintPath", hintPath);
 
966
                                if (!pref.LocalCopy)
 
967
                                        buildItem.SetMetadata ("Private", "False");
 
968
                                else
 
969
                                        buildItem.UnsetMetadata ("Private");
 
970
                        }
 
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 (',');
 
976
                                        if (i != -1)
 
977
                                                include = include.Substring (0, i).Trim ();
 
978
                                }
 
979
                                buildItem = AddOrGetBuildItem (msproject, oldItems, "Reference", include);
 
980
                                if (!pref.SpecificVersion)
 
981
                                        buildItem.SetMetadata ("SpecificVersion", "False");
 
982
                                else
 
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);
 
988
                                } else
 
989
                                        buildItem.UnsetMetadata ("RequiredTargetFramework");
 
990
                                string hintPath = (string) pref.ExtendedProperties ["_OriginalMSBuildReferenceHintPath"];
 
991
                                if (hintPath != null)
 
992
                                        buildItem.SetMetadata ("HintPath", hintPath);
 
993
                                else
 
994
                                        buildItem.UnsetMetadata ("HintPath");
 
995
                        }
 
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);
 
1003
                                        else
 
1004
                                                buildItem.UnsetMetadata ("Project");
 
1005
                                        buildItem.SetMetadata ("Name", refProj.Name);
 
1006
                                        if (!pref.LocalCopy)
 
1007
                                                buildItem.SetMetadata ("Private", "False");
 
1008
                                        else
 
1009
                                                buildItem.UnsetMetadata ("Private");
 
1010
                                } else {
 
1011
                                        monitor.ReportWarning (GettextCatalog.GetString ("Reference to unknown project '{0}' ignored.", pref.Reference));
 
1012
                                        return;
 
1013
                                }
 
1014
                        }
 
1015
                        else {
 
1016
                                // Custom
 
1017
                                DataType dt = ser.DataContext.GetConfigurationDataType (pref.GetType ());
 
1018
                                buildItem = AddOrGetBuildItem (msproject, oldItems, dt.Name, pref.Reference);
 
1019
                        }
 
1020
                        WriteBuildItemMetadata (ser, buildItem, pref, oldItems);
 
1021
                        buildItem.Condition = pref.Condition;
 
1022
                }
 
1023
                
 
1024
                void UpdateImports (List<string> imports)
 
1025
                {
 
1026
                        if (targetImports != null) {
 
1027
                                foreach (string imp in targetImports)
 
1028
                                        if (!imports.Contains (imp))
 
1029
                                                imports.Add (imp);
 
1030
                        }
 
1031
                        foreach (IMSBuildImportProvider ip in AddinManager.GetExtensionObjects ("/MonoDevelop/ProjectModel/MSBuildImportProviders")) {
 
1032
                                ip.UpdateImports (EntityItem, imports);
 
1033
                        }
 
1034
                }
 
1035
 
 
1036
                void UnmergeBaseConfiguration (List<ConfigData> configData, MSBuildPropertyGroup propGroup, string conf, string platform)
 
1037
                {
 
1038
                        MSBuildPropertyGroup baseGroup = null;
 
1039
                        
 
1040
                        foreach (ConfigData data in configData) {
 
1041
                                if (data.Group == propGroup)
 
1042
                                        break;
 
1043
                                if ((data.Config == conf || data.Config == Unspecified) && (data.Platform == platform || data.Platform == Unspecified)) {
 
1044
                                        if (baseGroup == null)
 
1045
                                                baseGroup = data.Group;
 
1046
                                        else
 
1047
                                                baseGroup = MSBuildPropertyGroup.Merge (baseGroup, data.Group);
 
1048
                                }
 
1049
                        }
 
1050
                        if (baseGroup != null)
 
1051
                                propGroup.UnMerge (baseGroup);
 
1052
                }
 
1053
                
 
1054
                void ReadBuildItemMetadata (DataSerializer ser, MSBuildItem buildItem, object dataItem, Type extendedType)
 
1055
                {
 
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));
 
1064
                                }
 
1065
                        }
 
1066
                        ConvertFromMsbuildFormat (ditem);
 
1067
                        ser.Deserialize (dataItem, ditem);
 
1068
                }
 
1069
                
 
1070
                void WriteBuildItemMetadata (DataSerializer ser, MSBuildItem buildItem, object dataItem, Dictionary<string,ItemInfo> oldItems)
 
1071
                {
 
1072
                        var notWrittenProps = new HashSet<string> ();
 
1073
                        foreach (ItemProperty prop in ser.GetProperties (dataItem))
 
1074
                                notWrittenProps.Add (prop.Name);
 
1075
                        
 
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;
 
1082
                                        else {
 
1083
                                                ConvertToMsbuildFormat (node);
 
1084
                                                buildItem.SetMetadata (node.Name, GetXmlString (node), node is DataItem);
 
1085
                                        }
 
1086
                                }
 
1087
                        }
 
1088
                        foreach (string prop in notWrittenProps)
 
1089
                                buildItem.UnsetMetadata (prop);
 
1090
                }
 
1091
                
 
1092
                MSBuildItem AddOrGetBuildItem (MSBuildProject msproject, Dictionary<string,ItemInfo> oldItems, string name, string include)
 
1093
                {
 
1094
                        ItemInfo itemInfo;
 
1095
                        string key = name + "<" + include;
 
1096
                        if (oldItems.TryGetValue (key, out itemInfo)) {
 
1097
                                if (!itemInfo.Added) {
 
1098
                                        itemInfo.Added = true;
 
1099
                                        oldItems [key] = itemInfo;
 
1100
                                }
 
1101
                                return itemInfo.Item;
 
1102
                        } else
 
1103
                                return msproject.AddNewItem (name, include);
 
1104
                }
 
1105
                
 
1106
                DataItem ReadPropertyGroupMetadata (DataSerializer ser, MSBuildPropertyGroup propGroup, object dataItem)
 
1107
                {
 
1108
                        DataItem ditem = new DataItem ();
 
1109
 
 
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);
 
1115
                                                break;
 
1116
                                        }
 
1117
                                }
 
1118
                                if (node == null)
 
1119
                                        node = new DataValue (bprop.Name, bprop.Value);
 
1120
                                
 
1121
                                ConvertFromMsbuildFormat (node);
 
1122
                                ditem.ItemData.Add (node);
 
1123
                        }
 
1124
                        
 
1125
                        return ditem;
 
1126
                }
 
1127
                
 
1128
                void WritePropertyGroupMetadata (MSBuildPropertyGroup propGroup, DataCollection itemData, MSBuildSerializer ser, params object[] itemsToReplace)
 
1129
                {
 
1130
                        var notWrittenProps = new HashSet<string> ();
 
1131
                        
 
1132
                        foreach (object ob in itemsToReplace) {
 
1133
                                if (ob == null)
 
1134
                                        continue;
 
1135
                                ClassDataType dt = (ClassDataType) ser.DataContext.GetConfigurationDataType (ob.GetType ());
 
1136
                                foreach (ItemProperty prop in dt.GetProperties (ser.SerializationContext, ob))
 
1137
                                        notWrittenProps.Add (prop.Name);
 
1138
                        }
 
1139
        
 
1140
                        foreach (DataNode node in itemData) {
 
1141
                                notWrittenProps.Remove (node.Name);
 
1142
                                ConvertToMsbuildFormat (node);
 
1143
                                SetGroupProperty (propGroup, node.Name, GetXmlString (node), node is DataItem);
 
1144
                        }
 
1145
                        foreach (string prop in notWrittenProps)
 
1146
                                propGroup.RemoveProperty (prop);
 
1147
                }
 
1148
                
 
1149
                string ToMsbuildItemName (string name)
 
1150
                {
 
1151
                        return name.Replace ('.', '-');
 
1152
                }
 
1153
 
 
1154
                void ConvertToMsbuildFormat (DataNode node)
 
1155
                {
 
1156
                        ReplaceChar (node, true, '.', '-');
 
1157
                }
 
1158
                
 
1159
                void ConvertFromMsbuildFormat (DataNode node)
 
1160
                {
 
1161
                        ReplaceChar (node, true, '-', '.');
 
1162
                }
 
1163
                
 
1164
                void ReplaceChar (DataNode node, bool force, char oldChar, char newChar)
 
1165
                {
 
1166
                        DataItem it = node as DataItem;
 
1167
                        if ((force || it != null) && node.Name != null)
 
1168
                                node.Name = node.Name.Replace (oldChar, newChar);
 
1169
                        if (it != null) {
 
1170
                                foreach (DataNode cnode in it.ItemData)
 
1171
                                        ReplaceChar (cnode, !it.UniqueNames, oldChar, newChar);
 
1172
                        }
 
1173
                }
 
1174
 
 
1175
                List<ConfigData> GetConfigData (MSBuildProject msproject)
 
1176
                {
 
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));
 
1182
                        }
 
1183
                        return configData;
 
1184
                }
 
1185
                
 
1186
                MSBuildProperty SetGroupProperty (MSBuildPropertyGroup propGroup, string name, string value, bool isLiteral)
 
1187
                {
 
1188
                        propGroup.SetPropertyValue (name, value);
 
1189
                        return propGroup.GetProperty (name);
 
1190
                }
 
1191
                
 
1192
                MSBuildPropertyGroup FindPropertyGroup (List<ConfigData> configData, SolutionItemConfiguration config)
 
1193
                {
 
1194
                        foreach (ConfigData data in configData) {
 
1195
                                if (data.Config == config.Name && data.Platform == config.Platform)
 
1196
                                        return data.Group;
 
1197
                        }
 
1198
                        return null;
 
1199
                }
 
1200
                
 
1201
                ProjectFile ReadProjectFile (DataSerializer ser, Project project, MSBuildItem buildItem, Type type)
 
1202
                {
 
1203
                        string path = MSBuildProjectService.FromMSBuildPath (project.ItemDirectory, buildItem.Include);
 
1204
                        ProjectFile file = (ProjectFile) Activator.CreateInstance (type);
 
1205
                        file.Name = path;
 
1206
                        file.BuildAction = buildItem.Name;
 
1207
                        
 
1208
                        ReadBuildItemMetadata (ser, buildItem, file, type);
 
1209
                        
 
1210
                        string dependentFile = buildItem.GetMetadata ("DependentUpon");
 
1211
                        if (!string.IsNullOrEmpty (dependentFile)) {
 
1212
                                dependentFile = MSBuildProjectService.FromMSBuildPath (Path.GetDirectoryName (path), dependentFile);
 
1213
                                file.DependsOn = dependentFile;
 
1214
                        }
 
1215
                        
 
1216
                        string copyToOutputDirectory = buildItem.GetMetadata ("CopyToOutputDirectory");
 
1217
                        if (!string.IsNullOrEmpty (copyToOutputDirectory)) {
 
1218
                                switch (copyToOutputDirectory) {
 
1219
                                case "None": break;
 
1220
                                case "Always": file.CopyToOutputDirectory = FileCopyMode.Always; break;
 
1221
                                case "PreserveNewest": file.CopyToOutputDirectory = FileCopyMode.PreserveNewest; break;
 
1222
                                default:
 
1223
                                        MonoDevelop.Core.LoggingService.LogWarning (
 
1224
                                                "Unrecognised value {0} for CopyToOutputDirectory MSBuild property",
 
1225
                                                copyToOutputDirectory);
 
1226
                                        break;
 
1227
                                }
 
1228
                        }
 
1229
                        
 
1230
                        if (buildItem.GetMetadataIsFalse ("Visible"))
 
1231
                                file.Visible = false;
 
1232
                                
 
1233
                        
 
1234
                        string resourceId = buildItem.GetMetadata ("LogicalName");
 
1235
                        if (!string.IsNullOrEmpty (resourceId))
 
1236
                                file.ResourceId = resourceId;
 
1237
                        
 
1238
                        string contentType = buildItem.GetMetadata ("SubType");
 
1239
                        if (!string.IsNullOrEmpty (contentType))
 
1240
                                file.ContentType = contentType;
 
1241
                        
 
1242
                        string generator = buildItem.GetMetadata ("Generator");
 
1243
                        if (!string.IsNullOrEmpty (generator))
 
1244
                                file.Generator = generator;
 
1245
                        
 
1246
                        string customToolNamespace = buildItem.GetMetadata ("CustomToolNamespace");
 
1247
                        if (!string.IsNullOrEmpty (customToolNamespace))
 
1248
                                file.CustomToolNamespace = customToolNamespace;
 
1249
                        
 
1250
                        string lastGenOutput = buildItem.GetMetadata ("LastGenOutput");
 
1251
                        if (!string.IsNullOrEmpty (lastGenOutput))
 
1252
                                file.LastGenOutput = lastGenOutput;
 
1253
                        
 
1254
                        string link = buildItem.GetMetadata ("Link");
 
1255
                        if (!string.IsNullOrEmpty (link))
 
1256
                                file.Link = MSBuildProjectService.FromMSBuildPathRelative (project.ItemDirectory, link);
 
1257
                        
 
1258
                        file.Condition = buildItem.Condition;
 
1259
                        return file;
 
1260
                }
 
1261
 
 
1262
                bool ParseConfigCondition (string cond, out string config, out string platform)
 
1263
                {
 
1264
                        config = platform = null;
 
1265
                        int i = cond.IndexOf ("==");
 
1266
                        if (i == -1)
 
1267
                                return false;
 
1268
                        if (cond.Substring (0, i).Trim () == "'$(Configuration)|$(Platform)'") {
 
1269
                                cond = cond.Substring (i+2).Trim (' ','\'');
 
1270
                                i = cond.IndexOf ('|');
 
1271
                                if (i != -1) {
 
1272
                                        config = cond.Substring (0, i);
 
1273
                                        platform = cond.Substring (i+1);
 
1274
                                } else {
 
1275
                                        // Invalid configuration
 
1276
                                        return false;
 
1277
                                }
 
1278
                                if (platform == "AnyCPU")
 
1279
                                        platform = string.Empty;
 
1280
                                return true;
 
1281
                        }
 
1282
                        else if (cond.Substring (0, i).Trim () == "'$(Configuration)'") {
 
1283
                                config = cond.Substring (i+2).Trim (' ','\'');
 
1284
                                platform = Unspecified;
 
1285
                                return true;
 
1286
                        }
 
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;
 
1292
                                return true;
 
1293
                        }
 
1294
                        return false;
 
1295
                }
 
1296
                
 
1297
                string BuildConfigCondition (string config, string platform)
 
1298
                {
 
1299
                        if (platform.Length == 0)
 
1300
                                platform = "AnyCPU";
 
1301
                        return " '$(Configuration)|$(Platform)' == '" + config + "|" + platform + "' ";
 
1302
                }
 
1303
 
 
1304
                bool IsMergeToProjectProperty (ItemProperty prop)
 
1305
                {
 
1306
                        foreach (object at in prop.CustomAttributes) {
 
1307
                                if (at is MergeToProjectAttribute)
 
1308
                                        return true;
 
1309
                        }
 
1310
                        return false;
 
1311
                }
 
1312
 
 
1313
                string FindClosestSupportedVersion (string version)
 
1314
                {
 
1315
                        TargetFramework sfx = Runtime.SystemAssemblyService.GetTargetFramework (version);
 
1316
                        if (!string.IsNullOrEmpty (sfx.SubsetOfFramework) && ((IList)TargetFormat.FrameworkVersions).Contains (sfx.SubsetOfFramework))
 
1317
                                return sfx.SubsetOfFramework;
 
1318
                        
 
1319
                        foreach (string supv in TargetFormat.FrameworkVersions) {
 
1320
                                TargetFramework fx = Runtime.SystemAssemblyService.GetTargetFramework (supv);
 
1321
                                if (fx.IsCompatibleWithFramework (version))
 
1322
                                        return fx.Id;
 
1323
                        }
 
1324
                        return TargetFormat.FrameworkVersions [TargetFormat.FrameworkVersions.Length - 1];
 
1325
                }
 
1326
                
 
1327
                string GetXmlString (DataNode node)
 
1328
                {
 
1329
                        if (node is DataValue)
 
1330
                                return ((DataValue)node).Value;
 
1331
                        else {
 
1332
                                StringWriter sw = new StringWriter ();
 
1333
                                XmlTextWriter xw = new XmlTextWriter (sw);
 
1334
                                XmlConfigurationWriter.DefaultWriter.Write (xw, node);
 
1335
                                return sw.ToString ();
 
1336
                        }
 
1337
                }
 
1338
                
 
1339
                DataNode GetDataNode (ItemProperty prop, string xmlString)
 
1340
                {
 
1341
                        if (prop.DataType.IsSimpleType)
 
1342
                                return new DataValue (prop.Name, xmlString);
 
1343
                        else {
 
1344
                                StringReader sr = new StringReader (xmlString);
 
1345
                                return XmlConfigurationReader.DefaultReader.Read (new XmlTextReader (sr));
 
1346
                        }
 
1347
                }
 
1348
                
 
1349
                internal virtual MSBuildSerializer CreateSerializer ()
 
1350
                {
 
1351
                        return new MSBuildSerializer (EntityItem.FileName);
 
1352
                }
 
1353
                
 
1354
                static readonly MSBuildElementOrder globalConfigOrder = new MSBuildElementOrder (
 
1355
                        "Configuration","Platform","ProductVersion","SchemaVersion","ProjectGuid","ProjectTypeGuids", "OutputType",
 
1356
                    "AppDesignerFolder","RootNamespace","AssemblyName","StartupObject"
 
1357
                );
 
1358
                static readonly MSBuildElementOrder configOrder = new MSBuildElementOrder (
 
1359
                        "DebugSymbols","DebugType","Optimize","OutputPath","DefineConstants","ErrorReport","WarningLevel",
 
1360
                    "TreatWarningsAsErrors","DocumentationFile"
 
1361
                );
 
1362
 
 
1363
                // Those are properties which are dynamically set by this file format
 
1364
                
 
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),
 
1375
                };
 
1376
                
 
1377
                // Items generated by VS but which MD is not using and should be ignored
 
1378
                
 
1379
                internal static readonly IList<string> UnsupportedItems = new string[] {
 
1380
                        "BootstrapperFile", "AppDesigner", "WebReferences", "WebReferenceUrl", "Service"
 
1381
                };
 
1382
        }
 
1383
        
 
1384
        class MSBuildSerializer: DataSerializer
 
1385
        {
 
1386
                public DataItem InternalItemProperties = new DataItem ();
 
1387
                public DataItem ExternalItemProperties = new DataItem ();
 
1388
                
 
1389
                public MSBuildSerializer (string baseFile): base (MSBuildProjectService.DataContext)
 
1390
                {
 
1391
                        // Use windows separators
 
1392
                        SerializationContext.BaseFile = baseFile;
 
1393
                        SerializationContext.DirectorySeparatorChar = '\\';
 
1394
                }
 
1395
                
 
1396
                internal protected override bool CanHandleProperty (ItemProperty prop, SerializationContext serCtx, object instance)
 
1397
                {
 
1398
                        if (instance is Project) {
 
1399
                                if (prop.Name == "Contents")
 
1400
                                        return false;
 
1401
                        }
 
1402
                        if (instance is DotNetProject) {
 
1403
                                if (prop.Name == "References" || prop.Name == "LanguageParameters")
 
1404
                                        return false;
 
1405
                        }
 
1406
                        if (instance is SolutionEntityItem) {
 
1407
                                if (prop.IsExtendedProperty (typeof(SolutionEntityItem)))
 
1408
                                        return true;
 
1409
                                return prop.Name != "name" && prop.Name != "Configurations";
 
1410
                        }
 
1411
                        if (instance is SolutionFolder) {
 
1412
                                if (prop.Name == "Files")
 
1413
                                        return false;
 
1414
                        }
 
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")
 
1421
                                        return false;
 
1422
                        if (instance is ItemConfiguration)
 
1423
                                if (prop.Name == "name")
 
1424
                                        return false;
 
1425
                        return true;
 
1426
                }
 
1427
                
 
1428
                internal protected override DataNode OnSerializeProperty (ItemProperty prop, SerializationContext serCtx, object instance, object value)
 
1429
                {
 
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);
 
1434
                                else
 
1435
                                        InternalItemProperties.ItemData.Add (data);
 
1436
                        }
 
1437
                        return data;
 
1438
                }
 
1439
        }
 
1440
        
 
1441
        class MSBuildElementOrder: Dictionary<string, int>
 
1442
        {
 
1443
                public MSBuildElementOrder (params string[] elements)
 
1444
                {
 
1445
                        for (int n=0; n<elements.Length; n++)
 
1446
                                this [elements [n]] = n;
 
1447
                }
 
1448
        }
 
1449
}