In class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine:
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / BuildItem.cs
index b0508e958a33b5ff9508f286acfe498ed16c58cc..45792185cb879213d6d91e197977b0e4ac36be8b 100644 (file)
@@ -41,7 +41,7 @@ using Mono.XBuild.Utilities;
 namespace Microsoft.Build.BuildEngine {
        public class BuildItem {
 
-               BuildItemGroup  child_items;
+               List<BuildItem> child_items;
                XmlElement      itemElement;
                string          finalItemSpec;
                bool            isImported;
@@ -59,6 +59,9 @@ namespace Microsoft.Build.BuildEngine {
                
                public BuildItem (string itemName, ITaskItem taskItem)
                {
+                       if (taskItem == null)
+                               throw new ArgumentNullException ("taskItem");
+
                        this.name = itemName;
                        this.finalItemSpec = taskItem.ItemSpec;
                        this.itemInclude = Utilities.Escape (taskItem.ItemSpec);
@@ -79,10 +82,10 @@ namespace Microsoft.Build.BuildEngine {
                        unevaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
                        evaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
                }
-               
+
                internal BuildItem (XmlElement itemElement, BuildItemGroup parentItemGroup)
                {
-                       child_items = new BuildItemGroup ();
+                       child_items = new List<BuildItem> ();
                        isImported = parentItemGroup.IsImported;
                        unevaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
                        evaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
@@ -99,7 +102,7 @@ namespace Microsoft.Build.BuildEngine {
                        isImported = parent.isImported;
                        name = parent.Name;
                        parent_item = parent;
-                       parent_item.child_items.AddItem (this);
+                       parent_item.child_items.Add (this);
                        parent_item_group = parent.parent_item_group;
                        unevaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable (parent.unevaluatedMetadata);
                        evaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable (parent.evaluatedMetadata);
@@ -107,8 +110,11 @@ namespace Microsoft.Build.BuildEngine {
                
                public void CopyCustomMetadataTo (BuildItem destinationItem)
                {
+                       if (destinationItem == null)
+                               throw new ArgumentNullException ("destinationItem");
+
                        foreach (DictionaryEntry de in unevaluatedMetadata)
-                               destinationItem.AddMetadata ((string) de.Key, (string) de.Value, false);
+                               destinationItem.AddMetadata ((string) de.Key, (string) de.Value);
                }
                
                [MonoTODO]
@@ -119,6 +125,11 @@ namespace Microsoft.Build.BuildEngine {
 
                public string GetEvaluatedMetadata (string metadataName)
                {
+                       if (ReservedNameUtils.IsReservedMetadataName (metadataName)) {
+                               string metadata = ReservedNameUtils.GetReservedMetadata (FinalItemSpec, metadataName);
+                               return (metadataName.ToLower () == "fullpath") ? Utilities.Escape (metadata) : metadata;
+                       }
+
                        if (evaluatedMetadata.Contains (metadataName))
                                return (string) evaluatedMetadata [metadataName];
                        else
@@ -152,6 +163,17 @@ namespace Microsoft.Build.BuildEngine {
                        if (ReservedNameUtils.IsReservedMetadataName (metadataName))
                                throw new ArgumentException (String.Format ("\"{0}\" is a reserved item meta-data, and cannot be modified or deleted.",
                                        metadataName));
+
+                       if (FromXml) {
+                               if (unevaluatedMetadata.Contains (metadataName)) {
+                                       XmlNode node = itemElement [metadataName];
+                                       itemElement.RemoveChild (node);
+                               }
+                       } else if (HasParentItem) {
+                               if (parent_item.child_items.Count > 1)
+                                       SplitParentItem ();
+                               parent_item.RemoveMetadata (metadataName);
+                       } 
                        
                        DeleteMetadata (metadataName);
                }
@@ -176,40 +198,40 @@ namespace Microsoft.Build.BuildEngine {
                                throw new ArgumentException (String.Format ("\"{0}\" is a reserved item meta-data, and cannot be modified or deleted.",
                                        metadataName));
 
+                       if (treatMetadataValueAsLiteral && !HasParentItem)
+                               metadataValue = Utilities.Escape (metadataValue);
+
                        if (FromXml) {
                                XmlElement element = itemElement [metadataName];
                                if (element == null) {
                                        element = itemElement.OwnerDocument.CreateElement (metadataName, Project.XmlNamespace);
-                                       // FIXME treat as literal
                                        element.InnerText = metadataValue;
                                        itemElement.AppendChild (element);
                                } else
                                        element.InnerText = metadataValue;
-                       } else if (HasParent) {
-                               if (parent_item.child_items.Count == 1)
-                                       parent_item.SetMetadata (metadataName, metadataValue, treatMetadataValueAsLiteral);
-                               else {
+                       } else if (HasParentItem) {
+                               if (parent_item.child_items.Count > 1)
                                        SplitParentItem ();
-                                       parent_item.SetMetadata (metadataName, metadataValue, treatMetadataValueAsLiteral);
-                               }
+                               parent_item.SetMetadata (metadataName, metadataValue, treatMetadataValueAsLiteral);
+                       }
+                       if (FromXml || HasParentItem) {
+                               parent_item_group.ParentProject.MarkProjectAsDirty ();
+                               parent_item_group.ParentProject.NeedToReevaluate ();
                        }
                        
                        DeleteMetadata (metadataName);
-                       AddMetadata (metadataName, metadataValue, treatMetadataValueAsLiteral);
+                       AddMetadata (metadataName, metadataValue);
                }
 
-               void AddMetadata (string name, string value, bool literal)
+               void AddMetadata (string name, string value)
                {
                        if (parent_item_group != null) {
                                Expression e = new Expression ();
-                               e.Parse (value);
-                               evaluatedMetadata.Add (name, (string) e.ConvertTo (parent_item_group.Project, typeof (string)));
+                               e.Parse (value, true);
+                               evaluatedMetadata.Add (name, (string) e.ConvertTo (parent_item_group.ParentProject, typeof (string)));
                        } else
                                evaluatedMetadata.Add (name, Utilities.Unescape (value));
                                
-                       if (literal)
-                               unevaluatedMetadata.Add (name, Utilities.Escape (value));
-                       else
                                unevaluatedMetadata.Add (name, value);
                }
 
@@ -226,21 +248,21 @@ namespace Microsoft.Build.BuildEngine {
                {
                        // FIXME: maybe make Expression.ConvertTo (null, ...) work as Utilities.Unescape ()?
                        if (project == null) {
-                               this.finalItemSpec = Utilities.Unescape (itemInclude);
+                               this.finalItemSpec = Utilities.Unescape (Include);
                                return;
                        }
                        
                        foreach (XmlElement xe in itemElement.ChildNodes)
-                               AddMetadata (xe.Name, xe.InnerText, false);
+                               AddMetadata (xe.Name, xe.InnerText);
 
                        DirectoryScanner directoryScanner;
                        Expression includeExpr, excludeExpr;
                        string includes, excludes;
 
                        includeExpr = new Expression ();
-                       includeExpr.Parse (Include);
+                       includeExpr.Parse (Include, true);
                        excludeExpr = new Expression ();
-                       excludeExpr.Parse (Exclude);
+                       excludeExpr.Parse (Exclude, true);
                        
                        includes = (string) includeExpr.ConvertTo (project, typeof (string));
                        excludes = (string) excludeExpr.ConvertTo (project, typeof (string));
@@ -308,7 +330,7 @@ namespace Microsoft.Build.BuildEngine {
                {
                        if (FromXml)
                                itemElement.ParentNode.RemoveChild (itemElement);
-                       else if (HasParent) {
+                       else if (HasParentItem) {
                                if (parent_item.child_items.Count > 1)
                                        SplitParentItem ();
                                parent_item.Detach ();
@@ -327,9 +349,9 @@ namespace Microsoft.Build.BuildEngine {
                                        if (o is string) {
                                                sb.Append ((string)o);
                                        } else if (o is PropertyReference) {
-                                               sb.Append (((PropertyReference)o).ConvertToString (parent_item_group.Project));
+                                               sb.Append (((PropertyReference)o).ConvertToString (parent_item_group.ParentProject));
                                        } else if (o is ItemReference) {
-                                               sb.Append (((ItemReference)o).ConvertToString (parent_item_group.Project));
+                                               sb.Append (((ItemReference)o).ConvertToString (parent_item_group.ParentProject));
                                        } else if (o is MetadataReference) {
                                                sb.Append (GetMetadata (((MetadataReference)o).MetadataName));
                                        }
@@ -366,7 +388,7 @@ namespace Microsoft.Build.BuildEngine {
                        parent.itemElement.ParentNode.InsertAfter (newElement, insertAfter);
 
                        newParent = new BuildItem (newElement, parent.parent_item_group);
-                       newParent.child_items.AddItem (child);
+                       newParent.child_items.Add (child);
                        child.parent_item = newParent;
 
                        return newParent;
@@ -382,7 +404,7 @@ namespace Microsoft.Build.BuildEngine {
                        set {
                                if (FromXml)
                                        itemElement.SetAttribute ("Condition", value);
-                               else if (!HasParent)
+                               else if (!HasParentItem)
                                        throw new InvalidOperationException ("Cannot set a condition on an object not represented by an XML element in the project file.");
                        }
                }
@@ -410,7 +432,7 @@ namespace Microsoft.Build.BuildEngine {
                        get {
                                if (FromXml)
                                        return itemElement.GetAttribute ("Include");
-                               else if (HasParent)
+                               else if (HasParentItem)
                                        return parent_item.Include;
                                else
                                        return itemInclude;
@@ -418,7 +440,7 @@ namespace Microsoft.Build.BuildEngine {
                        set {
                                if (FromXml)
                                        itemElement.SetAttribute ("Include", value);
-                               else if (HasParent) {
+                               else if (HasParentItem) {
                                        if (parent_item.child_items.Count > 1)
                                                SplitParentItem ();
                                        parent_item.Include = value;
@@ -435,7 +457,7 @@ namespace Microsoft.Build.BuildEngine {
                        get {
                                if (FromXml)
                                        return itemElement.Name;
-                               else if (HasParent)
+                               else if (HasParentItem)
                                        return parent_item.Name;
                                else
                                        return name;
@@ -449,7 +471,7 @@ namespace Microsoft.Build.BuildEngine {
                                                newElement.AppendChild (xe.Clone ());
                                        itemElement.ParentNode.ReplaceChild (newElement, itemElement);
                                        itemElement = newElement;
-                               } else if (HasParent) {
+                               } else if (HasParentItem) {
                                        if (parent_item.child_items.Count > 1)
                                                SplitParentItem ();
                                        parent_item.Name = value;
@@ -462,7 +484,7 @@ namespace Microsoft.Build.BuildEngine {
                        get { return itemElement != null; }
                }
                
-               internal bool HasParent {
+               internal bool HasParentItem {
                        get { return parent_item != null; }
                }
 
@@ -472,6 +494,7 @@ namespace Microsoft.Build.BuildEngine {
 
                internal BuildItemGroup ParentItemGroup {
                        get { return parent_item_group; }
+                       set { parent_item_group = value; }
                }
        }
 }