2 // Project.cs: Project class
5 // Marek Sieradzki (marek.sieradzki@gmail.com)
7 // (C) 2005 Marek Sieradzki
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections;
32 using System.Collections.Generic;
33 using System.Collections.Specialized;
37 using System.Xml.Schema;
38 using Microsoft.Build.Framework;
39 using Mono.XBuild.Framework;
41 namespace Microsoft.Build.BuildEngine {
42 public class Project {
45 Dictionary <string, List <string>> conditionedProperties;
46 string[] defaultTargets;
48 BuildItemGroup evaluatedItems;
49 BuildItemGroup evaluatedItemsIgnoringCondition;
50 Dictionary <string, BuildItemGroup> evaluatedItemsByName;
51 Dictionary <string, BuildItemGroup> evaluatedItemsByNameIgnoringCondition;
52 BuildPropertyGroup evaluatedProperties;
53 string firstTargetName;
55 BuildPropertyGroup globalProperties;
56 GroupingCollection groupingCollection;
59 BuildItemGroupCollection itemGroups;
60 ImportCollection imports;
61 string[] initialTargets;
62 Dictionary <string, BuildItemGroup> last_item_group_containing;
63 bool needToReevaluate;
65 BuildPropertyGroupCollection propertyGroups;
67 TaskDatabase taskDatabase;
68 TargetCollection targets;
69 DateTime timeOfLastDirty;
70 UsingTaskCollection usingTasks;
71 XmlDocument xmlDocument;
73 bool initialTargetsBuilt;
75 static XmlNamespaceManager manager;
76 static string ns = "http://schemas.microsoft.com/developer/msbuild/2003";
79 : this (Engine.GlobalEngine)
83 public Project (Engine engine)
85 parentEngine = engine;
87 buildEnabled = ParentEngine.BuildEnabled;
88 xmlDocument = new XmlDocument ();
89 xmlDocument.PreserveWhitespace = false;
90 xmlDocument.AppendChild (xmlDocument.CreateElement ("Project", XmlNamespace));
91 xmlDocument.DocumentElement.SetAttribute ("xmlns", ns);
93 fullFileName = String.Empty;
95 globalProperties = new BuildPropertyGroup (null, this, null, false);
96 foreach (BuildProperty bp in parentEngine.GlobalProperties)
97 GlobalProperties.AddProperty (bp.Clone (true));
102 [MonoTODO ("Not tested")]
103 public void AddNewImport (string importLocation,
104 string importCondition)
106 if (importLocation == null)
107 throw new ArgumentNullException ("importLocation");
109 XmlElement importElement = xmlDocument.CreateElement ("Import", XmlNamespace);
110 xmlDocument.DocumentElement.AppendChild (importElement);
111 importElement.SetAttribute ("Project", importLocation);
112 if (!String.IsNullOrEmpty (importCondition))
113 importElement.SetAttribute ("Condition", importCondition);
115 Import import = new Import (importElement, this, null);
116 imports.Add (import);
117 MarkProjectAsDirty ();
121 public BuildItem AddNewItem (string itemName,
124 return AddNewItem (itemName, itemInclude, false);
127 [MonoTODO ("Adds item not in the same place as MS")]
128 public BuildItem AddNewItem (string itemName,
130 bool treatItemIncludeAsLiteral)
134 if (itemGroups.Count == 0)
135 big = AddNewItemGroup ();
137 if (last_item_group_containing.ContainsKey (itemName)) {
138 big = last_item_group_containing [itemName];
141 BuildItemGroup [] groups = new BuildItemGroup [itemGroups.Count];
142 itemGroups.CopyTo (groups, 0);
147 BuildItem item = big.AddNewItem (itemName, itemInclude, treatItemIncludeAsLiteral);
149 MarkProjectAsDirty ();
155 [MonoTODO ("Not tested")]
156 public BuildItemGroup AddNewItemGroup ()
158 XmlElement element = xmlDocument.CreateElement ("ItemGroup", XmlNamespace);
159 xmlDocument.DocumentElement.AppendChild (element);
161 BuildItemGroup big = new BuildItemGroup (element, this, null, false);
162 itemGroups.Add (big);
163 MarkProjectAsDirty ();
169 [MonoTODO ("Ignores insertAtEndOfProject")]
170 public BuildPropertyGroup AddNewPropertyGroup (bool insertAtEndOfProject)
172 XmlElement element = xmlDocument.CreateElement ("PropertyGroup", XmlNamespace);
173 xmlDocument.DocumentElement.AppendChild (element);
175 BuildPropertyGroup bpg = new BuildPropertyGroup (element, this, null, false);
176 propertyGroups.Add (bpg);
177 MarkProjectAsDirty ();
183 [MonoTODO ("Not tested, isn't added to TaskDatabase (no reevaluation)")]
184 public void AddNewUsingTaskFromAssemblyFile (string taskName,
187 if (taskName == null)
188 throw new ArgumentNullException ("taskName");
189 if (assemblyFile == null)
190 throw new ArgumentNullException ("assemblyFile");
192 XmlElement element = xmlDocument.CreateElement ("UsingTask", XmlNamespace);
193 xmlDocument.DocumentElement.AppendChild (element);
194 element.SetAttribute ("TaskName", taskName);
195 element.SetAttribute ("AssemblyFile", assemblyFile);
197 UsingTask ut = new UsingTask (element, this, null);
199 MarkProjectAsDirty ();
202 [MonoTODO ("Not tested, isn't added to TaskDatabase (no reevaluation)")]
203 public void AddNewUsingTaskFromAssemblyName (string taskName,
206 if (taskName == null)
207 throw new ArgumentNullException ("taskName");
208 if (assemblyName == null)
209 throw new ArgumentNullException ("assemblyName");
211 XmlElement element = xmlDocument.CreateElement ("UsingTask", XmlNamespace);
212 xmlDocument.DocumentElement.AppendChild (element);
213 element.SetAttribute ("TaskName", taskName);
214 element.SetAttribute ("AssemblyName", assemblyName);
216 UsingTask ut = new UsingTask (element, this, null);
218 MarkProjectAsDirty ();
221 [MonoTODO ("Not tested")]
224 return Build (new string [0]);
227 [MonoTODO ("Not tested")]
228 public bool Build (string targetName)
230 if (targetName == null)
231 return Build ((string[]) null);
233 return Build (new string [1] { targetName });
236 [MonoTODO ("Not tested")]
237 public bool Build (string [] targetNames)
239 return Build (targetNames, null);
242 [MonoTODO ("Not tested")]
243 public bool Build (string [] targetNames,
244 IDictionary targetOutputs)
246 return Build (targetNames, targetOutputs, BuildSettings.None);
249 [MonoTODO ("Not tested")]
250 public bool Build (string [] targetNames,
251 IDictionary targetOutputs,
252 BuildSettings buildFlags)
256 ParentEngine.StartBuild ();
259 if (targetNames == null || targetNames.Length == 0) {
260 if (defaultTargets != null && defaultTargets.Length != 0)
261 targetNames = defaultTargets;
262 else if (firstTargetName != null)
263 targetNames = new string [1] { firstTargetName};
268 if (!initialTargetsBuilt && initialTargets != null && initialTargets.Length > 0) {
269 foreach (string target in initialTargets) {
270 if (!BuildTarget (target.Trim (), targetOutputs))
273 initialTargetsBuilt = true;
276 foreach (string target in targetNames)
277 if (!BuildTarget (target.Trim (), targetOutputs))
283 bool BuildTarget (string target, IDictionary targetOutputs)
286 throw new ArgumentException ("targetNames cannot contain null strings");
288 if (!targets.Exists (target)) {
290 Console.WriteLine ("Target named '{0}' not found in the project.", target);
294 if (!targets [target].Build ())
297 if (targetOutputs != null)
298 targetOutputs.Add (target, targets [target].Outputs);
304 public string [] GetConditionedPropertyValues (string propertyName)
306 if (conditionedProperties.ContainsKey (propertyName))
307 return conditionedProperties [propertyName].ToArray ();
309 return new string [0];
312 public BuildItemGroup GetEvaluatedItemsByName (string itemName)
314 if (needToReevaluate) {
315 needToReevaluate = false;
319 if (evaluatedItemsByName.ContainsKey (itemName))
320 return evaluatedItemsByName [itemName];
322 return new BuildItemGroup ();
325 public BuildItemGroup GetEvaluatedItemsByNameIgnoringCondition (string itemName)
327 if (needToReevaluate) {
328 needToReevaluate = false;
332 if (evaluatedItemsByNameIgnoringCondition.ContainsKey (itemName))
333 return evaluatedItemsByNameIgnoringCondition [itemName];
335 return new BuildItemGroup ();
338 public string GetEvaluatedProperty (string propertyName)
340 if (needToReevaluate) {
341 needToReevaluate = false;
345 if (propertyName == null)
346 throw new ArgumentNullException ("propertyName");
348 BuildProperty bp = evaluatedProperties [propertyName];
350 return bp == null ? null : (string) bp;
353 [MonoTODO ("We should remember that node and not use XPath to get it")]
354 public string GetProjectExtensions (string id)
356 if (id == null || id == String.Empty)
359 XmlNode node = xmlDocument.SelectSingleNode (String.Format ("/tns:Project/tns:ProjectExtensions/tns:{0}", id), XmlNamespaceManager);
364 return node.InnerXml;
368 public void Load (string projectFileName)
370 this.fullFileName = Path.GetFullPath (projectFileName);
371 DoLoad (new StreamReader (projectFileName));
374 [MonoTODO ("Not tested")]
375 public void Load (TextReader textReader)
377 fullFileName = String.Empty;
381 public void LoadXml (string projectXml)
383 fullFileName = String.Empty;
384 DoLoad (new StringReader (projectXml));
385 MarkProjectAsDirty ();
389 public void MarkProjectAsDirty ()
392 timeOfLastDirty = DateTime.Now;
395 [MonoTODO ("Not tested")]
396 public void RemoveAllItemGroups ()
398 int length = ItemGroups.Count;
399 BuildItemGroup [] groups = new BuildItemGroup [length];
400 ItemGroups.CopyTo (groups, 0);
402 for (int i = 0; i < length; i++)
403 RemoveItemGroup (groups [i]);
405 MarkProjectAsDirty ();
409 [MonoTODO ("Not tested")]
410 public void RemoveAllPropertyGroups ()
412 int length = PropertyGroups.Count;
413 BuildPropertyGroup [] groups = new BuildPropertyGroup [length];
414 PropertyGroups.CopyTo (groups, 0);
416 for (int i = 0; i < length; i++)
417 RemovePropertyGroup (groups [i]);
419 MarkProjectAsDirty ();
424 public void RemoveItem (BuildItem itemToRemove)
426 if (itemToRemove == null)
427 throw new ArgumentNullException ("itemToRemove");
429 if (!itemToRemove.FromXml && !itemToRemove.HasParent)
430 throw new InvalidOperationException ("The object passed in is not part of the project.");
432 BuildItemGroup big = itemToRemove.ParentItemGroup;
434 if (big.Count == 1) {
435 // ParentItemGroup for items from xml and that have parent is the same
436 groupingCollection.Remove (big);
438 if (big.ParentProject != this)
439 throw new InvalidOperationException ("The object passed in is not part of the project.");
441 if (itemToRemove.FromXml)
442 big.RemoveItem (itemToRemove);
444 big.RemoveItem (itemToRemove.ParentItem);
447 MarkProjectAsDirty ();
451 [MonoTODO ("Not tested")]
452 public void RemoveItemGroup (BuildItemGroup itemGroupToRemove)
454 if (itemGroupToRemove == null)
455 throw new ArgumentNullException ("itemGroupToRemove");
457 groupingCollection.Remove (itemGroupToRemove);
458 MarkProjectAsDirty ();
462 // NOTE: does not modify imported projects
463 public void RemoveItemGroupsWithMatchingCondition (string matchingCondition)
465 throw new NotImplementedException ();
469 public void RemoveItemsByName (string itemName)
471 if (itemName == null)
472 throw new ArgumentNullException ("itemName");
474 throw new NotImplementedException ();
477 [MonoTODO ("Not tested")]
478 public void RemovePropertyGroup (BuildPropertyGroup propertyGroupToRemove)
480 if (propertyGroupToRemove == null)
481 throw new ArgumentNullException ("propertyGroupToRemove");
483 groupingCollection.Remove (propertyGroupToRemove);
484 MarkProjectAsDirty ();
488 // NOTE: does not modify imported projects
489 public void RemovePropertyGroupsWithMatchingCondition (string matchCondition)
491 throw new NotImplementedException ();
495 public void ResetBuildStatus ()
497 throw new NotImplementedException ();
500 public void Save (string projectFileName)
502 Save (projectFileName, Encoding.Default);
506 [MonoTODO ("Ignores encoding")]
507 public void Save (string projectFileName, Encoding encoding)
509 xmlDocument.Save (projectFileName);
513 public void Save (TextWriter outTextWriter)
515 xmlDocument.Save (outTextWriter);
519 public void SetImportedProperty (string propertyName,
520 string propertyValue,
522 Project importProject)
524 SetImportedProperty (propertyName, propertyValue, condition, importProject,
525 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup);
528 public void SetImportedProperty (string propertyName,
529 string propertyValue,
531 Project importedProject,
532 PropertyPosition position)
534 SetImportedProperty (propertyName, propertyValue, condition, importedProject,
535 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup, false);
539 public void SetImportedProperty (string propertyName,
540 string propertyValue,
542 Project importedProject,
543 PropertyPosition position,
544 bool treatPropertyValueAsLiteral)
546 throw new NotImplementedException ();
549 public void SetProjectExtensions (string id, string xmlText)
552 throw new ArgumentNullException ("id");
554 throw new ArgumentNullException ("xmlText");
556 XmlNode projectExtensions, node;
558 projectExtensions = xmlDocument.SelectSingleNode ("/tns:Project/tns:ProjectExtensions", XmlNamespaceManager);
560 if (projectExtensions == null) {
561 projectExtensions = xmlDocument.CreateElement ("ProjectExtensions", XmlNamespace);
562 xmlDocument.DocumentElement.AppendChild (projectExtensions);
564 node = xmlDocument.CreateElement (id, XmlNamespace);
565 node.InnerXml = xmlText;
566 projectExtensions.AppendChild (node);
568 node = xmlDocument.SelectSingleNode (String.Format ("/tns:Project/tns:ProjectExtensions/tns:{0}", id), XmlNamespaceManager);
571 node = xmlDocument.CreateElement (id, XmlNamespace);
572 projectExtensions.AppendChild (node);
575 node.InnerXml = xmlText;
579 MarkProjectAsDirty ();
582 public void SetProperty (string propertyName,
583 string propertyValue)
585 SetProperty (propertyName, propertyValue, "true",
586 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup, false);
589 public void SetProperty (string propertyName,
590 string propertyValue,
593 SetProperty (propertyName, propertyValue, condition,
594 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup);
597 public void SetProperty (string propertyName,
598 string propertyValue,
600 PropertyPosition position)
602 SetProperty (propertyName, propertyValue, condition,
603 PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup, false);
607 public void SetProperty (string propertyName,
608 string propertyValue,
610 PropertyPosition position,
611 bool treatPropertyValueAsLiteral)
613 throw new NotImplementedException ();
616 internal void Unload ()
621 internal void CheckUnloaded ()
624 throw new InvalidOperationException ("This project object has been unloaded from the MSBuild engine and is no longer valid.");
627 internal void NeedToReevaluate ()
629 needToReevaluate = true;
632 // Does the actual loading.
633 void DoLoad (TextReader textReader)
636 ParentEngine.RemoveLoadedProject (this);
638 XmlReaderSettings settings = new XmlReaderSettings ();
640 if (SchemaFile != null) {
641 settings.Schemas.Add (null, SchemaFile);
642 settings.ValidationType = ValidationType.Schema;
643 settings.ValidationEventHandler += new ValidationEventHandler (ValidationCallBack);
646 XmlReader xmlReader = XmlReader.Create (textReader, settings);
647 xmlDocument.Load (xmlReader);
649 if (xmlDocument.DocumentElement.Name != "Project") {
650 throw new InvalidProjectFileException (String.Format (
651 "The element <{0}> is unrecognized, or not supported in this context.", xmlDocument.DocumentElement.Name));
654 if (xmlDocument.DocumentElement.GetAttribute ("xmlns") != ns) {
655 throw new InvalidProjectFileException (
656 @"The default XML namespace of the project must be the MSBuild XML namespace." +
657 " If the project is authored in the MSBuild 2003 format, please add " +
658 "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\" to the <Project> element. " +
659 "If the project has been authored in the old 1.0 or 1.2 format, please convert it to MSBuild 2003 format. ");
662 ParentEngine.AddLoadedProject (this);
663 } catch (Exception e) {
664 throw new InvalidProjectFileException (String.Format ("{0}: {1}",
665 fullFileName, e.Message), e);
667 if (textReader != null)
679 groupingCollection = new GroupingCollection (this);
680 imports = new ImportCollection (groupingCollection);
681 usingTasks = new UsingTaskCollection (this);
682 itemGroups = new BuildItemGroupCollection (groupingCollection);
683 propertyGroups = new BuildPropertyGroupCollection (groupingCollection);
684 targets = new TargetCollection (this);
685 last_item_group_containing = new Dictionary <string, BuildItemGroup> ();
687 taskDatabase = new TaskDatabase ();
688 if (ParentEngine.DefaultTasksRegistered)
689 taskDatabase.CopyTasks (ParentEngine.DefaultTasks);
691 if (xmlDocument.DocumentElement.GetAttributeNode ("DefaultTargets") != null)
692 defaultTargets = xmlDocument.DocumentElement.GetAttribute ("DefaultTargets").Split (';');
694 defaultTargets = new string [0];
696 ProcessProjectAttributes (xmlDocument.DocumentElement.Attributes);
697 ProcessElements (xmlDocument.DocumentElement, null);
703 void ProcessProjectAttributes (XmlAttributeCollection attributes)
705 foreach (XmlAttribute attr in attributes) {
707 case "InitialTargets":
708 initialTargets = attr.Value.Split (new char [] {';'},
709 StringSplitOptions.RemoveEmptyEntries);
711 case "DefaultTargets":
712 defaultTargets = attr.Value.Split (new char [] {';'},
713 StringSplitOptions.RemoveEmptyEntries);
719 internal void ProcessElements (XmlElement rootElement, ImportedProject ip)
721 foreach (XmlNode xn in rootElement.ChildNodes) {
722 if (xn is XmlElement) {
723 XmlElement xe = (XmlElement) xn;
725 case "ProjectExtensions":
726 AddProjectExtensions (xe);
737 AddUsingTask (xe, ip);
743 AddItemGroup (xe, ip);
745 case "PropertyGroup":
746 AddPropertyGroup (xe, ip);
752 throw new InvalidProjectFileException ("Invalid element in project file.");
760 evaluatedItems = new BuildItemGroup (null, this, null, true);
761 evaluatedItemsIgnoringCondition = new BuildItemGroup (null, this, null, true);
762 evaluatedItemsByName = new Dictionary <string, BuildItemGroup> (StringComparer.InvariantCultureIgnoreCase);
763 evaluatedItemsByNameIgnoringCondition = new Dictionary <string, BuildItemGroup> (StringComparer.InvariantCultureIgnoreCase);
764 evaluatedProperties = new BuildPropertyGroup (null, null, null, true);
766 InitializeProperties ();
768 groupingCollection.Evaluate ();
770 //FIXME: UsingTasks aren't really evaluated. (shouldn't use expressions or anything)
771 foreach (UsingTask usingTask in UsingTasks)
772 usingTask.Evaluate ();
775 void InitializeProperties ()
779 foreach (BuildProperty gp in GlobalProperties) {
780 bp = new BuildProperty (gp.Name, gp.Value, PropertyType.Global);
781 EvaluatedProperties.AddProperty (bp);
784 foreach (DictionaryEntry de in Environment.GetEnvironmentVariables ()) {
785 bp = new BuildProperty ((string) de.Key, (string) de.Value, PropertyType.Environment);
786 EvaluatedProperties.AddProperty (bp);
789 EvaluatedProperties.AddProperty (new BuildProperty ("MSBuildBinPath", parentEngine.BinPath, PropertyType.Reserved));
791 // FIXME: make some internal method that will work like GetDirectoryName but output String.Empty on null/String.Empty
793 if (FullFileName == String.Empty)
794 projectDir = Environment.CurrentDirectory;
796 projectDir = Path.GetDirectoryName (FullFileName);
798 EvaluatedProperties.AddProperty (new BuildProperty ("MSBuildProjectDirectory", projectDir, PropertyType.Reserved));
801 void AddProjectExtensions (XmlElement xmlElement)
805 void AddMessage (XmlElement xmlElement)
809 void AddTarget (XmlElement xmlElement, ImportedProject importedProject)
811 Target target = new Target (xmlElement, this, importedProject);
812 targets.AddTarget (target);
814 if (firstTargetName == null)
815 firstTargetName = target.Name;
818 void AddUsingTask (XmlElement xmlElement, ImportedProject importedProject)
822 usingTask = new UsingTask (xmlElement, this, importedProject);
823 UsingTasks.Add (usingTask);
826 void AddImport (XmlElement xmlElement, ImportedProject importingProject)
830 import = new Import (xmlElement, this, importingProject);
831 Imports.Add (import);
834 void AddItemGroup (XmlElement xmlElement, ImportedProject importedProject)
836 BuildItemGroup big = new BuildItemGroup (xmlElement, this, importedProject, false);
837 ItemGroups.Add (big);
840 void AddPropertyGroup (XmlElement xmlElement, ImportedProject importedProject)
842 BuildPropertyGroup bpg = new BuildPropertyGroup (xmlElement, this, importedProject, false);
843 PropertyGroups.Add (bpg);
846 void AddChoose (XmlElement xmlElement)
848 BuildChoose bc = new BuildChoose (xmlElement, this);
849 groupingCollection.Add (bc);
852 static void ValidationCallBack (object sender, ValidationEventArgs e)
854 Console.WriteLine ("Validation Error: {0}", e.Message);
857 public bool BuildEnabled {
862 buildEnabled = value;
867 public Encoding Encoding {
868 get { return encoding; }
871 public string DefaultTargets {
873 return xmlDocument.DocumentElement.GetAttribute ("DefaultTargets");
876 xmlDocument.DocumentElement.SetAttribute ("DefaultTargets", value);
877 defaultTargets = value.Split (new char [] {';'}, StringSplitOptions.RemoveEmptyEntries);
881 public BuildItemGroup EvaluatedItems {
883 if (needToReevaluate) {
884 needToReevaluate = false;
887 return evaluatedItems;
891 public BuildItemGroup EvaluatedItemsIgnoringCondition {
893 if (needToReevaluate) {
894 needToReevaluate = false;
897 return evaluatedItemsIgnoringCondition;
901 internal IDictionary <string, BuildItemGroup> EvaluatedItemsByName {
903 // FIXME: do we need to do this here?
904 if (needToReevaluate) {
905 needToReevaluate = false;
908 return evaluatedItemsByName;
912 internal IDictionary <string, BuildItemGroup> EvaluatedItemsByNameIgnoringCondition {
914 // FIXME: do we need to do this here?
915 if (needToReevaluate) {
916 needToReevaluate = false;
919 return evaluatedItemsByNameIgnoringCondition;
923 // For batching implementation
924 Dictionary<string, BuildItemGroup> perBatchItemsByName;
925 Dictionary<string, BuildItemGroup> commonItemsByName;
927 internal void SetBatchedItems (Dictionary<string, BuildItemGroup> perBatchItemsByName, Dictionary<string, BuildItemGroup> commonItemsByName)
929 this.perBatchItemsByName = perBatchItemsByName;
930 this.commonItemsByName = commonItemsByName;
934 internal bool TryGetEvaluatedItemByNameBatched (string itemName, out BuildItemGroup group)
936 if (perBatchItemsByName == null && commonItemsByName == null)
937 return EvaluatedItemsByName.TryGetValue (itemName, out group);
939 if (perBatchItemsByName != null)
940 return perBatchItemsByName.TryGetValue (itemName, out group);
942 if (commonItemsByName != null)
943 return commonItemsByName.TryGetValue (itemName, out group);
949 internal string GetMetadataBatched (string itemName, string metadataName)
951 BuildItemGroup group = null;
952 if (itemName == null) {
953 //unqualified, all items in a batch(bucket) have the
954 //same metadata values
955 group = GetFirst<BuildItemGroup> (perBatchItemsByName.Values);
957 group = GetFirst<BuildItemGroup> (commonItemsByName.Values);
960 TryGetEvaluatedItemByNameBatched (itemName, out group);
964 foreach (BuildItem item in group) {
965 if (item.HasMetadata (metadataName))
966 return item.GetMetadata (metadataName);
972 internal IEnumerable<BuildItemGroup> GetAllItemGroups ()
974 if (perBatchItemsByName == null && commonItemsByName == null)
975 foreach (BuildItemGroup group in EvaluatedItemsByName.Values)
978 if (perBatchItemsByName != null)
979 foreach (BuildItemGroup group in perBatchItemsByName.Values)
982 if (commonItemsByName != null)
983 foreach (BuildItemGroup group in commonItemsByName.Values)
987 T GetFirst<T> (ICollection<T> list)
992 foreach (T t in list)
998 public BuildPropertyGroup EvaluatedProperties {
1000 if (needToReevaluate) {
1001 needToReevaluate = false;
1004 return evaluatedProperties;
1008 public string FullFileName {
1009 get { return fullFileName; }
1010 set { fullFileName = value; }
1013 public BuildPropertyGroup GlobalProperties {
1014 get { return globalProperties; }
1017 throw new ArgumentNullException ("value");
1020 throw new InvalidOperationException ("GlobalProperties can not be set to persisted property group.");
1022 globalProperties = value;
1023 NeedToReevaluate ();
1027 public bool IsDirty {
1028 get { return isDirty; }
1031 public bool IsValidated {
1032 get { return isValidated; }
1033 set { isValidated = value; }
1036 public BuildItemGroupCollection ItemGroups {
1037 get { return itemGroups; }
1040 public ImportCollection Imports {
1041 get { return imports; }
1044 public string InitialTargets {
1046 return xmlDocument.DocumentElement.GetAttribute ("InitialTargets");
1049 xmlDocument.DocumentElement.SetAttribute ("InitialTargets", value);
1050 initialTargets = value.Split (new char [] {';'}, StringSplitOptions.RemoveEmptyEntries);
1054 public Engine ParentEngine {
1055 get { return parentEngine; }
1058 public BuildPropertyGroupCollection PropertyGroups {
1059 get { return propertyGroups; }
1062 public string SchemaFile {
1063 get { return schemaFile; }
1064 set { schemaFile = value; }
1067 public TargetCollection Targets {
1068 get { return targets; }
1071 public DateTime TimeOfLastDirty {
1072 get { return timeOfLastDirty; }
1075 public UsingTaskCollection UsingTasks {
1076 get { return usingTasks; }
1081 get { return xmlDocument.InnerXml; }
1084 internal Dictionary <string, BuildItemGroup> LastItemGroupContaining {
1085 get { return last_item_group_containing; }
1088 internal static XmlNamespaceManager XmlNamespaceManager {
1090 if (manager == null) {
1091 manager = new XmlNamespaceManager (new NameTable ());
1092 manager.AddNamespace ("tns", ns);
1099 internal TaskDatabase TaskDatabase {
1100 get { return taskDatabase; }
1103 internal XmlDocument XmlDocument {
1104 get { return xmlDocument; }
1107 internal static string XmlNamespace {