Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProject.cs')
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProject.cs898
1 files changed, 247 insertions, 651 deletions
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProject.cs
index 2976287a16..4674d3f027 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProject.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProject.cs
@@ -26,33 +26,39 @@
//
using System;
-using System.Linq;
using System.IO;
using System.Collections.Generic;
using System.Xml;
using System.Text;
+using MonoDevelop.Core;
using MonoDevelop.Projects.Utility;
-using MonoDevelop.Projects.Text;
using Microsoft.Build.BuildEngine;
+using MSProject = Microsoft.Build.BuildEngine.Project;
+using System.Linq;
+using MonoDevelop.Projects.Text;
+using System.Threading.Tasks;
namespace MonoDevelop.Projects.Formats.MSBuild
{
public class MSBuildProject
{
XmlDocument doc;
- string file;
+ FilePath file;
Dictionary<XmlElement,MSBuildObject> elemCache = new Dictionary<XmlElement,MSBuildObject> ();
Dictionary<string, MSBuildItemGroup> bestGroups;
-
+ List<MSBuildItemEvaluated> evaluatedItems = new List<MSBuildItemEvaluated> ();
+ List<MSBuildItemEvaluated> evaluatedItemsIgnoringCondition;
+ MSBuildEvaluatedPropertyCollection evaluatedProperties;
+
public const string Schema = "http://schemas.microsoft.com/developer/msbuild/2003";
static XmlNamespaceManager manager;
bool endsWithEmptyLine;
string newLine = Environment.NewLine;
ByteOrderMark bom;
-
- internal static XmlNamespaceManager XmlNamespaceManager {
+
+ public static XmlNamespaceManager XmlNamespaceManager {
get {
if (manager == null) {
manager = new XmlNamespaceManager (new NameTable ());
@@ -62,9 +68,21 @@ namespace MonoDevelop.Projects.Formats.MSBuild
}
}
- public string FileName {
+ public FilePath FileName {
get { return file; }
+ set { file = value; }
+ }
+
+ public FilePath BaseDirectory {
+ get { return file.ParentDirectory; }
}
+
+ public MSBuildFileFormat Format {
+ get;
+ set;
+ }
+
+ public bool IsNewProject { get; private set; }
public XmlDocument Document {
get { return doc; }
@@ -72,14 +90,27 @@ namespace MonoDevelop.Projects.Formats.MSBuild
public MSBuildProject ()
{
+ evaluatedProperties = new MSBuildEvaluatedPropertyCollection (this);
+ evaluatedItemsIgnoringCondition = new List<MSBuildItemEvaluated> ();
doc = new XmlDocument ();
doc.PreserveWhitespace = false;
doc.AppendChild (doc.CreateElement (null, "Project", Schema));
+ IsNewProject = true;
+ }
+
+ public static Task<MSBuildProject> LoadAsync (string file)
+ {
+ return Task<MSBuildProject>.Factory.StartNew (delegate {
+ var p = new MSBuildProject ();
+ p.Load (file);
+ return p;
+ });
}
public void Load (string file)
{
this.file = file;
+ IsNewProject = false;
using (FileStream fs = File.OpenRead (file)) {
byte[] buf = new byte [1024];
int nread, i;
@@ -172,18 +203,87 @@ namespace MonoDevelop.Projects.Formats.MSBuild
return content;
}
+ void WriteDataObjects ()
+ {
+ foreach (var ob in elemCache.Values) {
+ if (ob is MSBuildPropertyGroup)
+ ((MSBuildPropertyGroup)ob).WriteDataObjects ();
+ else if (ob is MSBuildItem)
+ ((MSBuildItem)ob).WriteDataObjects ();
+ }
+ }
+
public void Evaluate ()
{
- Evaluate (new MSBuildEvaluationContext ());
+ try {
+ Engine e = new Engine ();
+ MSProject project = new MSProject (e);
+ project.Load (FileName);
+ SyncBuildProject (project);
+ } catch (Exception ex) {
+ // If the project can't be evaluated don't crash
+ LoggingService.LogError ("MSBuild project could not be evaluated", ex);
+ }
}
- public void Evaluate (MSBuildEvaluationContext context)
+ void SyncBuildProject (MSProject project)
{
- context.InitEvaluation (this);
- foreach (var pg in PropertyGroups)
- pg.Evaluate (context);
- foreach (var pg in ItemGroups)
- pg.Evaluate (context);
+ var xmlGroups = PropertyGroups.ToArray ();
+ var buildGroups = project.PropertyGroups.Cast<BuildPropertyGroup> ().ToArray ();
+ for (int n=0; n<xmlGroups.Length && n<buildGroups.Length; n++)
+ SyncBuildPropertyGroup (xmlGroups [n], buildGroups [n]);
+
+ var xmlItems = ItemGroups.ToArray ();
+ var buildItems = project.ItemGroups.Cast<BuildItemGroup> ().Where (g => !g.IsImported).ToArray ();
+ for (int n=0; n<xmlItems.Length && n<buildItems.Length; n++)
+ SyncBuildItemGroup (xmlItems [n], buildItems [n]);
+
+ var xmlImports = Imports.ToArray ();
+ var buildImports = project.Imports.Cast<Import> ().ToArray ();
+ for (int n = 0; n < xmlImports.Length && n < buildImports.Length; n++)
+ xmlImports [n].SetEvalResult (buildImports [n].EvaluatedProjectPath);
+
+ foreach (BuildItem it in project.EvaluatedItems) {
+ var xit = new MSBuildItemEvaluated (this, it.Name, it.Include, it.FinalItemSpec);
+ xit.IsImported = it.IsImported;
+ ((MSBuildPropertyGroupEvaluated)xit.Metadata).Sync (it);
+ evaluatedItems.Add (xit);
+ }
+
+ foreach (BuildItem it in project.EvaluatedItemsIgnoringCondition) {
+ var xit = new MSBuildItemEvaluated (this, it.Name, it.Include, it.FinalItemSpec);
+ xit.IsImported = it.IsImported;
+ ((MSBuildPropertyGroupEvaluated)xit.Metadata).Sync (it);
+ evaluatedItemsIgnoringCondition.Add (xit);
+ }
+
+ evaluatedProperties.Sync (project.EvaluatedProperties);
+ }
+
+ void SyncBuildPropertyGroup (MSBuildPropertyGroup xmlGroup, BuildPropertyGroup buildGroup)
+ {
+ var xmlProps = xmlGroup.Properties.ToArray ();
+ var buildProps = buildGroup.Cast<BuildProperty> ().ToArray ();
+ for (int n = 0; n < xmlProps.Length && n < buildProps.Length; n++)
+ SyncBuildProperty (xmlProps [n], buildProps [n]);
+ }
+
+ void SyncBuildProperty (MSBuildProperty xmlProp, BuildProperty buildProp)
+ {
+ }
+
+ void SyncBuildItemGroup (MSBuildItemGroup xmlGroup, BuildItemGroup buildGroup)
+ {
+ var xmlItems = xmlGroup.Items.ToArray ();
+ var buildItems = buildGroup.Cast<BuildItem> ().ToArray ();
+ for (int n = 0; n < xmlItems.Length && n < buildItems.Length; n++)
+ SyncBuildItem (xmlItems [n], buildItems [n]);
+ }
+
+ void SyncBuildItem (MSBuildItem xmlItem, BuildItem buildItem)
+ {
+ xmlItem.SetEvalResult (buildItem.FinalItemSpec);
+ ((MSBuildPropertyGroupEvaluated)xmlItem.EvaluatedMetadata).Sync (buildItem);
}
public string DefaultTargets {
@@ -200,11 +300,43 @@ namespace MonoDevelop.Projects.Formats.MSBuild
doc.DocumentElement.RemoveAttribute ("ToolsVersion");
}
}
+
+ public string[] ProjectTypeGuids {
+ get { return GetGlobalPropertyGroup ().GetValue ("ProjectTypeGuids", "").Split (new []{';'}, StringSplitOptions.RemoveEmptyEntries).Select (t => t.Trim()).ToArray (); }
+ set { GetGlobalPropertyGroup ().SetValue ("ProjectTypeGuids", string.Join (";", value), preserveExistingCase:true); }
+ }
+
+ public bool AddProjectTypeGuid (string guid)
+ {
+ var guids = GetGlobalPropertyGroup ().GetValue ("ProjectTypeGuids", "").Trim ();
+ if (guids.IndexOf (guid, StringComparison.OrdinalIgnoreCase) == -1) {
+ if (!string.IsNullOrEmpty (guids))
+ guids += ";" + guid;
+ else
+ guids = guid;
+ GetGlobalPropertyGroup ().SetValue ("ProjectTypeGuids", guids, preserveExistingCase: true);
+ return true;
+ }
+ return false;
+ }
- public MSBuildImport AddNewImport (string name, MSBuildImport beforeImport = null)
+ public bool RemoveProjectTypeGuid (string guid)
+ {
+ var guids = ProjectTypeGuids;
+ var newGuids = guids.Where (g => !g.Equals (guid, StringComparison.OrdinalIgnoreCase)).ToArray ();
+ if (newGuids.Length != guids.Length) {
+ ProjectTypeGuids = newGuids;
+ return true;
+ } else
+ return false;
+ }
+
+ public MSBuildImport AddNewImport (string name, string condition = null, MSBuildImport beforeImport = null)
{
XmlElement elem = doc.CreateElement (null, "Import", MSBuildProject.Schema);
elem.SetAttribute ("Project", name);
+ if (condition != null)
+ elem.SetAttribute ("Condition", condition);
if (beforeImport != null) {
doc.DocumentElement.InsertBefore (elem, beforeImport.Element);
@@ -215,7 +347,12 @@ namespace MonoDevelop.Projects.Formats.MSBuild
else
doc.DocumentElement.AppendChild (elem);
}
- return new MSBuildImport (elem);
+ return GetImport (elem);
+ }
+
+ public MSBuildImport GetImport (string name, string condition = null)
+ {
+ return Imports.FirstOrDefault (i => i.Project == name && i.Condition == condition);
}
public void RemoveImport (string name)
@@ -228,21 +365,37 @@ namespace MonoDevelop.Projects.Formats.MSBuild
Console.WriteLine ("ppnf:");
}
+ public void RemoveImport (MSBuildImport import)
+ {
+ import.Element.ParentNode.RemoveChild (import.Element);
+ }
+
public IEnumerable<MSBuildImport> Imports {
get {
foreach (XmlElement elem in doc.DocumentElement.SelectNodes ("tns:Import", XmlNamespaceManager))
- yield return new MSBuildImport (elem);
+ yield return GetImport (elem);
}
}
-
- public MSBuildPropertySet GetGlobalPropertyGroup ()
+
+ public IMSBuildEvaluatedPropertyCollection EvaluatedProperties {
+ get { return evaluatedProperties; }
+ }
+
+ public IEnumerable<IMSBuildItemEvaluated> EvaluatedItems {
+ get { return evaluatedItems; }
+ }
+
+ public IEnumerable<IMSBuildItemEvaluated> EvaluatedItemsIgnoringCondition {
+ get { return evaluatedItemsIgnoringCondition; }
+ }
+
+ public IMSBuildPropertySet GetGlobalPropertyGroup ()
{
- MSBuildPropertyGroupMerged res = new MSBuildPropertyGroupMerged ();
foreach (MSBuildPropertyGroup grp in PropertyGroups) {
if (grp.Condition.Length == 0)
- res.Add (grp);
+ return grp;
}
- return res.GroupCount > 0 ? res : null;
+ return null;
}
public MSBuildPropertyGroup AddNewPropertyGroup (bool insertAtEnd)
@@ -336,31 +489,67 @@ namespace MonoDevelop.Projects.Formats.MSBuild
return group;
}
- public string GetProjectExtensions (string section)
+ public XmlElement GetProjectExtension (string section)
{
- XmlElement elem = doc.DocumentElement.SelectSingleNode ("tns:ProjectExtensions/tns:" + section, XmlNamespaceManager) as XmlElement;
- if (elem != null)
- return elem.InnerXml;
- else
- return string.Empty;
+ return doc.DocumentElement.SelectSingleNode ("tns:ProjectExtensions/tns:" + section, XmlNamespaceManager) as XmlElement;
}
- public void SetProjectExtensions (string section, string value)
+ public XmlElement GetMonoDevelopProjectExtension (string section)
{
+ return doc.DocumentElement.SelectSingleNode ("tns:ProjectExtensions/tns:MonoDevelop/tns:Properties/tns:" + section, XmlNamespaceManager) as XmlElement;
+ }
+
+ public void SetProjectExtension (string section, XmlElement value)
+ {
+ if (value.OwnerDocument != doc)
+ value = (XmlElement)doc.ImportNode (value, true);
+
+ XmlElement elem = doc.DocumentElement ["ProjectExtensions", MSBuildProject.Schema];
+ if (elem == null) {
+ elem = doc.CreateElement (null, "ProjectExtensions", MSBuildProject.Schema);
+ doc.DocumentElement.AppendChild (elem);
+ }
+ XmlElement sec = elem [section];
+ if (sec == null)
+ elem.AppendChild (value);
+ else {
+ elem.InsertAfter (value, sec);
+ elem.RemoveChild (sec);
+ }
+ }
+
+ public void SetMonoDevelopProjectExtension (string section, XmlElement value)
+ {
+ if (value.OwnerDocument != doc)
+ value = (XmlElement)doc.ImportNode (value, true);
+
XmlElement elem = doc.DocumentElement ["ProjectExtensions", MSBuildProject.Schema];
if (elem == null) {
elem = doc.CreateElement (null, "ProjectExtensions", MSBuildProject.Schema);
doc.DocumentElement.AppendChild (elem);
}
+ var parent = elem;
+ elem = parent ["MonoDevelop", MSBuildProject.Schema];
+ if (elem == null) {
+ elem = doc.CreateElement (null, "MonoDevelop", MSBuildProject.Schema);
+ parent.AppendChild (elem);
+ }
+ parent = elem;
+ elem = parent ["Properties", MSBuildProject.Schema];
+ if (elem == null) {
+ elem = doc.CreateElement (null, "Properties", MSBuildProject.Schema);
+ parent.AppendChild (elem);
+ }
XmlElement sec = elem [section];
- if (sec == null) {
- sec = doc.CreateElement (null, section, MSBuildProject.Schema);
- elem.AppendChild (sec);
+ if (sec == null)
+ elem.AppendChild (value);
+ else {
+ elem.InsertAfter (value, sec);
+ elem.RemoveChild (sec);
}
- sec.InnerXml = value;
}
- public void RemoveProjectExtensions (string section)
+ public void RemoveProjectExtension (string section)
{
XmlElement elem = doc.DocumentElement.SelectSingleNode ("tns:ProjectExtensions/tns:" + section, XmlNamespaceManager) as XmlElement;
if (elem != null) {
@@ -371,6 +560,19 @@ namespace MonoDevelop.Projects.Formats.MSBuild
}
}
+ public void RemoveMonoDevelopProjectExtension (string section)
+ {
+ XmlElement elem = doc.DocumentElement.SelectSingleNode ("tns:ProjectExtensions/tns:MonoDevelop/tns:Properties/tns:" + section, XmlNamespaceManager) as XmlElement;
+ if (elem != null) {
+ do {
+ XmlElement parent = (XmlElement) elem.ParentNode;
+ parent.RemoveChild (elem);
+ elem = parent;
+ }
+ while (!elem.HasChildNodes);
+ }
+ }
+
public void RemoveItem (MSBuildItem item)
{
elemCache.Remove (item.Element);
@@ -383,12 +585,22 @@ namespace MonoDevelop.Projects.Formats.MSBuild
}
}
+ internal MSBuildImport GetImport (XmlElement elem)
+ {
+ MSBuildObject ob;
+ if (elemCache.TryGetValue (elem, out ob))
+ return (MSBuildImport) ob;
+ MSBuildImport it = new MSBuildImport (elem);
+ elemCache [elem] = it;
+ return it;
+ }
+
internal MSBuildItem GetItem (XmlElement elem)
{
MSBuildObject ob;
if (elemCache.TryGetValue (elem, out ob))
return (MSBuildItem) ob;
- MSBuildItem it = new MSBuildItem (elem);
+ MSBuildItem it = new MSBuildItem (this, elem);
elemCache [elem] = it;
return it;
}
@@ -420,628 +632,12 @@ namespace MonoDevelop.Projects.Formats.MSBuild
}
}
- public class MSBuildObject
- {
- XmlElement elem;
- XmlElement evaluatedElem;
- public MSBuildObject (XmlElement elem)
- {
- this.elem = elem;
- }
-
- public XmlElement Element {
- get { return elem; }
- }
-
- public XmlElement EvaluatedElement {
- get { return evaluatedElem ?? elem; }
- protected set { evaluatedElem = value; }
- }
-
- public bool IsEvaluated {
- get { return evaluatedElem != null; }
- }
-
- protected XmlElement AddChildElement (string name)
- {
- XmlElement e = elem.OwnerDocument.CreateElement (null, name, MSBuildProject.Schema);
- elem.AppendChild (e);
- return e;
- }
-
- public string Label {
- get { return EvaluatedElement.GetAttribute ("Label"); }
- set { Element.SetAttribute ("Label", value); }
- }
-
- public string Condition {
- get {
- return Element.GetAttribute ("Condition");
- }
- set {
- if (string.IsNullOrEmpty (value))
- Element.RemoveAttribute ("Condition");
- else
- Element.SetAttribute ("Condition", value);
- }
- }
-
- internal virtual void Evaluate (MSBuildEvaluationContext context)
- {
- }
- }
-
- public class MSBuildImport: MSBuildObject
- {
- public MSBuildImport (XmlElement elem): base (elem)
- {
- }
-
- public string Project {
- get { return EvaluatedElement.GetAttribute ("Project"); }
- set { Element.SetAttribute ("Project", value); }
- }
-
- public string Condition {
- get { return EvaluatedElement.GetAttribute ("Condition"); }
- set { Element.SetAttribute ("Condition", value); }
- }
- }
- public class MSBuildProperty: MSBuildObject
- {
- public MSBuildProperty (XmlElement elem): base (elem)
- {
- }
-
- public string Name {
- get { return Element.Name; }
- }
-
- internal bool Overwritten { get; set; }
-
- public string GetValue (bool isXml = false)
- {
- if (isXml)
- return EvaluatedElement.InnerXml;
- return EvaluatedElement.InnerText;
- }
-
- public void SetValue (string value, bool isXml = false)
- {
- if (isXml)
- Element.InnerXml = value;
- else
- Element.InnerText = value;
- }
-
- internal override void Evaluate (MSBuildEvaluationContext context)
- {
- EvaluatedElement = null;
-
- if (!string.IsNullOrEmpty (Condition)) {
- string cond;
- if (!context.Evaluate (Condition, out cond)) {
- // The value could not be evaluated, so if there is an existing value, it is not valid anymore
- context.ClearPropertyValue (Name);
- return;
- }
- if (!ConditionParser.ParseAndEvaluate (cond, context))
- return;
- }
-
- XmlElement elem;
-
- if (context.Evaluate (Element, out elem)) {
- EvaluatedElement = elem;
- context.SetPropertyValue (Name, GetValue ());
- } else {
- // The value could not be evaluated, so if there is an existing value, it is not valid anymore
- context.ClearPropertyValue (Name);
- }
- }
- }
- public interface MSBuildPropertySet
- {
- MSBuildProperty GetProperty (string name);
- IEnumerable<MSBuildProperty> Properties { get; }
- MSBuildProperty SetPropertyValue (string name, string value, bool preserveExistingCase, bool isXml = false);
- string GetPropertyValue (string name, bool isXml = false);
- bool RemoveProperty (string name);
- void RemoveAllProperties ();
- void UnMerge (MSBuildPropertySet baseGrp, ISet<string> propertiesToExclude);
- }
- class MSBuildPropertyGroupMerged: MSBuildPropertySet
- {
- List<MSBuildPropertyGroup> groups = new List<MSBuildPropertyGroup> ();
-
- public void Add (MSBuildPropertyGroup g)
- {
- groups.Add (g);
- }
-
- public int GroupCount {
- get { return groups.Count; }
- }
-
- public MSBuildProperty GetProperty (string name)
- {
- // Find property in reverse order, since the last set
- // value is the good one
- for (int n=groups.Count - 1; n >= 0; n--) {
- var g = groups [n];
- MSBuildProperty p = g.GetProperty (name);
- if (p != null)
- return p;
- }
- return null;
- }
-
- public MSBuildProperty SetPropertyValue (string name, string value, bool preserveExistingCase, bool isXml = false)
- {
- MSBuildProperty p = GetProperty (name);
- if (p != null) {
- if (!preserveExistingCase || !string.Equals (value, p.GetValue (isXml), StringComparison.OrdinalIgnoreCase)) {
- p.SetValue (value, isXml);
- }
- return p;
- }
- return groups [0].SetPropertyValue (name, value, preserveExistingCase, isXml);
- }
-
- public string GetPropertyValue (string name, bool isXml = false)
- {
- MSBuildProperty prop = GetProperty (name);
- return prop != null ? prop.GetValue (isXml) : null;
- }
-
- public bool RemoveProperty (string name)
- {
- bool found = false;
- foreach (var g in groups) {
- if (g.RemoveProperty (name)) {
- Prune (g);
- found = true;
- }
- }
- return found;
- }
-
- public void RemoveAllProperties ()
- {
- foreach (var g in groups) {
- g.RemoveAllProperties ();
- Prune (g);
- }
- }
-
- public void UnMerge (MSBuildPropertySet baseGrp, ISet<string> propertiesToExclude)
- {
- foreach (var g in groups) {
- g.UnMerge (baseGrp, propertiesToExclude);
- }
- }
-
- public IEnumerable<MSBuildProperty> Properties {
- get {
- foreach (var g in groups) {
- foreach (var p in g.Properties)
- yield return p;
- }
- }
- }
-
- void Prune (MSBuildPropertyGroup g)
- {
- if (g != groups [0] && !g.Properties.Any()) {
- // Remove this group since it's now empty
- g.Parent.RemoveGroup (g);
- }
- }
- }
- public class MSBuildPropertyGroup: MSBuildObject, MSBuildPropertySet
- {
- Dictionary<string,MSBuildProperty> properties = new Dictionary<string,MSBuildProperty> ();
- List<MSBuildProperty> propertyList = new List<MSBuildProperty> ();
- MSBuildProject parent;
-
- public MSBuildPropertyGroup (MSBuildProject parent, XmlElement elem): base (elem)
- {
- this.parent = parent;
-
- foreach (var pelem in Element.ChildNodes.OfType<XmlElement> ()) {
- MSBuildProperty prevSameName;
- if (properties.TryGetValue (pelem.Name, out prevSameName))
- prevSameName.Overwritten = true;
-
- var prop = new MSBuildProperty (pelem);
- propertyList.Add (prop);
- properties [pelem.Name] = prop; // If a property is defined more than once, we only care about the last registered value
- }
- }
-
- public MSBuildProject Parent {
- get {
- return this.parent;
- }
- }
-
- public MSBuildProperty GetProperty (string name)
- {
- MSBuildProperty prop;
- properties.TryGetValue (name, out prop);
- return prop;
- }
-
- public IEnumerable<MSBuildProperty> Properties {
- get {
- return propertyList.Where (p => !p.Overwritten);
- }
- }
-
- public MSBuildProperty SetPropertyValue (string name, string value, bool preserveExistingCase, bool isXml = false)
- {
- MSBuildProperty prop = GetProperty (name);
- if (prop == null) {
- XmlElement pelem = AddChildElement (name);
- prop = new MSBuildProperty (pelem);
- properties [name] = prop;
- propertyList.Add (prop);
- prop.SetValue (value, isXml);
- } else if (!preserveExistingCase || !string.Equals (value, prop.GetValue (isXml), StringComparison.OrdinalIgnoreCase)) {
- prop.SetValue (value, isXml);
- }
- return prop;
- }
-
- public string GetPropertyValue (string name, bool isXml = false)
- {
- MSBuildProperty prop = GetProperty (name);
- if (prop == null)
- return null;
- else
- return prop.GetValue (isXml);
- }
-
- public bool RemoveProperty (string name)
- {
- MSBuildProperty prop = GetProperty (name);
- if (prop != null) {
- properties.Remove (name);
- propertyList.Remove (prop);
- Element.RemoveChild (prop.Element);
- return true;
- }
- return false;
- }
-
- public void RemoveAllProperties ()
- {
- List<XmlNode> toDelete = new List<XmlNode> ();
- foreach (XmlNode node in Element.ChildNodes) {
- if (node is XmlElement)
- toDelete.Add (node);
- }
- foreach (XmlNode node in toDelete)
- Element.RemoveChild (node);
- properties.Clear ();
- propertyList.Clear ();
- }
-
- public void UnMerge (MSBuildPropertySet baseGrp, ISet<string> propsToExclude)
- {
- foreach (MSBuildProperty prop in baseGrp.Properties) {
- if (propsToExclude != null && propsToExclude.Contains (prop.Name))
- continue;
- MSBuildProperty thisProp = GetProperty (prop.Name);
- if (thisProp != null && prop.GetValue (true).Equals (thisProp.GetValue (true), StringComparison.OrdinalIgnoreCase))
- RemoveProperty (prop.Name);
- }
- }
-
- internal override void Evaluate (MSBuildEvaluationContext context)
- {
- if (!string.IsNullOrEmpty (Condition)) {
- string cond;
- if (!context.Evaluate (Condition, out cond)) {
- // The condition could not be evaluated. Clear all properties that this group defines
- // since we don't know if they will have a value or not
- foreach (var prop in Properties)
- context.ClearPropertyValue (prop.Name);
- return;
- }
- if (!ConditionParser.ParseAndEvaluate (cond, context))
- return;
- }
-
- foreach (var prop in propertyList)
- prop.Evaluate (context);
- }
-
- public override string ToString()
- {
- string s = "[MSBuildPropertyGroup:";
- foreach (MSBuildProperty prop in Properties)
- s += " " + prop.Name + "=" + prop.GetValue (true);
- return s + "]";
- }
-
- }
- public class MSBuildItem: MSBuildObject
- {
- public MSBuildItem (XmlElement elem): base (elem)
- {
- }
-
- public string Include {
- get { return EvaluatedElement.GetAttribute ("Include"); }
- set { Element.SetAttribute ("Include", value); }
- }
-
- public string UnevaluatedInclude {
- get { return Element.GetAttribute ("Include"); }
- set { Element.SetAttribute ("Include", value); }
- }
-
- public string Name {
- get { return Element.Name; }
- }
-
- public bool HasMetadata (string name)
- {
- return EvaluatedElement [name, MSBuildProject.Schema] != null;
- }
-
- public void SetMetadata (string name, bool value)
- {
- SetMetadata (name, value ? "True" : "False");
- }
-
- public void SetMetadata (string name, string value, bool isXml = false)
- {
- // Don't overwrite the metadata value if the new value is the same as the old
- // This will keep the old metadata string, which can contain property references
- if (GetMetadata (name, isXml) == value)
- return;
-
- XmlElement elem = Element [name, MSBuildProject.Schema];
- if (elem == null) {
- elem = AddChildElement (name);
- Element.AppendChild (elem);
- }
- if (isXml)
- elem.InnerXml = value;
- else
- elem.InnerText = value;
- }
-
- public void UnsetMetadata (string name)
- {
- XmlElement elem = Element [name, MSBuildProject.Schema];
- if (elem != null) {
- Element.RemoveChild (elem);
- if (!Element.HasChildNodes)
- Element.IsEmpty = true;
- }
- }
-
- public string GetMetadata (string name, bool isXml = false)
- {
- XmlElement elem = EvaluatedElement [name, MSBuildProject.Schema];
- if (elem != null)
- return isXml ? elem.InnerXml : elem.InnerText;
- else
- return null;
- }
-
- public bool? GetBoolMetadata (string name)
- {
- var val = GetMetadata (name);
- if (String.Equals (val, "False", StringComparison.OrdinalIgnoreCase))
- return false;
- if (String.Equals (val, "True", StringComparison.OrdinalIgnoreCase))
- return true;
- return null;
- }
-
- public bool GetMetadataIsFalse (string name)
- {
- return String.Compare (GetMetadata (name), "False", StringComparison.OrdinalIgnoreCase) == 0;
- }
-
- public void MergeFrom (MSBuildItem other)
- {
- foreach (XmlNode node in Element.ChildNodes) {
- if (node is XmlElement)
- SetMetadata (node.LocalName, node.InnerXml, true);
- }
- }
-
- internal override void Evaluate (MSBuildEvaluationContext context)
- {
- XmlElement elem;
- if (context.Evaluate (Element, out elem))
- EvaluatedElement = elem;
- else
- EvaluatedElement = null;
- }
- }
- public class MSBuildItemGroup: MSBuildObject
- {
- MSBuildProject parent;
-
- internal MSBuildItemGroup (MSBuildProject parent, XmlElement elem): base (elem)
- {
- this.parent = parent;
- }
-
- public MSBuildItem AddNewItem (string name, string include)
- {
- XmlElement elem = AddChildElement (name);
- MSBuildItem it = parent.GetItem (elem);
- it.Include = include;
- return it;
- }
-
- public IEnumerable<MSBuildItem> Items {
- get {
- foreach (XmlNode node in Element.ChildNodes) {
- XmlElement elem = node as XmlElement;
- if (elem != null)
- yield return parent.GetItem (elem);
- }
- }
- }
-
- internal override void Evaluate (MSBuildEvaluationContext context)
- {
- foreach (var item in Items)
- item.Evaluate (context);
- }
- }
- public class MSBuildEvaluationContext: IExpressionContext
- {
- Dictionary<string,string> properties = new Dictionary<string, string> ();
- bool allResolved;
- MSBuildProject project;
-
- public MSBuildEvaluationContext ()
- {
- }
-
- internal void InitEvaluation (MSBuildProject project)
- {
- this.project = project;
- SetPropertyValue ("MSBuildThisFile", Path.GetFileName (project.FileName));
- SetPropertyValue ("MSBuildThisFileName", Path.GetFileNameWithoutExtension (project.FileName));
- SetPropertyValue ("MSBuildThisFileDirectory", Path.GetDirectoryName (project.FileName) + Path.DirectorySeparatorChar);
- SetPropertyValue ("MSBuildThisFileExtension", Path.GetExtension (project.FileName));
- SetPropertyValue ("MSBuildThisFileFullPath", Path.GetFullPath (project.FileName));
- SetPropertyValue ("VisualStudioReferenceAssemblyVersion", project.ToolsVersion + ".0.0");
- }
-
- public string GetPropertyValue (string name)
- {
- string val;
- if (properties.TryGetValue (name, out val))
- return val;
- else
- return Environment.GetEnvironmentVariable (name);
- }
-
- public void SetPropertyValue (string name, string value)
- {
- properties [name] = value;
- }
-
- public void ClearPropertyValue (string name)
- {
- properties.Remove (name);
- }
-
- public bool Evaluate (XmlElement source, out XmlElement result)
- {
- allResolved = true;
- result = (XmlElement) EvaluateNode (source);
- return allResolved;
- }
-
- XmlNode EvaluateNode (XmlNode source)
- {
- var elemSource = source as XmlElement;
- if (elemSource != null) {
- var elem = source.OwnerDocument.CreateElement (elemSource.Prefix, elemSource.LocalName, elemSource.NamespaceURI);
- foreach (XmlAttribute attr in elemSource.Attributes)
- elem.Attributes.Append ((XmlAttribute)EvaluateNode (attr));
- foreach (XmlNode child in elemSource.ChildNodes)
- elem.AppendChild (EvaluateNode (child));
- return elem;
- }
-
- var attSource = source as XmlAttribute;
- if (attSource != null) {
- bool oldResolved = allResolved;
- var att = source.OwnerDocument.CreateAttribute (attSource.Prefix, attSource.LocalName, attSource.NamespaceURI);
- att.Value = Evaluate (attSource.Value);
-
- // Condition attributes don't change the resolution status. Conditions are handled in the property and item objects
- if (attSource.Name == "Condition")
- allResolved = oldResolved;
-
- return att;
- }
- var textSource = source as XmlText;
- if (textSource != null) {
- return source.OwnerDocument.CreateTextNode (Evaluate (textSource.InnerText));
- }
- return source.Clone ();
- }
-
- public bool Evaluate (string str, out string result)
- {
- allResolved = true;
- result = Evaluate (str);
- return allResolved;
- }
-
- string Evaluate (string str)
- {
- int i = str.IndexOf ("$(");
- if (i == -1)
- return str;
-
- int last = 0;
-
- StringBuilder sb = new StringBuilder ();
- do {
- sb.Append (str, last, i - last);
- i += 2;
- int j = str.IndexOf (")", i);
- if (j == -1) {
- allResolved = false;
- return "";
- }
-
- string prop = str.Substring (i, j - i);
- string val = GetPropertyValue (prop);
- if (val == null) {
- allResolved = false;
- return "";
- }
-
- sb.Append (val);
- last = j + 1;
- i = str.IndexOf ("$(", last);
- }
- while (i != -1);
-
- sb.Append (str, last, str.Length - last);
- return sb.ToString ();
- }
-
- #region IExpressionContext implementation
-
- public string EvaluateString (string value)
- {
- if (value.StartsWith ("$(") && value.EndsWith (")"))
- return GetPropertyValue (value.Substring (2, value.Length - 3)) ?? value;
- else
- return value;
- }
-
- public string FullFileName {
- get {
- return project.FileName;
- }
- }
-
- #endregion
- }
}