Merge pull request #303 from ermshiperete/5278
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / BuildProperty.cs
index ddf5cb6b6f77e43778427378994ffcf021c7adca..62caeda9edbf65629c676554e72c7d44be9087b0 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
@@ -31,48 +33,80 @@ using System;
 using System.Text;
 using System.Xml;
 
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using Mono.XBuild.Utilities;
+
 namespace Microsoft.Build.BuildEngine {
        public class BuildProperty {
        
                XmlElement      propertyElement;
-               XmlAttribute    condition;
                string          finalValue;
+               bool            isImported;
                string          value;
                string          name;
+               Project         parentProject;
                PropertyType    propertyType;
-       
-               public BuildProperty ()
-                       : this (null, null)
+               bool            converting;
+
+               BuildProperty ()
+               {
+               }
+
+               public BuildProperty (string propertyName, string propertyValue)
+                       : this (propertyName, propertyValue, PropertyType.Normal)
                {
+                       if (propertyName == null)
+                               throw new ArgumentNullException ("propertyName");
+                       if (propertyValue == null)
+                               throw new ArgumentNullException ("propertyValue");
                }
 
-               public BuildProperty (string propertyName,
-                               string propertyValue)
+               internal BuildProperty (string propertyName,
+                               string propertyValue, PropertyType propertyType)
                {
                        this.name = propertyName;
                        this.value = propertyValue;
+                       this.finalValue = propertyValue;
+                       this.propertyType = propertyType;
+                       this.isImported = false;
                }
 
+               internal BuildProperty (Project parentProject, XmlElement propertyElement)
+               {
+                       if (propertyElement == null)
+                               throw new ArgumentNullException ("propertyElement");
+
+                       this.propertyElement = propertyElement;
+                       this.propertyType = PropertyType.Normal;
+                       this.parentProject = parentProject;
+                       this.name = propertyElement.Name;
+                       this.value = MSBuildUtils.UnescapeFromXml (propertyElement.InnerXml);
+                       this.isImported = false;
+               }
+
+               [MonoTODO]
                public BuildProperty Clone (bool deepClone)
                {
-                       BuildProperty bp;
-                       
-                       bp = new BuildProperty ();
-                       bp.condition = this.condition;
-                       bp.finalValue = this.finalValue;
-                       bp.name = this.name;
-                       bp.propertyElement = this.propertyElement;
-                       bp.propertyType = this.propertyType;
-                       bp.value = this.value;
-                       
-                       return bp;
-               }
-
-               public static implicit operator string (BuildProperty propertyToCast)
+                       if (deepClone) {
+                               if (FromXml) 
+                                       throw new NotImplementedException ();
+                               else
+                                       return (BuildProperty) this.MemberwiseClone ();
+                       } else {
+                               if (FromXml)
+                                       throw new NotImplementedException ();
+                               else
+                                       throw new InvalidOperationException ("A shallow clone of this object cannot be created.");
+                       }
+               }
+
+               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 ()
@@ -83,50 +117,107 @@ namespace Microsoft.Build.BuildEngine {
                                return Value;
                }
 
-               
-               internal void BindToXml (XmlElement propertyElement)
+               internal void Evaluate ()
                {
-                       if (propertyElement == null)
-                               throw new ArgumentNullException ("propertyElement");
-                       this.propertyElement = propertyElement;
-                       this.condition = propertyElement.GetAttributeNode ("Condition");
-                       this.name = propertyElement.Name;
-                       this.value = propertyElement.InnerText;
+                       BuildProperty evaluated = new BuildProperty (Name, Value);
+
+                       // In evaluate phase, properties are not expanded
+                       Expression exp = new Expression ();
+                       exp.Parse (Value, ParseOptions.None);
+                       evaluated.finalValue = (string) exp.ConvertTo (parentProject, typeof (string),
+                                       ExpressionOptions.DoNotExpandItemRefs);
+
+                       parentProject.EvaluatedProperties.AddProperty (evaluated);
                }
-               
-               internal void UpdateXml ()
+
+               // 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;
+                       }
                }
-               
+
+               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;
+                       }
+               }
+       
                public string Condition {
                        get {
-                               if (condition == null)
-                                       return null;
+                               if (FromXml)
+                                       return propertyElement.GetAttribute ("Condition");
                                else
-                                       return condition.Value;
+                                       return String.Empty;
                        }
                        set {
-                               if (condition != null)
-                                       condition.Value = value;
+                               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.");
                        }
                }
 
                public string FinalValue {
                        get {
-                               if (finalValue == null) {
+                               if (finalValue == null)
                                        return this.@value;
-                               else
+                               else
                                        return finalValue;
                        }
-                       internal set {
-                               finalValue = value;
-                       }
+               }
+               
+               public bool IsImported {
+                       get { return isImported; }
                }
 
                public string Name {
-                       get {
-                               return name;
-                       }
+                       get { return name; }
                }
 
                public string Value {
@@ -135,21 +226,31 @@ namespace Microsoft.Build.BuildEngine {
                        }
                        set {
                                this.@value = value;
+                               if (FromXml) {
+                                       propertyElement.InnerXml = value;
+                               } else {
+                                       finalValue = value;
+                               }
                        }
                }
 
                internal PropertyType PropertyType {
-                       get { return propertyType; }
-                       set { propertyType = value; }
+                       get {
+                               return propertyType;
+                       }
+               }
+
+               internal XmlElement XmlElement {
+                       get { return propertyElement; }
                }
        }
 
        internal enum PropertyType {
                Reserved,
-               CommandLine,
+               Global,
                Normal,
                Environment
        }
 }
 
-#endif
\ No newline at end of file
+#endif