5 // Leszek Ciesielski (skolima@gmail.com)
6 // Rolf Bjarne Kvinge (rolf@xamarin.com)
8 // (C) 2011 Leszek Ciesielski
9 // Copyright (C) 2011 Xamarin Inc. (http://www.xamarin.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Collections.Generic;
33 using System.Diagnostics;
38 using Microsoft.Build.Construction;
39 using Microsoft.Build.Internal;
40 using Microsoft.Build.Execution;
41 using Microsoft.Build.Framework;
42 using Microsoft.Build.Logging;
43 using System.Collections;
45 namespace Microsoft.Build.Evaluation
47 [DebuggerDisplay ("{FullPath} EffectiveToolsVersion={ToolsVersion} #GlobalProperties="
48 + "{data.globalProperties.Count} #Properties={data.Properties.Count} #ItemTypes="
49 + "{data.ItemTypes.Count} #ItemDefinitions={data.ItemDefinitions.Count} #Items="
50 + "{data.Items.Count} #Targets={data.Targets.Count}")]
53 public Project (XmlReader xml)
54 : this (ProjectRootElement.Create (xml))
58 public Project (XmlReader xml, IDictionary<string, string> globalProperties,
60 : this (ProjectRootElement.Create (xml), globalProperties, toolsVersion)
64 public Project (XmlReader xml, IDictionary<string, string> globalProperties,
65 string toolsVersion, ProjectCollection projectCollection)
66 : this (ProjectRootElement.Create (xml), globalProperties, toolsVersion, projectCollection)
70 public Project (XmlReader xml, IDictionary<string, string> globalProperties,
71 string toolsVersion, ProjectCollection projectCollection,
72 ProjectLoadSettings loadSettings)
73 : this (ProjectRootElement.Create (xml), globalProperties, toolsVersion, projectCollection, loadSettings)
77 public Project (ProjectRootElement xml) : this (xml, null, null)
81 public Project (ProjectRootElement xml, IDictionary<string, string> globalProperties,
83 : this (xml, globalProperties, toolsVersion, ProjectCollection.GlobalProjectCollection)
87 public Project (ProjectRootElement xml, IDictionary<string, string> globalProperties,
88 string toolsVersion, ProjectCollection projectCollection)
89 : this (xml, globalProperties, toolsVersion, projectCollection, ProjectLoadSettings.Default)
93 public Project (ProjectRootElement xml, IDictionary<string, string> globalProperties,
94 string toolsVersion, ProjectCollection projectCollection,
95 ProjectLoadSettings loadSettings)
97 if (projectCollection == null)
98 throw new ArgumentNullException ("projectCollection");
100 this.GlobalProperties = globalProperties ?? new Dictionary<string, string> ();
101 this.ToolsVersion = toolsVersion;
102 this.ProjectCollection = projectCollection;
103 this.load_settings = loadSettings;
108 public Project (string projectFile)
109 : this (projectFile, null, null)
113 public Project (string projectFile, IDictionary<string, string> globalProperties,
115 : this (projectFile, globalProperties, toolsVersion, ProjectCollection.GlobalProjectCollection, ProjectLoadSettings.Default)
119 public Project (string projectFile, IDictionary<string, string> globalProperties,
120 string toolsVersion, ProjectCollection projectCollection)
121 : this (projectFile, globalProperties, toolsVersion, projectCollection, ProjectLoadSettings.Default)
125 public Project (string projectFile, IDictionary<string, string> globalProperties,
126 string toolsVersion, ProjectCollection projectCollection,
127 ProjectLoadSettings loadSettings)
128 : this (ProjectRootElement.Create (projectFile), globalProperties, toolsVersion, projectCollection, loadSettings)
132 ProjectLoadSettings load_settings;
134 public IDictionary<string, string> GlobalProperties { get; private set; }
136 public ProjectCollection ProjectCollection { get; private set; }
138 public string ToolsVersion { get; private set; }
140 public ProjectRootElement Xml { get; private set; }
143 Dictionary<string, ProjectItemDefinition> item_definitions;
144 List<ResolvedImport> raw_imports;
145 List<ProjectItem> raw_items;
146 List<string> item_types;
147 List<ProjectProperty> properties;
148 Dictionary<string, ProjectTargetInstance> targets;
152 dir_path = Directory.GetCurrentDirectory ();
153 raw_imports = new List<ResolvedImport> ();
154 item_definitions = new Dictionary<string, ProjectItemDefinition> ();
155 item_types = new List<string> ();
156 properties = new List<ProjectProperty> ();
157 targets = new Dictionary<string, ProjectTargetInstance> ();
164 foreach (DictionaryEntry p in Environment.GetEnvironmentVariables ())
165 this.properties.Add (new EnvironmentProjectProperty (this, (string)p.Key, (string)p.Value));
166 foreach (var p in GlobalProperties)
167 this.properties.Add (new GlobalProjectProperty (this, p.Key, p.Value));
168 foreach (var child in Xml.Children) {
169 if (child is ProjectPropertyGroupElement)
170 foreach (var p in ((ProjectPropertyGroupElement) child).Properties)
171 this.properties.Add (new XmlProjectProperty (this, p, PropertyType.Normal));
172 else if (child is ProjectItemGroupElement)
173 foreach (var p in ((ProjectItemGroupElement) child).Items)
174 this.raw_items.Add (new ProjectItem (p));
175 else if (child is ProjectItemDefinitionGroupElement)
176 foreach (var p in ((ProjectItemDefinitionGroupElement) child).ItemDefinitions) {
177 ProjectItemDefinition existing;
178 if (!item_definitions.TryGetValue (p.ItemType, out existing))
179 item_definitions.Add (p.ItemType, (existing = new ProjectItemDefinition (this, p.ItemType)));
180 existing.AddItems (p);
185 public ICollection<ProjectItem> GetItemsIgnoringCondition (string itemType)
187 return new CollectionFromEnumerable<ProjectItem> (
188 new FilteredEnumerable<ProjectItemElement> (Xml.Items).
189 Where (p => p.ItemType.Equals (itemType, StringComparison.OrdinalIgnoreCase)).
190 Select (p => new ProjectItem (p)));
193 public void RemoveItems (IEnumerable<ProjectItem> items)
195 var removal = new List<ProjectItem> (items);
196 foreach (var item in removal) {
197 var parent = item.Xml.Parent;
198 parent.RemoveChild (item.Xml);
199 if (parent.Count == 0)
200 parent.Parent.RemoveChild (parent);
204 static readonly Dictionary<string, string> empty_metadata = new Dictionary<string, string> ();
206 public IList<ProjectItem> AddItem (string itemType, string unevaluatedInclude)
208 return AddItem (itemType, unevaluatedInclude, empty_metadata);
211 public IList<ProjectItem> AddItem (string itemType, string unevaluatedInclude,
212 IEnumerable<KeyValuePair<string, string>> metadata)
214 // FIXME: needs several check that AddItemFast() does not process (see MSDN for details).
216 return AddItemFast (itemType, unevaluatedInclude, metadata);
219 public IList<ProjectItem> AddItemFast (string itemType, string unevaluatedInclude)
221 return AddItemFast (itemType, unevaluatedInclude, empty_metadata);
224 public IList<ProjectItem> AddItemFast (string itemType, string unevaluatedInclude,
225 IEnumerable<KeyValuePair<string, string>> metadata)
227 throw new NotImplementedException ();
232 return Build (Xml.DefaultTargets.Split (';'));
235 public bool Build (IEnumerable<ILogger> loggers)
237 return Build (Xml.DefaultTargets.Split (';'), loggers);
240 public bool Build (string target)
242 return string.IsNullOrWhiteSpace (target) ? Build () : Build (new string [] {target});
245 public bool Build (string[] targets)
247 return Build (targets, new ILogger [0]);
250 public bool Build (ILogger logger)
252 return Build (Xml.DefaultTargets.Split (';'), new ILogger [] {logger});
255 public bool Build (string[] targets, IEnumerable<ILogger> loggers)
257 return Build (targets, loggers, new ForwardingLoggerRecord [0]);
260 public bool Build (IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> remoteLoggers)
262 return Build (Xml.DefaultTargets.Split (';'), loggers, remoteLoggers);
265 public bool Build (string target, IEnumerable<ILogger> loggers)
267 return Build (new string [] { target }, loggers);
270 public bool Build (string[] targets, IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> remoteLoggers)
272 // Unlike ProjectInstance.Build(), there is no place to fill outputs by targets, so ignore them
273 // (i.e. we don't use the overload with output).
275 // This does not check FullPath, so don't call GetProjectInstanceForBuild() directly.
276 return new BuildManager ().GetProjectInstanceForBuildInternal (this).Build (targets, loggers, remoteLoggers);
279 public bool Build (string target, IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> remoteLoggers)
281 return Build (new string [] { target }, loggers, remoteLoggers);
284 public ProjectInstance CreateProjectInstance ()
286 var ret = new ProjectInstance (Xml, GlobalProperties, ToolsVersion, ProjectCollection);
287 // FIXME: maybe fill other properties to the result.
291 public string ExpandString (string unexpandedValue)
293 throw new NotImplementedException ();
296 public static string GetEvaluatedItemIncludeEscaped (ProjectItem item)
298 throw new NotImplementedException ();
301 public static string GetEvaluatedItemIncludeEscaped (ProjectItemDefinition item)
303 throw new NotImplementedException ();
306 public ICollection<ProjectItem> GetItems (string itemType)
308 throw new NotImplementedException ();
311 public ICollection<ProjectItem> GetItemsByEvaluatedInclude (string evaluatedInclude)
313 throw new NotImplementedException ();
316 public IEnumerable<ProjectElement> GetLogicalProject ()
318 throw new NotImplementedException ();
321 public static string GetMetadataValueEscaped (ProjectMetadata metadatum)
323 throw new NotImplementedException ();
326 public static string GetMetadataValueEscaped (ProjectItem item, string name)
328 throw new NotImplementedException ();
331 public static string GetMetadataValueEscaped (ProjectItemDefinition item, string name)
333 throw new NotImplementedException ();
336 public string GetPropertyValue (string name)
338 var prop = GetProperty (name);
339 return prop != null ? prop.EvaluatedValue : string.Empty;
342 public static string GetPropertyValueEscaped (ProjectProperty property)
344 return property.EvaluatedValue;
347 public ProjectProperty GetProperty (string name)
349 return properties.FirstOrDefault (p => p.Name == name);
352 public void MarkDirty ()
354 throw new NotImplementedException ();
357 public void ReevaluateIfNecessary ()
359 throw new NotImplementedException ();
362 public bool RemoveGlobalProperty (string name)
364 throw new NotImplementedException ();
367 public bool RemoveItem (ProjectItem item)
369 throw new NotImplementedException ();
372 public bool RemoveProperty (ProjectProperty property)
374 var removed = properties.FirstOrDefault (p => p.Name == property.Name);
377 properties.Remove (removed);
386 public void Save (TextWriter writer)
391 public void Save (string path)
393 Save (path, Encoding.Default);
396 public void Save (Encoding encoding)
398 Save (FullPath, encoding);
401 public void Save (string path, Encoding encoding)
403 using (var writer = new StreamWriter (path, false, encoding))
407 public void SaveLogicalProject (TextWriter writer)
409 throw new NotImplementedException ();
412 public bool SetGlobalProperty (string name, string escapedValue)
414 throw new NotImplementedException ();
417 public ProjectProperty SetProperty (string name, string unevaluatedValue)
419 var p = new ManuallyAddedProjectProperty (this, name, unevaluatedValue);
424 public ICollection<ProjectMetadata> AllEvaluatedItemDefinitionMetadata { get; private set; }
426 public ICollection<ProjectItem> AllEvaluatedItems { get; private set; }
428 public ICollection<ProjectProperty> AllEvaluatedProperties { get; private set; }
430 public IDictionary<string, List<string>> ConditionedProperties {
432 // this property returns different instances every time.
433 var dic = new Dictionary<string, List<string>> ();
435 // but I dunno HOW this evaluates
437 throw new NotImplementedException ();
441 public string DirectoryPath {
442 get { return dir_path; }
445 public bool DisableMarkDirty { get; set; }
447 public int EvaluationCounter {
448 get { throw new NotImplementedException (); }
451 public string FullPath {
452 get { return Xml.FullPath; }
453 set { Xml.FullPath = value; }
456 public IList<ResolvedImport> Imports {
457 get { throw new NotImplementedException (); }
460 public IList<ResolvedImport> ImportsIncludingDuplicates {
461 get { return raw_imports; }
464 public bool IsBuildEnabled {
465 get { return ProjectCollection.IsBuildEnabled; }
468 public bool IsDirty {
469 get { throw new NotImplementedException (); }
472 public IDictionary<string, ProjectItemDefinition> ItemDefinitions {
473 get { return item_definitions; }
476 public ICollection<ProjectItem> Items {
477 get { throw new NotImplementedException (); }
480 public ICollection<ProjectItem> ItemsIgnoringCondition {
481 get { return raw_items; }
484 public ICollection<string> ItemTypes {
485 get { return item_types; }
488 public ICollection<ProjectProperty> Properties {
489 get { return properties; }
492 public bool SkipEvaluation { get; set; }
499 IDictionary<string, ProjectTargetInstance> Targets {
500 get { return targets; }