Handle fault messages in duplex callback channel.
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / GroupingCollection.cs
index 2628244d19cc218520ea735c0d75ea0a752c80e8..0ebb654aa25912f25c14345767dbfc7beb041865 100644 (file)
 
 #if NET_2_0
 
+using System;
 using System.Collections;
+using System.Collections.Generic;
 
 namespace Microsoft.Build.BuildEngine {
-       public class GroupingCollection : IEnumerable {
+       internal class GroupingCollection : IEnumerable {
                
-               IList   allGroups;
+               int     imports;
                int     itemGroups;
+               Project project;
                int     propertyGroups;
                int     chooses;
+
+               LinkedList <object>     list;
+               LinkedListNode <object> add_iterator;
        
-               public GroupingCollection ()
+               public GroupingCollection (Project project)
                {
-                       allGroups = new ArrayList ();
+                       list = new LinkedList <object> ();
+                       add_iterator = null;
+                       this.project = project;
                }
 
                public IEnumerator GetChooseEnumerator ()
                {
-                       foreach (object o in allGroups)
+                       foreach (object o in list)
                                if (o is BuildChoose)
                                        yield return o;
                }
 
                public IEnumerator GetEnumerator ()
                {
-                       foreach (object o in allGroups) {
-                               if (o is BuildItemGroup) {
-                                       yield return o;
-                                       continue;
-                               }
-                               if (o is BuildPropertyGroup) {
-                                       yield return o;
-                                       continue;
-                               }
-                               if (o is BuildChoose) {
+                       return list.GetEnumerator ();
+               }
+
+               public IEnumerator GetImportEnumerator ()
+               {
+                       foreach (object o in list)
+                               if (o is Import)
                                        yield return o;
-                               }
-                       }
                }
 
                public IEnumerator GetItemGroupAndChooseEnumerator ()
                {
-                       foreach (object o in allGroups) {
-                               if (o is BuildItemGroup) {
-                                       yield return o;
-                                       continue;
-                               }
-                               if (o is BuildChoose) {
+                       foreach (object o in list)
+                               if (o is BuildItemGroup || o is BuildPropertyGroup)
                                        yield return o;
-                               }
-                       }
                }
 
                public IEnumerator GetItemGroupEnumerator ()
                {
-                       foreach (object o in allGroups)
+                       foreach (object o in list)
                                if (o is BuildItemGroup)
                                        yield return o;
                }
 
                public IEnumerator GetPropertyGroupAndChooseEnumerator ()
                {
-                       foreach (object o in allGroups) {
-                               if (o is BuildPropertyGroup) {
-                                       yield return o;
-                                       continue;
-                               }
-                               if (o is BuildChoose) {
+                       foreach (object o in list)
+                               if (o is BuildPropertyGroup || o is BuildChoose)
                                        yield return o;
-                               }
-                       }
                }
 
                public IEnumerator GetPropertyGroupEnumerator ()
                {
-                       foreach (object o in allGroups) {
+                       foreach (object o in list)
                                if (o is BuildPropertyGroup)
                                        yield return o;
-                       }
                }
                
-               internal void Add (BuildPropertyGroup bpg) {
+               internal void Add (BuildPropertyGroup bpg)
+               {
                        bpg.GroupingCollection = this;
-                       allGroups.Add (bpg);
                        propertyGroups++;
+                       if (add_iterator == null)
+                               list.AddLast (bpg);
+                       else {
+                               list.AddAfter (add_iterator, bpg);
+                               add_iterator = add_iterator.Next;
+                       }
                }
                
-               internal void Add (BuildItemGroup big) {
-                       allGroups.Add (big);
+               internal void Add (BuildItemGroup big)
+               {
                        itemGroups++;
+                       if (add_iterator == null)
+                               list.AddLast (big);
+                       else {
+                               list.AddAfter (add_iterator, big);
+                               add_iterator = add_iterator.Next;
+                       }
                }
                
-               internal void Add (BuildChoose bc) {
-                       allGroups.Add (bc);
+               internal void Add (BuildChoose bc)
+               {
                        chooses++;
+                       if (add_iterator == null)
+                               list.AddLast (bc);
+                       else {
+                               list.AddAfter (add_iterator, bc);
+                               add_iterator = add_iterator.Next;
+                       }
+               }
+
+               internal void Add (Import import)
+               {
+                       imports++;
+                       if (add_iterator == null)
+                               list.AddLast (import);
+                       else {
+                               list.AddAfter (add_iterator, import);
+                               add_iterator = add_iterator.Next;
+                       }
+               }
+
+               internal void Remove (BuildItemGroup big)
+               {
+                       if (big.ParentProject != project)
+                               throw new InvalidOperationException (
+                                       "The \"BuildItemGroup\" object specified does not belong to the correct \"Project\" object.");
+
+                       big.Detach ();
+                       list.Remove (big);
+               }
+
+               internal void Remove (BuildPropertyGroup bpg)
+               {
+                       // FIXME: add bpg.Detach ();
+                       bpg.XmlElement.ParentNode.RemoveChild (bpg.XmlElement);
+                       list.Remove (bpg);
+               }
+
+               internal void Evaluate ()
+               {
+                       Evaluate (EvaluationType.Property);
+                       Evaluate (EvaluationType.Item);
+                       Evaluate (EvaluationType.Choose);
+               }
+
+               internal void Evaluate (EvaluationType type)
+               {
+                       BuildItemGroup big;
+                       BuildPropertyGroup bpg;
+                       LinkedListNode <object> evaluate_iterator;
+
+                       if (type == EvaluationType.Property) {
+                               evaluate_iterator = list.First;
+                               add_iterator = list.First;
+
+                               while (evaluate_iterator != null) {
+                                       if (evaluate_iterator.Value is BuildPropertyGroup) {
+                                               bpg = (BuildPropertyGroup) evaluate_iterator.Value;
+                                               project.PushThisFileProperty (bpg.DefinedInFileName);
+                                               try {
+                                                       if (ConditionParser.ParseAndEvaluate (bpg.Condition, project))
+                                                               bpg.Evaluate ();
+                                               } finally {
+                                                       project.PopThisFileProperty ();
+                                               }
+                                       }
+
+                                       // if it wasn't moved by adding anything because of evaluating a Import shift it
+                                       if (add_iterator == evaluate_iterator)
+                                               add_iterator = add_iterator.Next;
+
+                                       evaluate_iterator = evaluate_iterator.Next;
+                               }
+                       } else if (type == EvaluationType.Item) {
+                               evaluate_iterator = list.First;
+                               add_iterator = list.First;
+
+                               while (evaluate_iterator != null) {
+                                       if (evaluate_iterator.Value is BuildItemGroup) {
+                                               big = (BuildItemGroup) evaluate_iterator.Value;
+                                               project.PushThisFileProperty (big.DefinedInFileName);
+                                               try {
+                                                       if (ConditionParser.ParseAndEvaluate (big.Condition, project))
+                                                               big.Evaluate ();
+                                               } finally {
+                                                       project.PopThisFileProperty ();
+                                               }
+                                       }
+
+                                       evaluate_iterator = evaluate_iterator.Next;
+                               }
+                       } else if (type == EvaluationType.Choose) {
+                               evaluate_iterator = list.First;
+                               add_iterator = list.First;
+
+                               while (evaluate_iterator != null) {
+                                       if (evaluate_iterator.Value is BuildChoose) {
+                                               BuildChoose bc = (BuildChoose)evaluate_iterator.Value;
+                                               project.PushThisFileProperty (bc.DefinedInFileName);
+                                               try {
+                                                       bool whenUsed = false;
+                                                       foreach (BuildWhen bw in bc.Whens) {
+                                                               if (ConditionParser.ParseAndEvaluate (bw.Condition, project)) {
+                                                                       bw.Evaluate ();
+                                                                       whenUsed = true;
+                                                                       break;
+                                                               }
+                                                       }
+                                                       if (!whenUsed && bc.Otherwise != null &&
+                                                               ConditionParser.ParseAndEvaluate (bc.Otherwise.Condition, project)) {
+                                                               bc.Otherwise.Evaluate ();
+                                                       }
+                                               } finally {
+                                                       project.PopThisFileProperty ();
+                                               }
+                                       }
+
+                                       evaluate_iterator = evaluate_iterator.Next;
+                               }
+                       }
+
+                       add_iterator = null;
+               }
+
+               internal int Imports {
+                       get { return this.imports; }
                }
                
                internal int ItemGroups {
@@ -136,6 +262,12 @@ namespace Microsoft.Build.BuildEngine {
                        get { return this.chooses; }
                } 
        }
+
+       enum EvaluationType {
+               Property,
+               Item,
+               Choose
+       }
 }
 
-#endif
\ No newline at end of file
+#endif