~ubuntu-branches/ubuntu/maverick/monodevelop/maverick

« back to all changes in this revision

Viewing changes to src/core/MonoDevelop.Projects/MonoDevelop.Projects/Project.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2010-07-05 13:00:05 UTC
  • mfrom: (1.2.8 upstream) (1.3.9 experimental)
  • Revision ID: james.westby@ubuntu.com-20100705130005-d6hp4k5gcn1xkj8c
Tags: 2.4+dfsg-1ubuntu1
* debian/patches/remove_support_for_moonlight.patch,
  debian/patches/dont_add_moonlight_to_core_addins.patch,
  debian/control:
  + Enable support for Moonlight
* debian/rules:
  + Ensure Moonlight addin isn't shipped in main MonoDevelop package by
    mistake

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//  Project.cs
2
 
//
3
 
// Author:
4
 
//   Lluis Sanchez Gual <lluis@novell.com>
5
 
//   Viktoria Dudka  <viktoriad@remobjects.com>
6
 
// 
7
 
// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
8
 
// Copyright (c) 2009 RemObjects Software
9
 
//
10
 
// Permission is hereby granted, free of charge, to any person obtaining a copy
11
 
// of this software and associated documentation files (the "Software"), to deal
12
 
// in the Software without restriction, including without limitation the rights
13
 
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
 
// copies of the Software, and to permit persons to whom the Software is
15
 
// furnished to do so, subject to the following conditions:
16
 
//
17
 
// The above copyright notice and this permission notice shall be included in
18
 
// all copies or substantial portions of the Software.
19
 
//
20
 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
 
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
 
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
 
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
 
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
 
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26
 
// THE SOFTWARE.
27
 
//
28
 
//
29
 
 
30
 
 
31
 
using System;
32
 
using System.Collections;
33
 
using System.Collections.Generic;
34
 
using System.IO;
35
 
using MonoDevelop;
36
 
using MonoDevelop.Core;
37
 
using MonoDevelop.Core.Serialization;
38
 
using MonoDevelop.Projects;
39
 
using MonoDevelop.Projects.Dom.Output;
40
 
 
41
 
 
42
 
namespace MonoDevelop.Projects
43
 
{
44
 
        public enum NewFileSearch
45
 
        {
46
 
                None,
47
 
                OnLoad,
48
 
                OnLoadAutoInsert
49
 
        }
50
 
 
51
 
        [DataInclude(typeof(ProjectFile))]
52
 
        [DataItem(FallbackType = typeof(UnknownProject))]
53
 
        public abstract class Project : SolutionEntityItem
54
 
        {
55
 
                string[] buildActions;
56
 
                bool isDirty;
57
 
 
58
 
                public Project ()
59
 
                {
60
 
                        FileService.FileChanged += OnFileChanged;
61
 
                        files = new ProjectFileCollection ();
62
 
                        Items.Bind (files);
63
 
                        DependencyResolutionEnabled = true;
64
 
                }
65
 
 
66
 
                [ItemProperty("Description", DefaultValue = "")]
67
 
                private string description = "";
68
 
                public string Description {
69
 
                        get { return description; }
70
 
                        set {
71
 
                                description = value;
72
 
                                NotifyModified ("Description");
73
 
                        }
74
 
                }
75
 
 
76
 
                public virtual bool IsCompileable (string fileName)
77
 
                {
78
 
                        return false;
79
 
                }
80
 
 
81
 
                private ProjectFileCollection files;
82
 
                public ProjectFileCollection Files {
83
 
                        get { return files; }
84
 
                }
85
 
 
86
 
                [ItemProperty("newfilesearch", DefaultValue = NewFileSearch.None)]
87
 
                protected NewFileSearch newFileSearch = NewFileSearch.None;
88
 
                public NewFileSearch NewFileSearch {
89
 
                        get { return newFileSearch; }
90
 
 
91
 
                        set {
92
 
                                newFileSearch = value;
93
 
                                NotifyModified ("NewFileSearch");
94
 
                        }
95
 
                }
96
 
 
97
 
                public abstract string ProjectType {
98
 
                        get;
99
 
                }
100
 
 
101
 
                string stockIcon = "md-project";
102
 
                public virtual string StockIcon {
103
 
                        get { return stockIcon; }
104
 
                        set { this.stockIcon = value; }
105
 
                }
106
 
 
107
 
                public virtual Ambience Ambience {
108
 
                        get { return new NetAmbience (); }
109
 
                }
110
 
 
111
 
                public virtual string[] SupportedLanguages {
112
 
                        get { return new String[] { "" }; }
113
 
                }
114
 
 
115
 
                public virtual string GetDefaultBuildAction (string fileName)
116
 
                {
117
 
                        return IsCompileable (fileName) ? BuildAction.Compile : BuildAction.None;
118
 
                }
119
 
 
120
 
                public ProjectFile GetProjectFile (string fileName)
121
 
                {
122
 
                        return files.GetFile (fileName);
123
 
                }
124
 
 
125
 
                public bool IsFileInProject (string fileName)
126
 
                {
127
 
                        return files.GetFile (fileName) != null;
128
 
                }
129
 
 
130
 
                //NOTE: groups the common actions at the top, separated by a "--" entry *IF* there are 
131
 
                // more "uncommon" actions than "common" actions
132
 
                public string[] GetBuildActions ()
133
 
                {
134
 
                        if (buildActions != null)
135
 
                                return buildActions;
136
 
 
137
 
                        // find all the actions in use and add them to the list of standard actions
138
 
                        Hashtable actions = new Hashtable ();
139
 
                        object marker = new object (); //avoid using bools as they need to be boxed. re-use single object instead
140
 
                        //ad the standard actions
141
 
                        foreach (string action in GetStandardBuildActions ())
142
 
                                actions[action] = marker;
143
 
 
144
 
                        //add any more actions that are in the project file
145
 
                        foreach (ProjectFile pf in files)
146
 
                                if (!actions.ContainsKey (pf.BuildAction))
147
 
                                        actions[pf.BuildAction] = marker;
148
 
 
149
 
                        //remove the "common" actions, since they're handled separately
150
 
                        IList<string> commonActions = GetCommonBuildActions ();
151
 
                        foreach (string action in commonActions)
152
 
                                if (actions.Contains (action))
153
 
                                        actions.Remove (action);
154
 
 
155
 
                        //calculate dimensions for our new array and create it
156
 
                        int dashPos = commonActions.Count;
157
 
                        bool hasDash = commonActions.Count > 0 && actions.Count > 0;
158
 
                        int arrayLen = commonActions.Count + actions.Count;
159
 
                        int uncommonStart = hasDash ? dashPos + 1 : dashPos;
160
 
                        if (hasDash)
161
 
                                arrayLen++;
162
 
                        buildActions = new string[arrayLen];
163
 
 
164
 
                        //populate it
165
 
                        if (commonActions.Count > 0)
166
 
                                commonActions.CopyTo (buildActions, 0);
167
 
                        if (hasDash)
168
 
                                buildActions[dashPos] = "--";
169
 
                        if (actions.Count > 0)
170
 
                                actions.Keys.CopyTo (buildActions, uncommonStart);
171
 
 
172
 
                        //sort the actions
173
 
                        if (hasDash) {
174
 
                                //it may be better to leave common actions in the order that the project specified
175
 
                                //Array.Sort (buildActions, 0, commonActions.Count, StringComparer.Ordinal);
176
 
                                Array.Sort (buildActions, uncommonStart, arrayLen - uncommonStart, StringComparer.Ordinal);
177
 
                        } else {
178
 
                                Array.Sort (buildActions, StringComparer.Ordinal);
179
 
                        }
180
 
                        return buildActions;
181
 
                }
182
 
 
183
 
                protected virtual IEnumerable<string> GetStandardBuildActions ()
184
 
                {
185
 
                        return BuildAction.StandardActions;
186
 
                }
187
 
 
188
 
                protected virtual IList<string> GetCommonBuildActions ()
189
 
                {
190
 
                        return BuildAction.StandardActions;
191
 
                }
192
 
 
193
 
                public static Project LoadProject (string filename, IProgressMonitor monitor)
194
 
                {
195
 
                        Project prj = Services.ProjectService.ReadSolutionItem (monitor, filename) as Project;
196
 
                        if (prj == null)
197
 
                                throw new InvalidOperationException ("Invalid project file: " + filename);
198
 
 
199
 
                        return prj;
200
 
                }
201
 
 
202
 
 
203
 
                public override void Dispose ()
204
 
                {
205
 
                        FileService.FileChanged -= OnFileChanged;
206
 
                        foreach (ProjectFile file in Files) {
207
 
                                file.Dispose ();
208
 
                        }
209
 
                        base.Dispose ();
210
 
                }
211
 
 
212
 
                public ProjectFile AddFile (string filename)
213
 
                {
214
 
                        return AddFile (filename, null);
215
 
                }
216
 
 
217
 
                public ProjectFile AddFile (string filename, string buildAction)
218
 
                {
219
 
                        foreach (ProjectFile fInfo in Files) {
220
 
                                if (fInfo.Name == filename) {
221
 
                                        return fInfo;
222
 
                                }
223
 
                        }
224
 
 
225
 
                        if (String.IsNullOrEmpty (buildAction)) {
226
 
                                buildAction = GetDefaultBuildAction (filename);
227
 
                        }
228
 
 
229
 
                        ProjectFile newFileInformation = new ProjectFile (filename, buildAction);
230
 
                        Files.Add (newFileInformation);
231
 
                        return newFileInformation;
232
 
                }
233
 
 
234
 
                public void AddFile (ProjectFile projectFile)
235
 
                {
236
 
                        Files.Add (projectFile);
237
 
                }
238
 
 
239
 
                public ProjectFile AddDirectory (string relativePath)
240
 
                {
241
 
                        string newPath = Path.Combine (BaseDirectory, relativePath);
242
 
 
243
 
                        foreach (ProjectFile fInfo in Files)
244
 
                                if (fInfo.Name == newPath && fInfo.Subtype == Subtype.Directory)
245
 
                                        return fInfo;
246
 
 
247
 
                        if (!Directory.Exists (newPath)) {
248
 
                                if (File.Exists (newPath)) {
249
 
                                        string message = GettextCatalog.GetString ("Cannot create directory {0}, as a file with that name exists.", newPath);
250
 
                                        throw new InvalidOperationException (message);
251
 
                                }
252
 
                                FileService.CreateDirectory (newPath);
253
 
                        }
254
 
 
255
 
                        ProjectFile newDir = new ProjectFile (newPath);
256
 
                        newDir.Subtype = Subtype.Directory;
257
 
                        AddFile (newDir);
258
 
                        return newDir;
259
 
                }
260
 
 
261
 
                protected internal override BuildResult OnBuild (IProgressMonitor monitor, ConfigurationSelector configuration)
262
 
                {
263
 
                        // create output directory, if not exists
264
 
                        ProjectConfiguration conf = GetConfiguration (configuration) as ProjectConfiguration;
265
 
                        if (conf == null) {
266
 
                                BuildResult cres = new BuildResult ();
267
 
                                cres.AddError (GettextCatalog.GetString ("Configuration '{0}' not found in project '{1}'", configuration.ToString (), Name));
268
 
                                return cres;
269
 
                        }
270
 
                        string outputDir = conf.OutputDirectory;
271
 
                        try {
272
 
                                DirectoryInfo directoryInfo = new DirectoryInfo (outputDir);
273
 
                                if (!directoryInfo.Exists) {
274
 
                                        directoryInfo.Create ();
275
 
                                }
276
 
                        } catch (Exception e) {
277
 
                                throw new ApplicationException ("Can't create project output directory " + outputDir + " original exception:\n" + e.ToString ());
278
 
                        }
279
 
 
280
 
                        //copy references and files marked to "CopyToOutputDirectory"
281
 
                        CopySupportFiles (monitor, configuration);
282
 
 
283
 
                        StringParserService.Properties["Project"] = Name;
284
 
 
285
 
                        monitor.Log.WriteLine (GettextCatalog.GetString ("Performing main compilation..."));
286
 
                        BuildResult res = DoBuild (monitor, configuration);
287
 
 
288
 
                        isDirty = false;
289
 
 
290
 
                        if (res != null) {
291
 
                                string errorString = GettextCatalog.GetPluralString ("{0} error", "{0} errors", res.ErrorCount, res.ErrorCount);
292
 
                                string warningString = GettextCatalog.GetPluralString ("{0} warning", "{0} warnings", res.WarningCount, res.WarningCount);
293
 
 
294
 
                                monitor.Log.WriteLine (GettextCatalog.GetString ("Build complete -- ") + errorString + ", " + warningString);
295
 
                        }
296
 
 
297
 
                        return res;
298
 
                }
299
 
 
300
 
                public void CopySupportFiles (IProgressMonitor monitor, ConfigurationSelector configuration)
301
 
                {
302
 
                        ProjectConfiguration config = (ProjectConfiguration) GetConfiguration (configuration);
303
 
 
304
 
                        foreach (FileCopySet.Item item in GetSupportFileList (configuration)) {
305
 
                                string dest = Path.GetFullPath (Path.Combine (config.OutputDirectory, item.Target));
306
 
                                string src = Path.GetFullPath (item.Src);
307
 
 
308
 
                                try {
309
 
                                        if (dest == src)
310
 
                                                continue;
311
 
 
312
 
                                        if (item.CopyOnlyIfNewer && File.Exists (dest) && (File.GetLastWriteTimeUtc (dest) >= File.GetLastWriteTimeUtc (src)))
313
 
                                                continue;
314
 
 
315
 
                                        if (!Directory.Exists (Path.GetDirectoryName (dest)))
316
 
                                                FileService.CreateDirectory (Path.GetDirectoryName (dest));
317
 
 
318
 
                                        if (File.Exists (src))
319
 
                                                FileService.CopyFile (src, dest);
320
 
                                        else
321
 
                                                monitor.ReportError (GettextCatalog.GetString ("Could not find support file '{0}'.", src), null);
322
 
 
323
 
                                } catch (IOException ex) {
324
 
                                        monitor.ReportError (GettextCatalog.GetString ("Error copying support file '{0}'.", dest), ex);
325
 
                                }
326
 
                        }
327
 
                }
328
 
 
329
 
                public void DeleteSupportFiles (IProgressMonitor monitor, ConfigurationSelector configuration)
330
 
                {
331
 
                        ProjectConfiguration config = (ProjectConfiguration) GetConfiguration (configuration);
332
 
 
333
 
                        foreach (FileCopySet.Item item in GetSupportFileList (configuration)) {
334
 
                                string dest = Path.Combine (config.OutputDirectory, item.Target);
335
 
 
336
 
                                // Ignore files which were not copied
337
 
                                if (Path.GetFullPath (dest) == Path.GetFullPath (item.Src))
338
 
                                        continue;
339
 
 
340
 
                                try {
341
 
                                        if (File.Exists (dest)) {
342
 
                                                FileService.DeleteFile (dest);
343
 
                                        }
344
 
                                } catch (IOException ex) {
345
 
                                        monitor.ReportError (GettextCatalog.GetString ("Error deleting support file '{0}'.", dest), ex);
346
 
                                }
347
 
                        }
348
 
                }
349
 
 
350
 
                public FileCopySet GetSupportFileList (ConfigurationSelector configuration)
351
 
                {
352
 
                        FileCopySet list = new FileCopySet ();
353
 
                        PopulateSupportFileList (list, configuration);
354
 
                        return list;
355
 
                }
356
 
 
357
 
                protected virtual void PopulateSupportFileList (FileCopySet list, ConfigurationSelector configuration)
358
 
                {
359
 
                        foreach (ProjectFile pf in Files) {
360
 
                                if (pf.CopyToOutputDirectory == FileCopyMode.None)
361
 
                                        continue;
362
 
                                FilePath outpath = pf.IsExternalToProject ? (FilePath)pf.FilePath.FileName : pf.RelativePath;
363
 
                                list.Add (pf.FilePath, pf.CopyToOutputDirectory == FileCopyMode.PreserveNewest, outpath);
364
 
                        }
365
 
                }
366
 
 
367
 
                protected virtual BuildResult DoBuild (IProgressMonitor monitor, ConfigurationSelector configuration)
368
 
                {
369
 
                        BuildResult res = ItemHandler.RunTarget (monitor, "Build", configuration);
370
 
                        return res ?? new BuildResult ();
371
 
                }
372
 
 
373
 
                protected internal override void OnClean (IProgressMonitor monitor, ConfigurationSelector configuration)
374
 
                {
375
 
                        SetDirty ();
376
 
                        ProjectConfiguration config = GetConfiguration (configuration) as ProjectConfiguration;
377
 
                        if (config == null) {
378
 
                                monitor.ReportError (GettextCatalog.GetString ("Configuration '{0}' not found in project '{1}'", config.Id, Name), null);
379
 
                                return;
380
 
                        }
381
 
 
382
 
                        // Delete the generated assembly
383
 
                        string file = GetOutputFileName (configuration);
384
 
                        if (file != null) {
385
 
                                if (File.Exists (file))
386
 
                                        FileService.DeleteFile (file);
387
 
                        }
388
 
 
389
 
                        DeleteSupportFiles (monitor, configuration);
390
 
 
391
 
                        DoClean (monitor, config.Selector);
392
 
                }
393
 
 
394
 
                protected virtual void DoClean (IProgressMonitor monitor, ConfigurationSelector configuration)
395
 
                {
396
 
                        ItemHandler.RunTarget (monitor, "Clean", configuration);
397
 
                }
398
 
 
399
 
                void GetBuildableReferencedItems (List<SolutionItem> referenced, SolutionItem item, ConfigurationSelector configuration)
400
 
                {
401
 
                        if (referenced.Contains (item))
402
 
                                return;
403
 
 
404
 
                        if (item.NeedsBuilding (configuration))
405
 
                                referenced.Add (item);
406
 
 
407
 
                        foreach (SolutionItem ritem in item.GetReferencedItems (configuration))
408
 
                                GetBuildableReferencedItems (referenced, ritem, configuration);
409
 
                }
410
 
 
411
 
                protected internal override void OnExecute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration)
412
 
                {
413
 
                        ProjectConfiguration config = GetConfiguration (configuration) as ProjectConfiguration;
414
 
                        if (config == null) {
415
 
                                monitor.ReportError (GettextCatalog.GetString ("Configuration '{0}' not found in project '{1}'", configuration, Name), null);
416
 
                                return;
417
 
                        }
418
 
                        DoExecute (monitor, context, configuration);
419
 
                }
420
 
 
421
 
                protected virtual void DoExecute (IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration)
422
 
                {
423
 
                }
424
 
 
425
 
                public virtual FilePath GetOutputFileName (ConfigurationSelector configuration)
426
 
                {
427
 
                        return FilePath.Null;
428
 
                }
429
 
 
430
 
                protected internal override bool OnGetNeedsBuilding (ConfigurationSelector configuration)
431
 
                {
432
 
                        if (!isDirty) {
433
 
                                if (CheckNeedsBuild (configuration))
434
 
                                        SetDirty ();
435
 
                        }
436
 
                        return isDirty;
437
 
                }
438
 
 
439
 
                protected internal override void OnSetNeedsBuilding (bool value, ConfigurationSelector configuration)
440
 
                {
441
 
                        isDirty = value;
442
 
                }
443
 
 
444
 
                void SetDirty ()
445
 
                {
446
 
                        if (!Loading)
447
 
                                isDirty = true;
448
 
                }
449
 
 
450
 
                protected virtual bool CheckNeedsBuild (ConfigurationSelector configuration)
451
 
                {
452
 
                        DateTime tim = GetLastBuildTime (configuration);
453
 
                        if (tim == DateTime.MinValue)
454
 
                                return true;
455
 
 
456
 
                        foreach (ProjectFile file in Files) {
457
 
                                if (file.BuildAction == BuildAction.Content || file.BuildAction == BuildAction.None)
458
 
                                        continue;
459
 
                                try {
460
 
                                        if (File.GetLastWriteTime (file.FilePath) > tim)
461
 
                                                return true;
462
 
                                } catch (IOException) {
463
 
                                        // Ignore.
464
 
                                }
465
 
                        }
466
 
 
467
 
                        foreach (SolutionItem pref in GetReferencedItems (configuration)) {
468
 
                                if (pref.GetLastBuildTime (configuration) > tim || pref.NeedsBuilding (configuration))
469
 
                                        return true;
470
 
                        }
471
 
 
472
 
                        try {
473
 
                                if (File.GetLastWriteTime (FileName) > tim)
474
 
                                        return true;
475
 
                        } catch {
476
 
                                // Ignore
477
 
                        }
478
 
 
479
 
                        return false;
480
 
                }
481
 
 
482
 
                protected internal override DateTime OnGetLastBuildTime (ConfigurationSelector configuration)
483
 
                {
484
 
                        string file = GetOutputFileName (configuration);
485
 
                        if (file == null)
486
 
                                return DateTime.MinValue;
487
 
 
488
 
                        FileInfo finfo = new FileInfo (file);
489
 
                        if (!finfo.Exists)
490
 
                                return DateTime.MinValue;
491
 
                        else
492
 
                                return finfo.LastWriteTime;
493
 
                }
494
 
 
495
 
                internal virtual void OnFileChanged (object source, FileEventArgs e)
496
 
                {
497
 
                        ProjectFile file = GetProjectFile (e.FileName);
498
 
                        if (file != null) {
499
 
                                SetDirty ();
500
 
                                try {
501
 
                                        NotifyFileChangedInProject (file);
502
 
                                } catch {
503
 
                                        // Workaround Mono bug. The watcher seems to
504
 
                                        // stop watching if an exception is thrown in
505
 
                                        // the event handler
506
 
                                }
507
 
                        }
508
 
 
509
 
                }
510
 
 
511
 
                protected internal override List<FilePath> OnGetItemFiles (bool includeReferencedFiles)
512
 
                {
513
 
                        List<FilePath> col = base.OnGetItemFiles (includeReferencedFiles);
514
 
                        if (includeReferencedFiles) {
515
 
                                foreach (ProjectFile pf in Files) {
516
 
                                        if (pf.Subtype != Subtype.Directory)
517
 
                                                col.Add (pf.FilePath);
518
 
                                }
519
 
                        }
520
 
                        return col;
521
 
                }
522
 
 
523
 
                protected internal override void OnItemAdded (object obj)
524
 
                {
525
 
                        base.OnItemAdded (obj);
526
 
                        if (obj is ProjectFile)
527
 
                                NotifyFileAddedToProject ((ProjectFile)obj);
528
 
                }
529
 
 
530
 
                protected internal override void OnItemRemoved (object obj)
531
 
                {
532
 
                        base.OnItemRemoved (obj);
533
 
                        if (obj is ProjectFile)
534
 
                                NotifyFileRemovedFromProject ((ProjectFile)obj);
535
 
                }
536
 
 
537
 
                internal void NotifyFileChangedInProject (ProjectFile file)
538
 
                {
539
 
                        OnFileChangedInProject (new ProjectFileEventArgs (this, file));
540
 
                }
541
 
 
542
 
                internal void NotifyFilePropertyChangedInProject (ProjectFile file)
543
 
                {
544
 
                        NotifyModified ("Files");
545
 
                        OnFilePropertyChangedInProject (new ProjectFileEventArgs (this, file));
546
 
                }
547
 
 
548
 
                List<ProjectFile> unresolvedDeps;
549
 
 
550
 
                void NotifyFileRemovedFromProject (ProjectFile file)
551
 
                {
552
 
                        file.SetProject (null);
553
 
 
554
 
                        if (DependencyResolutionEnabled) {
555
 
                                if (unresolvedDeps.Contains (file))
556
 
                                        unresolvedDeps.Remove (file);
557
 
                                foreach (ProjectFile f in file.DependentChildren) {
558
 
                                        f.DependsOnFile = null;
559
 
                                        if (!string.IsNullOrEmpty (f.DependsOn))
560
 
                                                unresolvedDeps.Add (f);
561
 
                                }
562
 
                                file.DependsOnFile = null;
563
 
                        }
564
 
 
565
 
                        SetDirty ();
566
 
                        NotifyModified ("Files");
567
 
                        OnFileRemovedFromProject (new ProjectFileEventArgs (this, file));
568
 
                }
569
 
 
570
 
                void NotifyFileAddedToProject (ProjectFile file)
571
 
                {
572
 
                        if (file.Project != null)
573
 
                                throw new InvalidOperationException ("ProjectFile already belongs to a project");
574
 
                        file.SetProject (this);
575
 
 
576
 
                        ResolveDependencies (file);
577
 
 
578
 
                        SetDirty ();
579
 
                        NotifyModified ("Files");
580
 
                        OnFileAddedToProject (new ProjectFileEventArgs (this, file));
581
 
                }
582
 
 
583
 
                internal void ResolveDependencies (ProjectFile file)
584
 
                {
585
 
                        if (!DependencyResolutionEnabled)
586
 
                                return;
587
 
 
588
 
                        if (!file.ResolveParent ())
589
 
                                unresolvedDeps.Add (file);
590
 
 
591
 
                        List<ProjectFile> resolved = null;
592
 
                        foreach (ProjectFile unres in unresolvedDeps) {
593
 
                                if (string.IsNullOrEmpty (unres.DependsOn)) {
594
 
                                        resolved.Add (unres);
595
 
                                }
596
 
                                if (unres.ResolveParent ()) {
597
 
                                        if (resolved == null)
598
 
                                                resolved = new List<ProjectFile> ();
599
 
                                        resolved.Add (unres);
600
 
                                }
601
 
                        }
602
 
                        if (resolved != null)
603
 
                                foreach (ProjectFile pf in resolved)
604
 
                                        unresolvedDeps.Remove (pf);
605
 
                }
606
 
 
607
 
                bool DependencyResolutionEnabled {
608
 
 
609
 
                        get { return unresolvedDeps != null; }
610
 
                        set {
611
 
                                if (value) {
612
 
                                        if (unresolvedDeps != null)
613
 
                                                return;
614
 
                                        unresolvedDeps = new List<ProjectFile> ();
615
 
                                        foreach (ProjectFile file in files)
616
 
                                                ResolveDependencies (file);
617
 
                                } else {
618
 
                                        unresolvedDeps = null;
619
 
                                }
620
 
                        }
621
 
                }
622
 
 
623
 
                internal void NotifyFileRenamedInProject (ProjectFileRenamedEventArgs args)
624
 
                {
625
 
                        SetDirty ();
626
 
                        NotifyModified ("Files");
627
 
                        OnFileRenamedInProject (args);
628
 
                }
629
 
 
630
 
                protected virtual void OnFileRemovedFromProject (ProjectFileEventArgs e)
631
 
                {
632
 
                        buildActions = null;
633
 
                        if (FileRemovedFromProject != null) {
634
 
                                FileRemovedFromProject (this, e);
635
 
                        }
636
 
                }
637
 
 
638
 
                protected virtual void OnFileAddedToProject (ProjectFileEventArgs e)
639
 
                {
640
 
                        buildActions = null;
641
 
                        if (FileAddedToProject != null) {
642
 
                                FileAddedToProject (this, e);
643
 
                        }
644
 
                }
645
 
 
646
 
                protected virtual void OnFileChangedInProject (ProjectFileEventArgs e)
647
 
                {
648
 
                        if (FileChangedInProject != null) {
649
 
                                FileChangedInProject (this, e);
650
 
                        }
651
 
                }
652
 
 
653
 
                protected virtual void OnFilePropertyChangedInProject (ProjectFileEventArgs e)
654
 
                {
655
 
                        buildActions = null;
656
 
                        if (FilePropertyChangedInProject != null) {
657
 
                                FilePropertyChangedInProject (this, e);
658
 
                        }
659
 
                }
660
 
 
661
 
                protected virtual void OnFileRenamedInProject (ProjectFileRenamedEventArgs e)
662
 
                {
663
 
                        if (FileRenamedInProject != null) {
664
 
                                FileRenamedInProject (this, e);
665
 
                        }
666
 
                }
667
 
 
668
 
                public event ProjectFileEventHandler FileRemovedFromProject;
669
 
                public event ProjectFileEventHandler FileAddedToProject;
670
 
                public event ProjectFileEventHandler FileChangedInProject;
671
 
                public event ProjectFileEventHandler FilePropertyChangedInProject;
672
 
                public event ProjectFileRenamedEventHandler FileRenamedInProject;
673
 
 
674
 
 
675
 
        }
676
 
 
677
 
        public class UnknownProject : Project
678
 
        {
679
 
                public override string ProjectType {
680
 
                        get { return ""; }
681
 
                }
682
 
 
683
 
                public override SolutionItemConfiguration CreateConfiguration (string name)
684
 
                {
685
 
                        return null;
686
 
                }
687
 
                
688
 
                internal protected override bool OnGetCanExecute (ExecutionContext context, ConfigurationSelector configuration)
689
 
                {
690
 
                        return false;
691
 
                }
692
 
                
693
 
                internal protected override BuildResult OnBuild (IProgressMonitor monitor, ConfigurationSelector configuration)
694
 
                {
695
 
                        BuildResult res = new BuildResult ();
696
 
                        res.AddError ("Unknown project type");
697
 
                        return res;
698
 
                }
699
 
        }
700
 
 
701
 
        public delegate void ProjectEventHandler (Object sender, ProjectEventArgs e);
702
 
        public class ProjectEventArgs : EventArgs
703
 
        {
704
 
                public ProjectEventArgs (Project project)
705
 
                {
706
 
                        this.project = project;
707
 
                }
708
 
 
709
 
                private Project project;
710
 
                public Project Project {
711
 
                        get { return project; }
712
 
                }
713
 
        }
714
 
}