Merge pull request #485 from mtausig/master
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / BuildItemGroup.cs
index 8ec892d326ced9914dc4f6f6b18726c131b72870..444731a8cee60b70538b3055085f8b73478c782c 100644 (file)
@@ -25,8 +25,6 @@
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-#if NET_2_0
-
 using System;
 using System.Reflection;
 using System.Collections;
@@ -38,50 +36,47 @@ using Microsoft.Build.Utilities;
 namespace Microsoft.Build.BuildEngine {
        public class BuildItemGroup : IEnumerable {
        
-               XmlAttribute            condition;
-               bool                    isImported;
                List <BuildItem>        buildItems;
+               ImportedProject         importedProject;
+               XmlElement              itemGroupElement;
                GroupingCollection      parentCollection;
                Project                 parentProject;
-               XmlElement              itemGroupElement;
+               bool                    read_only;
+               bool evaluated;
 
                public BuildItemGroup ()
-                       : this (null, null)
+                       : this (null, null, null, false)
                {
                }
-               
-               internal BuildItemGroup (XmlElement xmlElement, Project project)
+
+               internal BuildItemGroup (Project project)
+                       : this (null, project, null, false)
+               {
+               }
+
+               internal BuildItemGroup (XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly)
                {
-                       this.itemGroupElement = xmlElement;
                        this.buildItems = new List <BuildItem> ();
-                       this.isImported = false;
+                       this.importedProject = importedProject;
+                       this.itemGroupElement = xmlElement;
                        this.parentProject = project;
+                       this.read_only = readOnly;
                        
                        if (!FromXml)
                                return;
 
-                       this.condition = xmlElement.GetAttributeNode ("Condition");
                        foreach (XmlNode xn in xmlElement.ChildNodes) {
-                               if (xn is XmlElement == false)
+                               if (!(xn is XmlElement))
                                        continue;
                                        
                                XmlElement xe = (XmlElement) xn;
                                BuildItem bi = new BuildItem (xe, this);
                                buildItems.Add (bi);
+                               project.LastItemGroupContaining [bi.Name] = this;
                        }
-               }
 
-               internal void Evaluate ()
-               {
-                       foreach (BuildItem bi in buildItems) {
-                               if (bi.Condition == String.Empty)
-                                       bi.Evaluate ();
-                               else {
-                                       ConditionExpression ce = ConditionParser.ParseCondition (bi.Condition);
-                                       if (ce.BoolEvaluate (parentProject))
-                                               bi.Evaluate ();
-                               }
-                       }
+                       DefinedInFileName = importedProject != null ? importedProject.FullFileName :
+                                               project != null ? project.FullFileName : null;
                }
 
                public BuildItem AddNewItem (string itemName,
@@ -90,42 +85,66 @@ namespace Microsoft.Build.BuildEngine {
                        return AddNewItem (itemName, itemInclude, false);
                }
                
-               // FIXME: use expression
                [MonoTODO]
                public BuildItem AddNewItem (string itemName,
                                             string itemInclude,
                                             bool treatItemIncludeAsLiteral)
                {
-                       BuildItem bi = new BuildItem (itemName, itemInclude);
-                       buildItems.Add (bi);
-                       return bi;
-               }
-               
-               internal void AddItem (BuildItem buildItem)
-               {
-                       buildItems.Add (buildItem);
+                       BuildItem item;
+
+                       if (treatItemIncludeAsLiteral)
+                               itemInclude = Utilities.Escape (itemInclude);
+
+                       if (FromXml) {
+                               XmlElement element = itemGroupElement.OwnerDocument.CreateElement (itemName, Project.XmlNamespace);
+                               itemGroupElement.AppendChild (element);
+                               element.SetAttribute ("Include", itemInclude);
+                               item = new BuildItem (element, this);
+                       } else {
+                               item = new BuildItem (itemName, itemInclude);
+                               item.ParentItemGroup = this;
+                       }
+
+                       item.Evaluate (null, true);
+
+                       if (!read_only)
+                               buildItems.Add (item);
+
+                       if (parentProject != null) {
+                               parentProject.MarkProjectAsDirty ();
+                               parentProject.NeedToReevaluate ();
+                       }
+
+                       return item;
                }
                
-               internal void AddItem (string name, ITaskItem taskItem)
-               {
-                       BuildItem buildItem;
-                       buildItem = new BuildItem (name, taskItem);
-                       buildItems.Add (buildItem);
-               }
-
-               [MonoTODO]
                public void Clear ()
                {
-                       //FIXME: should this remove all build items?
+                       if (FromXml)
+                               itemGroupElement.RemoveAll ();
+                       
                        buildItems = new List <BuildItem> ();
+
+                       if (parentProject != null) {
+                               parentProject.MarkProjectAsDirty ();
+                               parentProject.NeedToReevaluate ();
+                       }
                }
 
                [MonoTODO]
                public BuildItemGroup Clone (bool deepClone)
                {
-                       BuildItemGroup big = new BuildItemGroup ();
-                       // FIXME: add copying of items
-                       return big;
+                       if (deepClone) {
+                               if (FromXml)
+                                       throw new NotImplementedException ();
+                               else
+                                       throw new NotImplementedException ();
+                       } else {
+                               if (FromXml)
+                                       throw new InvalidOperationException ("A shallow clone of this object cannot be created.");
+                               else
+                                       throw new NotImplementedException ();
+                       }
                }
 
                public IEnumerator GetEnumerator ()
@@ -133,77 +152,138 @@ namespace Microsoft.Build.BuildEngine {
                        return buildItems.GetEnumerator ();
                }
 
-               [MonoTODO]
                public void RemoveItem (BuildItem itemToRemove)
                {
+                       if (itemToRemove == null)
+                               return;
+
+                       itemToRemove.Detach ();
+
                        buildItems.Remove (itemToRemove);
                }
 
-               [MonoTODO]
                public void RemoveItemAt (int index)
                {
-                       buildItems.RemoveAt (index);
+                       BuildItem item = buildItems [index];
+
+                       RemoveItem (item);
                }
 
                public BuildItem[] ToArray ()
                {
                        return buildItems.ToArray ();
                }
-               
-               internal string ConvertToString (OldExpression transform,
-                                                OldExpression separator)
+
+               internal void AddItem (BuildItem buildItem)
+               {
+                       buildItems.Add (buildItem);
+               }
+
+               internal void AddItem (string name, ITaskItem taskItem)
+               {
+                       BuildItem buildItem;
+                       buildItem = new BuildItem (name, taskItem);
+                       buildItem.ParentItemGroup = this;
+                       buildItems.Add (buildItem);
+               }
+
+               // In eval phase, any ref'ed item would've already been expanded
+               // or it doesnt exist, so dont expand again
+               // In non-eval, items have _already_ been expanded, so dont expand again
+               // So, ignore @options
+               internal string ConvertToString (Expression transform,
+                                                Expression separator, ExpressionOptions options)
                {
                        string separatorString;
                        
+                       // Item refs are not expanded for separator or transform
                        if (separator == null)
                                separatorString = ";";
                        else
-                               separatorString = (string) separator.ConvertTo (typeof (string));
+                               separatorString = (string) separator.ConvertTo (parentProject, typeof (string),
+                                                               ExpressionOptions.DoNotExpandItemRefs);
                
                        string[] items = new string [buildItems.Count];
                        int i = 0;
                        foreach (BuildItem bi in  buildItems)
-                               items [i++] = bi.ConvertToString (transform);
+                               items [i++] = bi.ConvertToString (transform, ExpressionOptions.DoNotExpandItemRefs);
                        return String.Join (separatorString, items);
                }
-               
-               internal ITaskItem[] ConvertToITaskItemArray (OldExpression transform)
+
+               // In eval phase, any ref'ed item would've already been expanded
+               // or it doesnt exist, so dont expand again
+               // In non-eval, items have _already_ been expanded, so dont expand again
+               // So, ignore @options
+               internal ITaskItem[] ConvertToITaskItemArray (Expression transform, Expression separator, ExpressionOptions options)
                {
+                       if (separator != null)
+                               // separator present, so return as a single "join'ed" string
+                               return new ITaskItem [] {
+                                       new TaskItem (ConvertToString (transform, separator, options))
+                               };
+
                        ITaskItem[] array = new ITaskItem [buildItems.Count];
                        int i = 0;
                        foreach (BuildItem item in buildItems)
-                               array [i++] = item.ConvertToITaskItem (transform);
+                               array [i++] = item.ConvertToITaskItem (transform, ExpressionOptions.DoNotExpandItemRefs);
                        return array;
                }
 
+               internal void Detach ()
+               {
+                       if (!FromXml)
+                               throw new InvalidOperationException ();
+
+                       itemGroupElement.ParentNode.RemoveChild (itemGroupElement);
+               }
+
+               internal void Evaluate ()
+               {
+                       if (evaluated)
+                               return;
+                       foreach (BuildItem bi in buildItems) {
+                               if (bi.Condition == String.Empty)
+                                       bi.Evaluate (parentProject, true);
+                               else {
+                                       ConditionExpression ce = ConditionParser.ParseCondition (bi.Condition);
+                                       bi.Evaluate (parentProject, ce.BoolEvaluate (parentProject));
+                               }
+                       }
+                       evaluated = true;
+               }               
+
+               internal void ReplaceWith (BuildItem item, List <BuildItem> list)
+               {
+                       int index = buildItems.IndexOf (item);
+                       buildItems.RemoveAt (index);
+                       buildItems.InsertRange (index, list);
+               }
+               
                public string Condition {
                        get {
-                               if (condition != null)
-                                       return condition.Value;
+                               if (FromXml)
+                                       return itemGroupElement.GetAttribute ("Condition");
                                else
                                        return String.Empty;
                        }
                        set {
-                               if (condition != null)
-                                       condition.Value = value;
+                               if (FromXml)
+                                       itemGroupElement.SetAttribute ("Condition", value);
+                               else
+                                       throw new InvalidOperationException ("Cannot set a condition on an object not represented by an XML element in the project file.");
                        }
                }
 
                public int Count {
-                       get {
-                               if (buildItems != null)
-                                       return buildItems.Count;
-                               else
-                                       return 0;
-                       }
+                       get { return buildItems.Count; }
                }
 
                public bool IsImported {
-                       get {
-                               return isImported;
-                       }
+                       get { return importedProject != null; }
                }
 
+               
+               [MonoTODO]
                public BuildItem this [int index] {
                        get {
                                return buildItems [index];
@@ -215,16 +295,27 @@ namespace Microsoft.Build.BuildEngine {
                        set { parentCollection = value; }
                }
                
-               internal Project Project {
+               internal Project ParentProject {
                        get { return parentProject; }
+                       set {
+                               if (parentProject != null)
+                                       throw new InvalidOperationException ("parentProject is already set");
+                               parentProject = value;
+                       }
                }
 
+               internal string DefinedInFileName { get; private set; }
+
                internal bool FromXml {
                        get {
                                return itemGroupElement != null;
                        }
                }
+
+               internal XmlElement XmlElement {
+                       get {
+                               return itemGroupElement;
+                       }       
+               }
        }
 }
-
-#endif