2010-03-01 Jeffrey Stedfast <fejj@novell.com>
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / GroupingCollection.cs
index 6c3748a3bcd5c0213c7fcb6f37eb8cc319442e8a..35b321d281626ef646b35fcb64bdf2a46061cf33 100644 (file)
@@ -28,6 +28,7 @@
 
 #if NET_2_0
 
+using System;
 using System.Collections;
 using System.Collections.Generic;
 
@@ -36,16 +37,18 @@ namespace Microsoft.Build.BuildEngine {
                
                int     imports;
                int     itemGroups;
+               Project project;
                int     propertyGroups;
                int     chooses;
 
                LinkedList <object>     list;
-               LinkedListNode <object> iterator;
+               LinkedListNode <object> add_iterator;
        
-               public GroupingCollection ()
+               public GroupingCollection (Project project)
                {
                        list = new LinkedList <object> ();
-                       iterator = null;
+                       add_iterator = null;
+                       this.project = project;
                }
 
                public IEnumerator GetChooseEnumerator ()
@@ -99,81 +102,133 @@ namespace Microsoft.Build.BuildEngine {
                {
                        bpg.GroupingCollection = this;
                        propertyGroups++;
-                       if (iterator == null)
+                       if (add_iterator == null)
                                list.AddLast (bpg);
-                       else
-                               list.AddAfter (iterator, bpg);
+                       else {
+                               list.AddAfter (add_iterator, bpg);
+                               add_iterator = add_iterator.Next;
+                       }
                }
                
                internal void Add (BuildItemGroup big)
                {
                        itemGroups++;
-                       if (iterator == null)
+                       if (add_iterator == null)
                                list.AddLast (big);
-                       else
-                               list.AddAfter (iterator, big);
+                       else {
+                               list.AddAfter (add_iterator, big);
+                               add_iterator = add_iterator.Next;
+                       }
                }
                
                internal void Add (BuildChoose bc)
                {
                        chooses++;
-                       if (iterator == null)
+                       if (add_iterator == null)
                                list.AddLast (bc);
-                       else
-                               list.AddAfter (iterator, bc);
+                       else {
+                               list.AddAfter (add_iterator, bc);
+                               add_iterator = add_iterator.Next;
+                       }
                }
 
                internal void Add (Import import)
                {
                        imports++;
-                       if (iterator == null)
+                       if (add_iterator == null)
                                list.AddLast (import);
-                       else
-                               list.AddAfter (iterator, 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);
                }
 
-               // FIXME: check conditions on groups/imports
-               // check what happens with order: import -> 1 2 (probably is entered in wrong order)
-               void Evaluate (EvaluationType type)
+               internal void Evaluate (EvaluationType type)
                {
                        BuildItemGroup big;
                        BuildPropertyGroup bpg;
-                       Import import;
+                       LinkedListNode <object> evaluate_iterator;
 
                        if (type == EvaluationType.Property) {
-                               iterator = list.First;
-
-                               while (iterator != null) {
-                                       if (iterator.Value is BuildPropertyGroup) {
-                                               bpg = (BuildPropertyGroup) iterator.Value;
-                                               bpg.Evaluate ();
-                                       } else if (iterator.Value is Import) {
-                                               import = (Import) iterator.Value;
-                                               import.Evaluate ();
+                               evaluate_iterator = list.First;
+                               add_iterator = list.First;
+
+                               while (evaluate_iterator != null) {
+                                       if (evaluate_iterator.Value is BuildPropertyGroup) {
+                                               bpg = (BuildPropertyGroup) evaluate_iterator.Value;
+                                               if (ConditionParser.ParseAndEvaluate (bpg.Condition, project))
+                                                       bpg.Evaluate ();
                                        }
 
-                                       iterator = iterator.Next;
+                                       // 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 {
-                               iterator = list.First;
+                       } else if (type == EvaluationType.Item) {
+                               evaluate_iterator = list.First;
+                               add_iterator = list.First;
 
-                               while (iterator != null) {
-                                       if (iterator.Value is BuildItemGroup) {
-                                               big = (BuildItemGroup) iterator.Value;
+                               while (evaluate_iterator != null) {
+                                       if (evaluate_iterator.Value is BuildItemGroup) {
+                                               big = (BuildItemGroup) evaluate_iterator.Value;
+                                               if (ConditionParser.ParseAndEvaluate (big.Condition, project))
+                                                       big.Evaluate ();
+                                       }
+
+                                       evaluate_iterator = evaluate_iterator.Next;
+                               }
+                       } else if (type == EvaluationType.Choose) {
+                               evaluate_iterator = list.First;
+                               add_iterator = list.First;
 
-                                               big.Evaluate ();
+                               while (evaluate_iterator != null) {
+                                       if (evaluate_iterator.Value is BuildChoose) {
+                                               BuildChoose bc = (BuildChoose)evaluate_iterator.Value;
+                                               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 ();
+                                               }
                                        }
 
-                                       iterator = iterator.Next;
+                                       evaluate_iterator = evaluate_iterator.Next;
                                }
                        }
+
+                       add_iterator = null;
                }
 
                internal int Imports {
@@ -195,7 +250,8 @@ namespace Microsoft.Build.BuildEngine {
 
        enum EvaluationType {
                Property,
-               Item
+               Item,
+               Choose
        }
 }