5 // Leszek Ciesielski (skolima@gmail.com)
6 // Rolf Bjarne Kvinge (rolf@xamarin.com)
7 // Atsushi Enomoto (atsushi@xamarin.com)
9 // (C) 2011 Leszek Ciesielski
10 // Copyright (C) 2011,2013 Xamarin Inc. (http://www.xamarin.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Collections.Generic;
34 using System.Diagnostics;
39 using Microsoft.Build.Construction;
40 using Microsoft.Build.Internal;
41 using Microsoft.Build.Execution;
42 using Microsoft.Build.Framework;
43 using Microsoft.Build.Logging;
44 using System.Collections;
46 namespace Microsoft.Build.Evaluation
48 [DebuggerDisplay ("{FullPath} EffectiveToolsVersion={ToolsVersion} #GlobalProperties="
49 + "{data.globalProperties.Count} #Properties={data.Properties.Count} #ItemTypes="
50 + "{data.ItemTypes.Count} #ItemDefinitions={data.ItemDefinitions.Count} #Items="
51 + "{data.Items.Count} #Targets={data.Targets.Count}")]
54 public Project (XmlReader xml)
55 : this (ProjectRootElement.Create (xml))
59 public Project (XmlReader xml, IDictionary<string, string> globalProperties,
61 : this (ProjectRootElement.Create (xml), globalProperties, toolsVersion)
65 public Project (XmlReader xml, IDictionary<string, string> globalProperties,
66 string toolsVersion, ProjectCollection projectCollection)
67 : this (ProjectRootElement.Create (xml), globalProperties, toolsVersion, projectCollection)
71 public Project (XmlReader xml, IDictionary<string, string> globalProperties,
72 string toolsVersion, ProjectCollection projectCollection,
73 ProjectLoadSettings loadSettings)
74 : this (ProjectRootElement.Create (xml), globalProperties, toolsVersion, projectCollection, loadSettings)
78 public Project (ProjectRootElement xml) : this (xml, null, null)
82 public Project (ProjectRootElement xml, IDictionary<string, string> globalProperties,
84 : this (xml, globalProperties, toolsVersion, ProjectCollection.GlobalProjectCollection)
88 public Project (ProjectRootElement xml, IDictionary<string, string> globalProperties,
89 string toolsVersion, ProjectCollection projectCollection)
90 : this (xml, globalProperties, toolsVersion, projectCollection, ProjectLoadSettings.Default)
94 public Project (ProjectRootElement xml, IDictionary<string, string> globalProperties,
95 string toolsVersion, ProjectCollection projectCollection,
96 ProjectLoadSettings loadSettings)
98 if (projectCollection == null)
99 throw new ArgumentNullException ("projectCollection");
101 this.GlobalProperties = globalProperties ?? new Dictionary<string, string> ();
102 this.ToolsVersion = toolsVersion;
103 this.ProjectCollection = projectCollection;
104 this.load_settings = loadSettings;
109 public Project (string projectFile)
110 : this (projectFile, null, null)
114 public Project (string projectFile, IDictionary<string, string> globalProperties,
116 : this (projectFile, globalProperties, toolsVersion, ProjectCollection.GlobalProjectCollection, ProjectLoadSettings.Default)
120 public Project (string projectFile, IDictionary<string, string> globalProperties,
121 string toolsVersion, ProjectCollection projectCollection)
122 : this (projectFile, globalProperties, toolsVersion, projectCollection, ProjectLoadSettings.Default)
126 public Project (string projectFile, IDictionary<string, string> globalProperties,
127 string toolsVersion, ProjectCollection projectCollection,
128 ProjectLoadSettings loadSettings)
129 : this (ProjectRootElement.Create (projectFile), globalProperties, toolsVersion, projectCollection, loadSettings)
133 ProjectLoadSettings load_settings;
135 public IDictionary<string, string> GlobalProperties { get; private set; }
137 public ProjectCollection ProjectCollection { get; private set; }
139 public string ToolsVersion { get; private set; }
141 public ProjectRootElement Xml { get; private set; }
144 Dictionary<string, ProjectItemDefinition> item_definitions;
145 List<ResolvedImport> raw_imports;
146 List<ProjectItem> raw_items;
147 List<string> item_types;
148 List<ProjectProperty> properties;
149 Dictionary<string, ProjectTargetInstance> targets;
153 dir_path = Directory.GetCurrentDirectory ();
154 raw_imports = new List<ResolvedImport> ();
155 item_definitions = new Dictionary<string, ProjectItemDefinition> ();
156 item_types = new List<string> ();
157 properties = new List<ProjectProperty> ();
158 targets = new Dictionary<string, ProjectTargetInstance> ();
159 raw_items = new List<ProjectItem> ();
166 foreach (DictionaryEntry p in Environment.GetEnvironmentVariables ())
167 this.properties.Add (new EnvironmentProjectProperty (this, (string)p.Key, (string)p.Value));
168 foreach (var p in GlobalProperties)
169 this.properties.Add (new GlobalProjectProperty (this, p.Key, p.Value));
170 foreach (var child in Xml.Children) {
171 if (child is ProjectPropertyGroupElement)
172 foreach (var p in ((ProjectPropertyGroupElement) child).Properties)
173 this.properties.Add (new XmlProjectProperty (this, p, PropertyType.Normal));
174 else if (child is ProjectItemGroupElement)
175 foreach (var p in ((ProjectItemGroupElement) child).Items)
176 this.raw_items.Add (new ProjectItem (this, p));
177 else if (child is ProjectItemDefinitionGroupElement)
178 foreach (var p in ((ProjectItemDefinitionGroupElement) child).ItemDefinitions) {
179 ProjectItemDefinition existing;
180 if (!item_definitions.TryGetValue (p.ItemType, out existing))
181 item_definitions.Add (p.ItemType, (existing = new ProjectItemDefinition (this, p.ItemType)));
182 existing.AddItems (p);
187 public ICollection<ProjectItem> GetItemsIgnoringCondition (string itemType)
189 return new CollectionFromEnumerable<ProjectItem> (raw_items.Where (p => p.ItemType.Equals (itemType, StringComparison.OrdinalIgnoreCase)));
192 public void RemoveItems (IEnumerable<ProjectItem> items)
194 var removal = new List<ProjectItem> (items);
195 foreach (var item in removal) {
196 var parent = item.Xml.Parent;
197 parent.RemoveChild (item.Xml);
198 if (parent.Count == 0)
199 parent.Parent.RemoveChild (parent);
203 static readonly Dictionary<string, string> empty_metadata = new Dictionary<string, string> ();
205 public IList<ProjectItem> AddItem (string itemType, string unevaluatedInclude)
207 return AddItem (itemType, unevaluatedInclude, empty_metadata);
210 public IList<ProjectItem> AddItem (string itemType, string unevaluatedInclude,
211 IEnumerable<KeyValuePair<string, string>> metadata)
213 // FIXME: needs several check that AddItemFast() does not process (see MSDN for details).
215 return AddItemFast (itemType, unevaluatedInclude, metadata);
218 public IList<ProjectItem> AddItemFast (string itemType, string unevaluatedInclude)
220 return AddItemFast (itemType, unevaluatedInclude, empty_metadata);
223 public IList<ProjectItem> AddItemFast (string itemType, string unevaluatedInclude,
224 IEnumerable<KeyValuePair<string, string>> metadata)
226 throw new NotImplementedException ();
231 return Build (Xml.DefaultTargets.Split (';'));
234 public bool Build (IEnumerable<ILogger> loggers)
236 return Build (Xml.DefaultTargets.Split (';'), loggers);
239 public bool Build (string target)
241 return string.IsNullOrWhiteSpace (target) ? Build () : Build (new string [] {target});
244 public bool Build (string[] targets)
246 return Build (targets, new ILogger [0]);
249 public bool Build (ILogger logger)
251 return Build (Xml.DefaultTargets.Split (';'), new ILogger [] {logger});
254 public bool Build (string[] targets, IEnumerable<ILogger> loggers)
256 return Build (targets, loggers, new ForwardingLoggerRecord [0]);
259 public bool Build (IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> remoteLoggers)
261 return Build (Xml.DefaultTargets.Split (';'), loggers, remoteLoggers);
264 public bool Build (string target, IEnumerable<ILogger> loggers)
266 return Build (new string [] { target }, loggers);
269 public bool Build (string[] targets, IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> remoteLoggers)
271 // Unlike ProjectInstance.Build(), there is no place to fill outputs by targets, so ignore them
272 // (i.e. we don't use the overload with output).
274 // This does not check FullPath, so don't call GetProjectInstanceForBuild() directly.
275 return new BuildManager ().GetProjectInstanceForBuildInternal (this).Build (targets, loggers, remoteLoggers);
278 public bool Build (string target, IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> remoteLoggers)
280 return Build (new string [] { target }, loggers, remoteLoggers);
283 public ProjectInstance CreateProjectInstance ()
285 var ret = new ProjectInstance (Xml, GlobalProperties, ToolsVersion, ProjectCollection);
286 // FIXME: maybe fill other properties to the result.
290 public string ExpandString (string unexpandedValue)
292 throw new NotImplementedException ();
295 public static string GetEvaluatedItemIncludeEscaped (ProjectItem item)
297 throw new NotImplementedException ();
300 public static string GetEvaluatedItemIncludeEscaped (ProjectItemDefinition item)
302 throw new NotImplementedException ();
305 public ICollection<ProjectItem> GetItems (string itemType)
307 throw new NotImplementedException ();
310 public ICollection<ProjectItem> GetItemsByEvaluatedInclude (string evaluatedInclude)
312 throw new NotImplementedException ();
315 public IEnumerable<ProjectElement> GetLogicalProject ()
317 throw new NotImplementedException ();
320 public static string GetMetadataValueEscaped (ProjectMetadata metadatum)
322 throw new NotImplementedException ();
325 public static string GetMetadataValueEscaped (ProjectItem item, string name)
327 throw new NotImplementedException ();
330 public static string GetMetadataValueEscaped (ProjectItemDefinition item, string name)
332 throw new NotImplementedException ();
335 public string GetPropertyValue (string name)
337 var prop = GetProperty (name);
338 return prop != null ? prop.EvaluatedValue : string.Empty;
341 public static string GetPropertyValueEscaped (ProjectProperty property)
343 return property.EvaluatedValue;
346 public ProjectProperty GetProperty (string name)
348 return properties.FirstOrDefault (p => p.Name == name);
351 public void MarkDirty ()
353 throw new NotImplementedException ();
356 public void ReevaluateIfNecessary ()
358 throw new NotImplementedException ();
361 public bool RemoveGlobalProperty (string name)
363 throw new NotImplementedException ();
366 public bool RemoveItem (ProjectItem item)
368 throw new NotImplementedException ();
371 public bool RemoveProperty (ProjectProperty property)
373 var removed = properties.FirstOrDefault (p => p.Name == property.Name);
376 properties.Remove (removed);
385 public void Save (TextWriter writer)
390 public void Save (string path)
392 Save (path, Encoding.Default);
395 public void Save (Encoding encoding)
397 Save (FullPath, encoding);
400 public void Save (string path, Encoding encoding)
402 using (var writer = new StreamWriter (path, false, encoding))
406 public void SaveLogicalProject (TextWriter writer)
408 throw new NotImplementedException ();
411 public bool SetGlobalProperty (string name, string escapedValue)
413 throw new NotImplementedException ();
416 public ProjectProperty SetProperty (string name, string unevaluatedValue)
418 var p = new ManuallyAddedProjectProperty (this, name, unevaluatedValue);
423 public ICollection<ProjectMetadata> AllEvaluatedItemDefinitionMetadata { get; private set; }
425 public ICollection<ProjectItem> AllEvaluatedItems { get; private set; }
427 public ICollection<ProjectProperty> AllEvaluatedProperties { get; private set; }
429 public IDictionary<string, List<string>> ConditionedProperties {
431 // this property returns different instances every time.
432 var dic = new Dictionary<string, List<string>> ();
434 // but I dunno HOW this evaluates
436 throw new NotImplementedException ();
440 public string DirectoryPath {
441 get { return dir_path; }
444 public bool DisableMarkDirty { get; set; }
446 public int EvaluationCounter {
447 get { throw new NotImplementedException (); }
450 public string FullPath {
451 get { return Xml.FullPath; }
452 set { Xml.FullPath = value; }
455 public IList<ResolvedImport> Imports {
456 get { throw new NotImplementedException (); }
459 public IList<ResolvedImport> ImportsIncludingDuplicates {
460 get { return raw_imports; }
463 public bool IsBuildEnabled {
464 get { return ProjectCollection.IsBuildEnabled; }
467 public bool IsDirty {
468 get { throw new NotImplementedException (); }
471 public IDictionary<string, ProjectItemDefinition> ItemDefinitions {
472 get { return item_definitions; }
475 public ICollection<ProjectItem> Items {
476 get { throw new NotImplementedException (); }
479 public ICollection<ProjectItem> ItemsIgnoringCondition {
480 get { return raw_items; }
483 public ICollection<string> ItemTypes {
484 get { return item_types; }
487 public ICollection<ProjectProperty> Properties {
488 get { return properties; }
491 public bool SkipEvaluation { get; set; }
498 IDictionary<string, ProjectTargetInstance> Targets {
499 get { return targets; }