4 // Rolf Bjarne Kvinge (rolf@xamarin.com)
5 // Atsushi Enomoto (atsushi@xamarin.com)
7 // Copyright (C) 2011,2013 Xamarin Inc.
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using Microsoft.Build.Construction;
32 using Microsoft.Build.Internal;
33 using System.Collections.Generic;
34 using System.Reflection;
37 namespace Microsoft.Build.Evaluation
39 // In .NET 4.0 MSDN says it is non-abstract, but some of those
40 // members are abstract and had been there since 4.0.
41 // I take this as doc bug, as non-abstract to abstract is a
42 // breaking change and I'd rather believe API designer's sanity.
43 public abstract class ProjectProperty
45 internal ProjectProperty (Project project) // hide default ctor
50 public string EvaluatedValue {
51 get { return InternalEvaluatedValue; }
54 public abstract bool IsEnvironmentProperty { get; }
56 public abstract bool IsGlobalProperty { get; }
59 public abstract bool IsImported { get; }
61 public abstract bool IsReservedProperty { get; }
63 internal virtual bool IsWellKnownProperty {
67 public abstract string Name { get; }
69 public abstract ProjectProperty Predecessor { get; }
71 public Project Project { get; private set; }
73 public abstract string UnevaluatedValue { get; set; }
75 public abstract ProjectPropertyElement Xml { get; }
77 internal abstract string InternalEvaluatedValue { get; }
80 // copy from MS.Build.Engine/BuildProperty.cs
81 internal enum PropertyType {
88 internal abstract class BaseProjectProperty : ProjectProperty
90 public BaseProjectProperty (Project project, PropertyType propertyType, string name)
93 property_type = propertyType;
95 predecessor = project.Properties.FirstOrDefault (p => p.Name.Equals (name, StringComparison.OrdinalIgnoreCase));
96 if (predecessor != null)
97 project.RemoveProperty (predecessor);
100 PropertyType property_type;
102 readonly string name;
103 public override string Name {
107 public override bool IsEnvironmentProperty {
108 get { return property_type == PropertyType.Environment; }
110 public override bool IsGlobalProperty {
111 get { return property_type == PropertyType.Global; }
113 public override bool IsImported {
114 get { return false; }
116 public override bool IsReservedProperty {
117 get { return property_type == PropertyType.Reserved; }
119 readonly ProjectProperty predecessor;
120 public override ProjectProperty Predecessor {
121 get { return predecessor; }
125 internal abstract class ImmutableProjectProperty : BaseProjectProperty
127 public ImmutableProjectProperty (Project project, PropertyType propertyType, string name)
128 : base (project, propertyType, name)
132 internal override string InternalEvaluatedValue {
133 get { return UnevaluatedValue; }
137 internal abstract class MutableProjectProperty : BaseProjectProperty
139 public MutableProjectProperty (Project project, PropertyType propertyType, string name)
140 : base (project, propertyType, name)
144 string evaluated_value; // see UpdateEvaluatedValue().
145 internal void UpdateEvaluatedValue ()
147 evaluated_value = Project.ExpandString (UnevaluatedValue);
150 internal override string InternalEvaluatedValue {
151 get { return evaluated_value; }
155 internal class XmlProjectProperty : MutableProjectProperty
157 public XmlProjectProperty (Project project, ProjectPropertyElement xml, PropertyType propertyType, bool isImported)
158 : base (project, propertyType, xml.Name)
161 this.is_imported = isImported;
162 UpdateEvaluatedValue ();
165 readonly ProjectPropertyElement xml;
166 readonly bool is_imported;
168 public override bool IsImported {
169 get { return is_imported; }
172 public override string UnevaluatedValue {
173 get { return xml.Value; }
174 set { xml.Value = value; }
177 public override ProjectPropertyElement Xml {
182 internal class EnvironmentProjectProperty : ImmutableProjectProperty
184 static string extensions_path;
185 internal static string DefaultExtensionsPath {
187 if (extensions_path == null) {
188 // NOTE: code from mcs/tools/gacutil/driver.cs
189 PropertyInfo gac = typeof (System.Environment).GetProperty (
190 "GacPath", BindingFlags.Static | BindingFlags.NonPublic);
193 MethodInfo get_gac = gac.GetGetMethod (true);
194 string gac_path = (string) get_gac.Invoke (null, null);
195 extensions_path = Path.GetFullPath (Path.Combine (
196 gac_path, Path.Combine ("..", "xbuild")));
199 return extensions_path;
203 public EnvironmentProjectProperty (Project project, string name, string value, bool wellknown = false)
204 : base (project, PropertyType.Environment, name)
207 this.wellknown = wellknown;
210 readonly string value;
211 readonly bool wellknown;
213 internal override bool IsWellKnownProperty {
214 get { return wellknown; }
217 // It can override possible another environment vairable property BUT never gives Predecessor.
218 public override ProjectProperty Predecessor {
222 public override string UnevaluatedValue {
223 get { return value; }
224 set { throw new InvalidOperationException (string.Format ("You cannot change value of environment property '{0}'.", Name)); }
226 public override ProjectPropertyElement Xml {
231 internal class GlobalProjectProperty : ImmutableProjectProperty
233 public GlobalProjectProperty (Project project, string name, string value)
234 : base (project, PropertyType.Global, name)
239 readonly string value;
241 public override string UnevaluatedValue {
242 get { return value; }
243 set { throw new InvalidOperationException (string.Format ("You cannot change value of global property '{0}'.", Name)); }
245 public override ProjectPropertyElement Xml {
250 internal class ManuallyAddedProjectProperty : MutableProjectProperty
252 public ManuallyAddedProjectProperty (Project project, string name, string value)
253 : base (project, PropertyType.Normal, name)
255 this.UnevaluatedValue = value;
258 public override string UnevaluatedValue { get; set; }
260 public override ProjectPropertyElement Xml {
265 internal class ReservedProjectProperty : ImmutableProjectProperty
267 public ReservedProjectProperty (Project project, string name, Func<string> value)
268 : base (project, PropertyType.Reserved, name)
273 // make sure it does not give access to any possible attempted overrrides.
274 public override ProjectProperty Predecessor {
278 readonly Func<string> value;
279 public override string UnevaluatedValue {
280 get { return value (); }
281 set { throw new InvalidOperationException (string.Format ("You cannot change value of reserved property '{0}'.", Name)); }
284 public override ProjectPropertyElement Xml {