4
// Lluis Sanchez Gual <lluis@novell.com>
6
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
8
// Permission is hereby granted, free of charge, to any person obtaining a copy
9
// of this software and associated documentation files (the "Software"), to deal
10
// in the Software without restriction, including without limitation the rights
11
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
// copies of the Software, and to permit persons to whom the Software is
13
// furnished to do so, subject to the following conditions:
15
// The above copyright notice and this permission notice shall be included in
16
// all copies or substantial portions of the Software.
18
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29
using System.Collections;
30
using System.Collections.Generic;
31
using System.Collections.ObjectModel;
33
using System.CodeDom.Compiler;
34
using MonoDevelop.Core;
35
using MonoDevelop.Core.Serialization;
36
using MonoDevelop.Projects.Extensions;
38
namespace MonoDevelop.Projects
40
public abstract class SolutionItem: IExtendedDataItem, IBuildTarget, ILoadController
42
SolutionFolder parentFolder;
43
Solution parentSolution;
44
ISolutionItemHandler handler;
47
[ProjectPathItemProperty ("BaseDirectory", DefaultValue=null)]
50
Hashtable extendedProperties;
52
[ItemProperty ("Policies", IsExternal = true, SkipEmpty = true)]
53
MonoDevelop.Projects.Policies.PolicyBag policies;
57
ProjectExtensionUtil.LoadControl (this);
60
public virtual void InitializeFromTemplate (XmlElement template)
64
protected internal ISolutionItemHandler ItemHandler {
66
if (handler == null) {
67
InitializeItemHandler ();
69
throw new InvalidOperationException ("No handler found for solution item of type: " + GetType ());
75
internal virtual void SetItemHandler (ISolutionItemHandler handler)
77
if (this.handler != null)
78
this.handler.Dispose ();
79
this.handler = handler;
82
internal ISolutionItemHandler GetItemHandler ()
84
// Used to get the handler without lazy loading it
88
public Solution ParentSolution {
90
if (parentFolder != null)
91
return parentFolder.ParentSolution;
92
return parentSolution;
95
parentSolution = value;
99
protected bool Loading {
100
get { return loading > 0; }
103
public abstract void Save (IProgressMonitor monitor);
105
public abstract string Name { get; set; }
107
public string BaseDirectory {
109
if (baseDirectory == null)
110
return System.IO.Path.GetFullPath (GetDefaultBaseDirectory ());
112
return baseDirectory;
115
string def = GetDefaultBaseDirectory ();
116
if (value != null && def != null && System.IO.Path.GetFullPath (value) == System.IO.Path.GetFullPath (def))
117
baseDirectory = null;
118
else if (string.IsNullOrEmpty (value))
119
baseDirectory = null;
121
baseDirectory = System.IO.Path.GetFullPath (value);
122
NotifyModified ("BaseDirectory");
126
internal bool HasCustomBaseDirectory {
127
get { return baseDirectory != null; }
130
protected virtual string GetDefaultBaseDirectory ()
132
return ParentSolution.BaseDirectory;
135
public string ItemId {
136
get { return ItemHandler.ItemId; }
139
public IDictionary ExtendedProperties {
140
get { return InternalGetExtendedProperties; }
143
public MonoDevelop.Projects.Policies.PolicyBag Policies {
145
//newly created (i.e. not deserialised) SolutionItems may have a null PolicyBag
146
if (policies == null)
147
policies = new MonoDevelop.Projects.Policies.PolicyBag ();
148
//this is the easiest reliable place to associate a deserialised Policybag with its owner
149
policies.Owner = this;
152
//setter so that a solution can deserialise the PropertyBag on its RootFolder
158
public SolutionFolder ParentFolder {
163
parentFolder = value;
167
public virtual void Dispose ()
169
if (extendedProperties != null) {
170
foreach (object ob in extendedProperties.Values) {
171
IDisposable disp = ob as IDisposable;
180
public virtual IEnumerable<SolutionItem> GetReferencedItems (string solutionConfiguration)
182
return new SolutionItem [0];
185
public BuildResult RunTarget (IProgressMonitor monitor, string target, string solutionConfiguration)
187
return Services.ProjectService.ExtensionChain.RunTarget (monitor, this, target, solutionConfiguration);
190
public void Clean (IProgressMonitor monitor, string solutionConfiguration)
192
Services.ProjectService.ExtensionChain.RunTarget (monitor, this, ProjectService.CleanTarget, solutionConfiguration);
195
public BuildResult Build (IProgressMonitor monitor, string solutionConfiguration)
197
return Build (monitor, solutionConfiguration, false);
200
public BuildResult Build (IProgressMonitor monitor, string solutionConfiguration, bool buildReferences)
202
if (!buildReferences) {
203
if (!NeedsBuilding (solutionConfiguration))
204
return new BuildResult (new CompilerResults (null), "");
207
SolutionEntityItem it = this as SolutionEntityItem;
208
string confName = it != null ? it.GetActiveConfigurationId (solutionConfiguration) : solutionConfiguration;
209
monitor.BeginTask (GettextCatalog.GetString ("Building: {0} ({1})", Name, confName), 1);
211
// This will end calling OnBuild ()
212
return Services.ProjectService.ExtensionChain.RunTarget (monitor, this, ProjectService.BuildTarget, solutionConfiguration);
219
// Get a list of all items that need to be built (including this),
220
// and build them in the correct order
222
List<SolutionItem> referenced = new List<SolutionItem> ();
223
GetBuildableReferencedItems (referenced, this, solutionConfiguration);
225
ReadOnlyCollection<SolutionItem> sortedReferenced = SolutionFolder.TopologicalSort (referenced, solutionConfiguration);
227
BuildResult cres = new BuildResult ();
230
monitor.BeginTask (null, sortedReferenced.Count);
231
foreach (SolutionItem p in sortedReferenced) {
232
if (p.NeedsBuilding (solutionConfiguration)) {
233
BuildResult res = p.Build (monitor, solutionConfiguration, false);
235
if (res.ErrorCount > 0)
239
if (monitor.IsCancelRequested)
246
public DateTime GetLastBuildTime (string itemConfiguration)
248
return OnGetLastBuildTime (itemConfiguration);
251
void GetBuildableReferencedItems (List<SolutionItem> referenced, SolutionItem item, string solutionConfiguration)
253
if (referenced.Contains (item)) return;
255
if (item.NeedsBuilding (solutionConfiguration))
256
referenced.Add (item);
258
foreach (SolutionItem ritem in item.GetReferencedItems (solutionConfiguration))
259
GetBuildableReferencedItems (referenced, ritem, solutionConfiguration);
262
public void Execute (IProgressMonitor monitor, ExecutionContext context, string solutionConfiguration)
264
Services.ProjectService.ExtensionChain.Execute (monitor, this, context, solutionConfiguration);
267
public bool CanExecute (ExecutionContext context, string solutionConfiguration)
269
return Services.ProjectService.ExtensionChain.CanExecute (this, context, solutionConfiguration);
272
public bool NeedsBuilding (string solutionConfiguration)
274
return Services.ProjectService.ExtensionChain.GetNeedsBuilding (this, solutionConfiguration);
277
public void SetNeedsBuilding (bool value, string solutionConfiguration)
279
Services.ProjectService.ExtensionChain.SetNeedsBuilding (this, value, solutionConfiguration);
282
public virtual bool NeedsReload {
284
if (ParentSolution != null)
285
return ParentSolution.NeedsReload;
293
public static ReadOnlyCollection<T> TopologicalSort<T> (IEnumerable<T> items, string solutionConfiguration) where T: SolutionItem
296
allItems = items as IList<T>;
297
if (allItems == null)
298
allItems = new List<T> (items);
300
List<T> sortedEntries = new List<T> ();
301
bool[] inserted = new bool[allItems.Count];
302
bool[] triedToInsert = new bool[allItems.Count];
303
for (int i = 0; i < allItems.Count; ++i) {
305
Insert<T> (i, allItems, sortedEntries, inserted, triedToInsert, solutionConfiguration);
307
return sortedEntries.AsReadOnly ();
310
static void Insert<T> (int index, IList<T> allItems, List<T> sortedItems, bool[] inserted, bool[] triedToInsert, string solutionConfiguration) where T: SolutionItem
312
if (triedToInsert[index]) {
313
throw new CyclicBuildOrderException();
315
triedToInsert[index] = true;
316
SolutionItem insertItem = allItems[index];
318
foreach (SolutionItem reference in insertItem.GetReferencedItems (solutionConfiguration)) {
319
for (int j=0; j < allItems.Count; ++j) {
320
SolutionItem checkItem = allItems[j];
321
if (reference == checkItem) {
323
Insert (j, allItems, sortedItems, inserted, triedToInsert, solutionConfiguration);
328
sortedItems.Add ((T)insertItem);
329
inserted[index] = true;
332
internal virtual IDictionary InternalGetExtendedProperties {
334
if (extendedProperties == null)
335
extendedProperties = new Hashtable ();
336
return extendedProperties;
340
void ILoadController.BeginLoad ()
346
void ILoadController.EndLoad ()
352
protected virtual void OnBeginLoad ()
356
protected virtual void OnEndLoad ()
360
protected void NotifyModified (string hint)
362
OnModified (new SolutionItemModifiedEventArgs (this, hint));
365
protected virtual void OnModified (SolutionItemModifiedEventArgs args)
367
if (Modified != null)
368
Modified (this, args);
371
protected virtual void OnNameChanged (SolutionItemRenamedEventArgs e)
373
NotifyModified ("Name");
374
if (NameChanged != null)
375
NameChanged (this, e);
378
protected virtual void InitializeItemHandler ()
383
internal protected abstract void OnClean (IProgressMonitor monitor, string solutionConfiguration);
384
internal protected abstract BuildResult OnBuild (IProgressMonitor monitor, string solutionConfiguration);
385
internal protected abstract void OnExecute (IProgressMonitor monitor, ExecutionContext context, string solutionConfiguration);
386
internal protected abstract bool OnGetNeedsBuilding (string solutionConfiguration);
387
internal protected abstract void OnSetNeedsBuilding (bool val, string solutionConfiguration);
389
internal protected virtual DateTime OnGetLastBuildTime (string solutionConfiguration)
391
return DateTime.MinValue;
394
internal protected virtual bool OnGetCanExecute (ExecutionContext context, string solutionConfiguration)
399
public event SolutionItemRenamedEventHandler NameChanged;
400
public event SolutionItemModifiedEventHandler Modified;