Merge pull request #4453 from lambdageek/bug-49721
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / BuildProperty.cs
index 1ebadce9a23e54946020ac6b06902e21e1e8cd67..f0936a3f65be3a40311e12ecc59e3300bfba0591 100644 (file)
@@ -3,8 +3,10 @@
 //
 // Author:
 //   Marek Sieradzki (marek.sieradzki@gmail.com)
+//   Ankit Jain (jankit@novell.com)
 // 
 // (C) 2005 Marek Sieradzki
+// Copyright 2009 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 // 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.Text;
 using System.Xml;
+using System.Collections.Generic;
+
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using Mono.XBuild.Utilities;
 
 namespace Microsoft.Build.BuildEngine {
        public class BuildProperty {
@@ -41,8 +46,9 @@ namespace Microsoft.Build.BuildEngine {
                string          name;
                Project         parentProject;
                PropertyType    propertyType;
+               bool            converting;
 
-               private BuildProperty ()
+               BuildProperty ()
                {
                }
 
@@ -50,11 +56,9 @@ namespace Microsoft.Build.BuildEngine {
                        : this (propertyName, propertyValue, PropertyType.Normal)
                {
                        if (propertyName == null)
-                               throw new ArgumentNullException (null,
-                                       "Parameter \"propertyName\" cannot be null.");
+                               throw new ArgumentNullException ("propertyName");
                        if (propertyValue == null)
-                               throw new ArgumentNullException (null,
-                                       "Parameter \"propertyValue\" cannot be null.");
+                               throw new ArgumentNullException ("propertyValue");
                }
 
                internal BuildProperty (string propertyName,
@@ -76,7 +80,7 @@ namespace Microsoft.Build.BuildEngine {
                        this.propertyType = PropertyType.Normal;
                        this.parentProject = parentProject;
                        this.name = propertyElement.Name;
-                       this.value = propertyElement.InnerText;
+                       this.value = MSBuildUtils.UnescapeFromXml (propertyElement.InnerXml);
                        this.isImported = false;
                }
 
@@ -99,8 +103,9 @@ namespace Microsoft.Build.BuildEngine {
                public static explicit operator string (BuildProperty propertyToCast)
                {
                        if (propertyToCast == null)
-                               throw new ArgumentNullException ("propertyToCast");
-                       return propertyToCast.ToString ();
+                               return String.Empty;
+                       else
+                               return propertyToCast.ToString ();
                }
 
                public override string ToString ()
@@ -113,15 +118,68 @@ namespace Microsoft.Build.BuildEngine {
 
                internal void Evaluate ()
                {
-                       if (FromXml) {
-                               OldExpression exp = new OldExpression (parentProject);
-                               exp.ParseSource (Value);
-                               finalValue = (string) exp.ConvertTo (typeof (string));
-                               parentProject.EvaluatedProperties.AddProperty (this);
+                       BuildProperty evaluated = new BuildProperty (Name, Value);
+
+                       // In evaluate phase, properties are not expanded
+                       evaluated.finalValue = Expression.ParseAs<string> (Value, ParseOptions.None, 
+                               parentProject, ExpressionOptions.DoNotExpandItemRefs);
+
+                       parentProject.EvaluatedProperties.AddProperty (evaluated);
+               }
+
+               // during property's eval phase, this is never reached, as PropertyReference
+               // handles the eval case
+               //
+               // during item's eval phase, we have expand: true, that's what we
+               // do here..
+               //
+               // during non-eval, expand: true
+               // So, its always true here
+               internal string ConvertToString (Project project, ExpressionOptions options)
+               {
+                       if (converting) {
+                               // found ref to @this while trying to ConvertToString
+                               // for @this!
+                               return FinalValue;
+                       }
+
+                       converting = true;
+                       try {
+                               Expression exp = new Expression ();
+
+                               // in non-evaluation phase, properties are always expanded
+                               exp.Parse (FinalValue, options == ExpressionOptions.ExpandItemRefs ?
+                                                       ParseOptions.AllowItems : ParseOptions.None);
+                               return (string) exp.ConvertTo (project, typeof (string), options);
+                       } finally {
+                               converting = false;
                        }
                }
 
-               private bool FromXml {
+               internal ITaskItem[] ConvertToITaskItemArray (Project project, ExpressionOptions options)
+               {
+                       if (converting) {
+                               // found ref to @this while trying to ConvertToITaskItemArray
+                               // for @this!
+                               ITaskItem []items = new ITaskItem [1];
+                               items [0] = new TaskItem (FinalValue);
+                               return items;
+                       }
+
+                       converting = true;
+                       try {
+                               Expression exp = new Expression ();
+
+                               // in non-evaluation phase, properties are always expanded
+                               exp.Parse (FinalValue, ParseOptions.Split | (options == ExpressionOptions.ExpandItemRefs ?
+                                                       ParseOptions.AllowItems : ParseOptions.None));
+                               return (ITaskItem[]) exp.ConvertTo (project, typeof (ITaskItem[]), options);
+                       } finally {
+                               converting = false;
+                       }
+               }
+
+               internal bool FromXml {
                        get {
                                return propertyElement != null;
                        }
@@ -137,6 +195,8 @@ namespace Microsoft.Build.BuildEngine {
                        set {
                                if (FromXml)
                                        propertyElement.SetAttribute ("Condition", value);
+                               else
+                                       throw new InvalidOperationException ("Cannot set a condition on an object not represented by an XML element in the project file.");
                        }
                }
 
@@ -164,7 +224,7 @@ namespace Microsoft.Build.BuildEngine {
                        set {
                                this.@value = value;
                                if (FromXml) {
-                                       propertyElement.InnerText = value;
+                                       propertyElement.InnerXml = value;
                                } else {
                                        finalValue = value;
                                }
@@ -176,6 +236,18 @@ namespace Microsoft.Build.BuildEngine {
                                return propertyType;
                        }
                }
+
+               internal XmlElement XmlElement {
+                       get { return propertyElement; }
+               }
+
+               internal IEnumerable<string> GetAttributes ()
+               {
+                       if (!FromXml)
+                               yield break;
+                       foreach (XmlAttribute attr in propertyElement.Attributes)
+                               yield return attr.Value;
+               }
        }
 
        internal enum PropertyType {
@@ -185,5 +257,3 @@ namespace Microsoft.Build.BuildEngine {
                Environment
        }
 }
-
-#endif