Merge pull request #900 from Blewzman/FixAggregateExceptionGetBaseException
[mono.git] / mcs / class / Microsoft.Build / Microsoft.Build.Evaluation / ProjectProperty.cs
index b930f9b7d98506f6b5cfae0794fd66af385e1a52..f2bdc9eda791767beeea6248d967f3b58ad2bddd 100644 (file)
@@ -2,8 +2,9 @@
 //
 // Author:
 //   Rolf Bjarne Kvinge (rolf@xamarin.com)
+//   Atsushi Enomoto (atsushi@xamarin.com)
 //
-// Copyright (C) 2011 Xamarin Inc.
+// Copyright (C) 2011,2013 Xamarin Inc.
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 //
 
 using System;
+using System.Linq;
 using Microsoft.Build.Construction;
+using Microsoft.Build.Internal;
+using System.Collections.Generic;
+using System.Reflection;
+using System.IO;
 
 namespace Microsoft.Build.Evaluation
 {
@@ -42,9 +48,7 @@ namespace Microsoft.Build.Evaluation
                }
 
                public string EvaluatedValue {
-                       get {
-                               throw new NotImplementedException ();
-                       }
+                       get { return InternalEvaluatedValue; }
                }
 
                public abstract bool IsEnvironmentProperty { get; }
@@ -56,9 +60,12 @@ namespace Microsoft.Build.Evaluation
 
                public abstract bool IsReservedProperty { get; }
 
+               internal virtual bool IsWellKnownProperty {
+                       get { return false; }
+               }
+
                public abstract string Name { get; }
 
-               [MonoTODO]
                public abstract ProjectProperty Predecessor { get; }
 
                public Project Project { get; private set; }
@@ -66,6 +73,8 @@ namespace Microsoft.Build.Evaluation
                public abstract string UnevaluatedValue { get; set; }
 
                public abstract ProjectPropertyElement Xml { get; }
+               
+               internal abstract string InternalEvaluatedValue { get; }
        }
 
        // copy from MS.Build.Engine/BuildProperty.cs
@@ -78,14 +87,23 @@ namespace Microsoft.Build.Evaluation
        
        internal abstract class BaseProjectProperty : ProjectProperty
        {
-               public BaseProjectProperty (Project project, PropertyType propertyType)
+               public BaseProjectProperty (Project project, PropertyType propertyType, string name)
                        : base (project)
                {
                        property_type = propertyType;
+                       this.name = name;
+                       predecessor = project.Properties.FirstOrDefault (p => p.Name.Equals (name, StringComparison.OrdinalIgnoreCase));
+                       if (predecessor != null)
+                               project.RemoveProperty (predecessor);
                }
                
                PropertyType property_type;
                
+               readonly string name;
+               public override string Name {
+                       get { return name; }
+               }
+               
                public override bool IsEnvironmentProperty {
                        get { return property_type == PropertyType.Environment; }
                }
@@ -93,56 +111,114 @@ namespace Microsoft.Build.Evaluation
                        get { return property_type == PropertyType.Global; }
                }
                public override bool IsImported {
-                       get {
-                               throw new NotImplementedException ();
-                       }
+                       get { return false; }
                }
                public override bool IsReservedProperty {
                        get { return property_type == PropertyType.Reserved; }
                }
+               readonly ProjectProperty predecessor; 
                public override ProjectProperty Predecessor {
-                       get {
-                               throw new NotImplementedException ();
-                       }
+                       get { return predecessor; }
+               }
+       }
+       
+       internal abstract class ImmutableProjectProperty : BaseProjectProperty
+       {
+               public ImmutableProjectProperty (Project project, PropertyType propertyType, string name)
+                       : base (project, propertyType, name)
+               {
+               }
+               
+               internal override string InternalEvaluatedValue {
+                       get { return UnevaluatedValue; }
+               }
+       }
+       
+       internal abstract class MutableProjectProperty : BaseProjectProperty
+       {
+               public MutableProjectProperty (Project project, PropertyType propertyType, string name)
+                       : base (project, propertyType, name)
+               {
+               }
+               
+               string evaluated_value; // see UpdateEvaluatedValue().
+               internal void UpdateEvaluatedValue ()
+               {
+                       evaluated_value = Project.ExpandString (UnevaluatedValue);
+               }
+               
+               internal override string InternalEvaluatedValue {
+                       get { return evaluated_value; }
                }
        }
        
-       internal class XmlProjectProperty : BaseProjectProperty
+       internal class XmlProjectProperty : MutableProjectProperty
        {
-               public XmlProjectProperty (Project project, ProjectPropertyElement xml, PropertyType propertyType)
-                       : base (project, propertyType)
+               public XmlProjectProperty (Project project, ProjectPropertyElement xml, PropertyType propertyType, bool isImported)
+                       : base (project, propertyType, xml.Name)
                {
                        this.xml = xml;
+                       this.is_imported = isImported;
+                       UpdateEvaluatedValue ();
                }
                
-               ProjectPropertyElement xml;
+               readonly ProjectPropertyElement xml;
+               readonly bool is_imported;
                
-               public override string Name {
-                       get { return xml.Name; }
+               public override bool IsImported {
+                       get { return is_imported; }
                }
+               
                public override string UnevaluatedValue {
                        get { return xml.Value; }
                        set { xml.Value = value; }
                }
+               
                public override ProjectPropertyElement Xml {
                        get { return xml; }
                }
        }
        
-       internal class EnvironmentProjectProperty : BaseProjectProperty
+       internal class EnvironmentProjectProperty : ImmutableProjectProperty
        {
-               public EnvironmentProjectProperty (Project project, string name, string value)
-                       : base (project, PropertyType.Environment)
+               static string extensions_path;
+               internal static string DefaultExtensionsPath {
+                       get {
+                               if (extensions_path == null) {
+                                       // NOTE: code from mcs/tools/gacutil/driver.cs
+                                       PropertyInfo gac = typeof (System.Environment).GetProperty (
+                                                       "GacPath", BindingFlags.Static | BindingFlags.NonPublic);
+
+                                       if (gac != null) {
+                                               MethodInfo get_gac = gac.GetGetMethod (true);
+                                               string gac_path = (string) get_gac.Invoke (null, null);
+                                               extensions_path = Path.GetFullPath (Path.Combine (
+                                                                       gac_path, Path.Combine ("..", "xbuild")));
+                                       }
+                               }
+                               return extensions_path;
+                       }
+               }
+               
+               public EnvironmentProjectProperty (Project project, string name, string value, bool wellknown = false)
+                       : base (project, PropertyType.Environment, name)
                {
-                       this.name = name;
                        this.value = value;
+                       this.wellknown = wellknown;
                }
                
-               readonly string name, value;
-               
-               public override string Name {
-                       get { return name; }
+               readonly string value;
+               readonly bool wellknown;
+
+               internal override bool IsWellKnownProperty {
+                       get { return wellknown; }
                }
+
+               // It can override possible another environment vairable property BUT never gives Predecessor.
+               public override ProjectProperty Predecessor {
+                       get { return null; }
+               }
+               
                public override string UnevaluatedValue {
                        get { return value; }
                        set { throw new InvalidOperationException (string.Format ("You cannot change value of environment property '{0}'.", Name)); }
@@ -152,20 +228,16 @@ namespace Microsoft.Build.Evaluation
                }
        }
        
-       internal class GlobalProjectProperty : BaseProjectProperty
+       internal class GlobalProjectProperty : ImmutableProjectProperty
        {
                public GlobalProjectProperty (Project project, string name, string value)
-                       : base (project, PropertyType.Global)
+                       : base (project, PropertyType.Global, name)
                {
-                       this.name = name;
                        this.value = value;
                }
                
-               readonly string name, value;
+               readonly string value;
                
-               public override string Name {
-                       get { return name; }
-               }
                public override string UnevaluatedValue {
                        get { return value; }
                        set { throw new InvalidOperationException (string.Format ("You cannot change value of global property '{0}'.", Name)); }
@@ -174,5 +246,43 @@ namespace Microsoft.Build.Evaluation
                        get { return null; }
                }
        }
-}
+       
+       internal class ManuallyAddedProjectProperty : MutableProjectProperty
+       {
+               public ManuallyAddedProjectProperty (Project project, string name, string value)
+                       : base (project, PropertyType.Normal, name)
+               {
+                       this.UnevaluatedValue = value;
+               }
+               
+               public override string UnevaluatedValue { get; set; }
+               
+               public override ProjectPropertyElement Xml {
+                       get { return null; }
+               }
+       }
+       
+       internal class ReservedProjectProperty : ImmutableProjectProperty
+       {
+               public ReservedProjectProperty (Project project, string name, Func<string> value)
+                       : base (project, PropertyType.Reserved, name)
+               {
+                       this.value = value;
+               }
+
+               // make sure it does not give access to any possible attempted overrrides.
+               public override ProjectProperty Predecessor {
+                       get { return null; }
+               }
 
+               readonly Func<string> value;
+               public override string UnevaluatedValue {
+                       get { return value (); }
+                       set { throw new InvalidOperationException (string.Format ("You cannot change value of reserved property '{0}'.", Name)); }
+               }
+               
+               public override ProjectPropertyElement Xml {
+                       get { return null; }
+               }
+       }
+}