Jo Shields 3c1f479b9d Imported Upstream version 4.0.0~alpha1
Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
2015-04-07 09:35:12 +01:00

1669 lines
50 KiB
C#

//
// Project.cs: Project class
//
// Author:
// Marek Sieradzki (marek.sieradzki@gmail.com)
// Ankit Jain (jankit@novell.com)
//
// (C) 2005 Marek Sieradzki
// Copyright 2011 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Mono.XBuild.Framework;
using Mono.XBuild.CommandLine;
namespace Microsoft.Build.BuildEngine {
public class Project {
bool buildEnabled;
Dictionary <string, List <string>> conditionedProperties;
string[] defaultTargets;
Encoding encoding;
BuildItemGroup evaluatedItems;
BuildItemGroup evaluatedItemsIgnoringCondition;
Dictionary <string, BuildItemGroup> evaluatedItemsByName;
Dictionary <string, BuildItemGroup> evaluatedItemsByNameIgnoringCondition;
BuildPropertyGroup evaluatedProperties;
string firstTargetName;
string fullFileName;
BuildPropertyGroup globalProperties;
GroupingCollection groupingCollection;
bool isDirty;
bool isValidated;
BuildItemGroupCollection itemGroups;
ImportCollection imports;
List<string> initialTargets;
Dictionary <string, BuildItemGroup> last_item_group_containing;
bool needToReevaluate;
Engine parentEngine;
BuildPropertyGroupCollection propertyGroups;
string schemaFile;
TaskDatabase taskDatabase;
TargetCollection targets;
DateTime timeOfLastDirty;
UsingTaskCollection usingTasks;
XmlDocument xmlDocument;
bool unloaded;
bool initialTargetsBuilt;
bool building;
BuildSettings current_settings;
Stack<Batch> batches;
// This is used to keep track of "current" file,
// which is then used to set the reserved properties
// $(MSBuildThisFile*)
Stack<string> this_file_property_stack;
ProjectLoadSettings project_load_settings;
static string extensions_path;
static XmlNamespaceManager manager;
static string ns = "http://schemas.microsoft.com/developer/msbuild/2003";
public Project ()
: this (Engine.GlobalEngine)
{
}
public Project (Engine engine) : this (engine, null)
{
}
public Project (Engine engine, string toolsVersion)
{
parentEngine = engine;
ToolsVersion = toolsVersion;
buildEnabled = ParentEngine.BuildEnabled;
xmlDocument = new XmlDocument ();
xmlDocument.PreserveWhitespace = false;
xmlDocument.AppendChild (xmlDocument.CreateElement ("Project", XmlNamespace));
xmlDocument.DocumentElement.SetAttribute ("xmlns", ns);
fullFileName = String.Empty;
timeOfLastDirty = DateTime.Now;
current_settings = BuildSettings.None;
project_load_settings = ProjectLoadSettings.None;
encoding = null;
initialTargets = new List<string> ();
defaultTargets = new string [0];
batches = new Stack<Batch> ();
this_file_property_stack = new Stack<string> ();
globalProperties = new BuildPropertyGroup (null, this, null, false);
foreach (BuildProperty bp in parentEngine.GlobalProperties)
GlobalProperties.AddProperty (bp.Clone (true));
ProcessXml ();
}
[MonoTODO ("Not tested")]
public void AddNewImport (string importLocation,
string importCondition)
{
if (importLocation == null)
throw new ArgumentNullException ("importLocation");
XmlElement importElement = xmlDocument.CreateElement ("Import", XmlNamespace);
xmlDocument.DocumentElement.AppendChild (importElement);
importElement.SetAttribute ("Project", importLocation);
if (!String.IsNullOrEmpty (importCondition))
importElement.SetAttribute ("Condition", importCondition);
AddImport (importElement, null, false);
MarkProjectAsDirty ();
NeedToReevaluate ();
}
public BuildItem AddNewItem (string itemName,
string itemInclude)
{
return AddNewItem (itemName, itemInclude, false);
}
[MonoTODO ("Adds item not in the same place as MS")]
public BuildItem AddNewItem (string itemName,
string itemInclude,
bool treatItemIncludeAsLiteral)
{
BuildItemGroup big;
if (itemGroups.Count == 0)
big = AddNewItemGroup ();
else {
if (last_item_group_containing.ContainsKey (itemName)) {
big = last_item_group_containing [itemName];
} else {
// FIXME: not tested
BuildItemGroup [] groups = new BuildItemGroup [itemGroups.Count];
itemGroups.CopyTo (groups, 0);
big = groups [0];
}
}
BuildItem item = big.AddNewItem (itemName, itemInclude, treatItemIncludeAsLiteral);
MarkProjectAsDirty ();
NeedToReevaluate ();
return item;
}
[MonoTODO ("Not tested")]
public BuildItemGroup AddNewItemGroup ()
{
XmlElement element = xmlDocument.CreateElement ("ItemGroup", XmlNamespace);
xmlDocument.DocumentElement.AppendChild (element);
BuildItemGroup big = new BuildItemGroup (element, this, null, false);
itemGroups.Add (big);
MarkProjectAsDirty ();
NeedToReevaluate ();
return big;
}
[MonoTODO ("Ignores insertAtEndOfProject")]
public BuildPropertyGroup AddNewPropertyGroup (bool insertAtEndOfProject)
{
XmlElement element = xmlDocument.CreateElement ("PropertyGroup", XmlNamespace);
xmlDocument.DocumentElement.AppendChild (element);
BuildPropertyGroup bpg = new BuildPropertyGroup (element, this, null, false);
propertyGroups.Add (bpg);
MarkProjectAsDirty ();
NeedToReevaluate ();
return bpg;
}
[MonoTODO ("Not tested, isn't added to TaskDatabase (no reevaluation)")]
public void AddNewUsingTaskFromAssemblyFile (string taskName,
string assemblyFile)
{
if (taskName == null)
throw new ArgumentNullException ("taskName");
if (assemblyFile == null)
throw new ArgumentNullException ("assemblyFile");
XmlElement element = xmlDocument.CreateElement ("UsingTask", XmlNamespace);
xmlDocument.DocumentElement.AppendChild (element);
element.SetAttribute ("TaskName", taskName);
element.SetAttribute ("AssemblyFile", assemblyFile);
UsingTask ut = new UsingTask (element, this, null);
usingTasks.Add (ut);
MarkProjectAsDirty ();
}
[MonoTODO ("Not tested, isn't added to TaskDatabase (no reevaluation)")]
public void AddNewUsingTaskFromAssemblyName (string taskName,
string assemblyName)
{
if (taskName == null)
throw new ArgumentNullException ("taskName");
if (assemblyName == null)
throw new ArgumentNullException ("assemblyName");
XmlElement element = xmlDocument.CreateElement ("UsingTask", XmlNamespace);
xmlDocument.DocumentElement.AppendChild (element);
element.SetAttribute ("TaskName", taskName);
element.SetAttribute ("AssemblyName", assemblyName);
UsingTask ut = new UsingTask (element, this, null);
usingTasks.Add (ut);
MarkProjectAsDirty ();
}
[MonoTODO ("Not tested")]
public bool Build ()
{
return Build (new string [0]);
}
[MonoTODO ("Not tested")]
public bool Build (string targetName)
{
if (targetName == null)
return Build ((string[]) null);
else
return Build (new string [1] { targetName });
}
[MonoTODO ("Not tested")]
public bool Build (string [] targetNames)
{
return Build (targetNames, null);
}
[MonoTODO ("Not tested")]
public bool Build (string [] targetNames,
IDictionary targetOutputs)
{
return Build (targetNames, targetOutputs, BuildSettings.None);
}
[MonoTODO ("Not tested")]
public bool Build (string [] targetNames,
IDictionary targetOutputs,
BuildSettings buildFlags)
{
bool result = false;
ParentEngine.StartProjectBuild (this, targetNames);
// Invoking this to emit a warning in case of unsupported
// ToolsVersion
GetToolsVersionToUse (true);
string current_directory = Environment.CurrentDirectory;
try {
current_settings = buildFlags;
if (!String.IsNullOrEmpty (fullFileName))
Directory.SetCurrentDirectory (Path.GetDirectoryName (fullFileName));
building = true;
result = BuildInternal (targetNames, targetOutputs, buildFlags);
} catch (InvalidProjectFileException ie) {
ParentEngine.LogErrorWithFilename (fullFileName, ie.Message);
ParentEngine.LogMessage (MessageImportance.Low, String.Format ("{0}: {1}", fullFileName, ie.ToString ()));
} catch (Exception e) {
ParentEngine.LogErrorWithFilename (fullFileName, e.Message);
ParentEngine.LogMessage (MessageImportance.Low, String.Format ("{0}: {1}", fullFileName, e.ToString ()));
throw;
} finally {
ParentEngine.EndProjectBuild (this, result);
current_settings = BuildSettings.None;
Directory.SetCurrentDirectory (current_directory);
building = false;
}
return result;
}
bool BuildInternal (string [] targetNames,
IDictionary targetOutputs,
BuildSettings buildFlags)
{
CheckUnloaded ();
if (buildFlags == BuildSettings.None) {
needToReevaluate = false;
Reevaluate ();
}
ProcessBeforeAndAfterTargets ();
if (targetNames == null || targetNames.Length == 0) {
if (defaultTargets != null && defaultTargets.Length != 0) {
targetNames = defaultTargets;
} else if (firstTargetName != null) {
targetNames = new string [1] { firstTargetName};
} else {
if (targets == null || targets.Count == 0) {
LogError (fullFileName, "No target found in the project");
return false;
}
return false;
}
}
if (!initialTargetsBuilt) {
foreach (string target in initialTargets) {
if (!BuildTarget (target.Trim (), targetOutputs))
return false;
}
initialTargetsBuilt = true;
}
foreach (string target in targetNames) {
if (target == null)
throw new ArgumentNullException ("Target name cannot be null");
if (!BuildTarget (target.Trim (), targetOutputs))
return false;
}
return true;
}
bool BuildTarget (string target_name, IDictionary targetOutputs)
{
if (target_name == null)
throw new ArgumentException ("targetNames cannot contain null strings");
if (!targets.Exists (target_name)) {
LogError (fullFileName, "Target named '{0}' not found in the project.", target_name);
return false;
}
string key = GetKeyForTarget (target_name);
if (!targets [target_name].Build (key))
return false;
ITaskItem[] outputs;
if (ParentEngine.BuiltTargetsOutputByName.TryGetValue (key, out outputs)) {
if (targetOutputs != null)
targetOutputs.Add (target_name, outputs);
}
return true;
}
internal string GetKeyForTarget (string target_name)
{
return GetKeyForTarget (target_name, true);
}
internal string GetKeyForTarget (string target_name, bool include_global_properties)
{
// target name is case insensitive
return fullFileName + ":" + target_name.ToLowerInvariant () +
(include_global_properties ? (":" + GlobalPropertiesToString (GlobalProperties))
: String.Empty);
}
string GlobalPropertiesToString (BuildPropertyGroup bgp)
{
StringBuilder sb = new StringBuilder ();
foreach (BuildProperty bp in bgp)
sb.AppendFormat (" {0}:{1}", bp.Name, bp.FinalValue);
return sb.ToString ();
}
void ProcessBeforeAndAfterTargets ()
{
var beforeTable = Targets.AsIEnumerable ()
.SelectMany (target => GetTargetNamesFromString (target.BeforeTargets),
(target, before_target) => new {before_target, name = target.Name})
.ToLookup (x => x.before_target, x => x.name)
.ToDictionary (x => x.Key, x => x.Distinct ().ToList ());
foreach (var pair in beforeTable) {
if (targets.Exists (pair.Key))
targets [pair.Key].BeforeThisTargets = pair.Value;
else
LogWarning (FullFileName, "Target '{0}', not found in the project", pair.Key);
}
var afterTable = Targets.AsIEnumerable ()
.SelectMany (target => GetTargetNamesFromString (target.AfterTargets),
(target, after_target) => new {after_target, name = target.Name})
.ToLookup (x => x.after_target, x => x.name)
.ToDictionary (x => x.Key, x => x.Distinct ().ToList ());
foreach (var pair in afterTable) {
if (targets.Exists (pair.Key))
targets [pair.Key].AfterThisTargets = pair.Value;
else
LogWarning (FullFileName, "Target '{0}', not found in the project", pair.Key);
}
}
string[] GetTargetNamesFromString (string targets)
{
Expression expr = new Expression ();
expr.Parse (targets, ParseOptions.AllowItemsNoMetadataAndSplit);
return (string []) expr.ConvertTo (this, typeof (string []));
}
[MonoTODO]
public string [] GetConditionedPropertyValues (string propertyName)
{
if (conditionedProperties.ContainsKey (propertyName))
return conditionedProperties [propertyName].ToArray ();
else
return new string [0];
}
public BuildItemGroup GetEvaluatedItemsByName (string itemName)
{
if (needToReevaluate) {
needToReevaluate = false;
Reevaluate ();
}
if (evaluatedItemsByName.ContainsKey (itemName))
return evaluatedItemsByName [itemName];
else
return new BuildItemGroup (this);
}
public BuildItemGroup GetEvaluatedItemsByNameIgnoringCondition (string itemName)
{
if (needToReevaluate) {
needToReevaluate = false;
Reevaluate ();
}
if (evaluatedItemsByNameIgnoringCondition.ContainsKey (itemName))
return evaluatedItemsByNameIgnoringCondition [itemName];
else
return new BuildItemGroup (this);
}
public string GetEvaluatedProperty (string propertyName)
{
if (needToReevaluate) {
needToReevaluate = false;
Reevaluate ();
}
if (propertyName == null)
throw new ArgumentNullException ("propertyName");
BuildProperty bp = evaluatedProperties [propertyName];
return bp == null ? null : (string) bp;
}
[MonoTODO ("We should remember that node and not use XPath to get it")]
public string GetProjectExtensions (string id)
{
if (id == null || id == String.Empty)
return String.Empty;
XmlNode node = xmlDocument.SelectSingleNode (String.Format ("/tns:Project/tns:ProjectExtensions/tns:{0}", id), XmlNamespaceManager);
if (node == null)
return String.Empty;
else
return node.InnerXml;
}
public void Load (string projectFileName)
{
Load (projectFileName, ProjectLoadSettings.None);
}
public void Load (string projectFileName, ProjectLoadSettings settings)
{
project_load_settings = settings;
if (String.IsNullOrEmpty (projectFileName))
throw new ArgumentNullException ("projectFileName");
if (!File.Exists (projectFileName))
throw new ArgumentException (String.Format ("Project file {0} not found", projectFileName),
"projectFileName");
this.fullFileName = Utilities.FromMSBuildPath (Path.GetFullPath (projectFileName));
PushThisFileProperty (fullFileName);
string filename = fullFileName;
if (String.Compare (Path.GetExtension (fullFileName), ".sln", true) == 0) {
Project tmp_project = ParentEngine.CreateNewProject ();
tmp_project.FullFileName = filename;
SolutionParser sln_parser = new SolutionParser ();
sln_parser.ParseSolution (fullFileName, tmp_project, delegate (int errorNumber, string message) {
LogWarning (filename, message);
});
filename = fullFileName + ".proj";
try {
tmp_project.Save (filename);
ParentEngine.RemoveLoadedProject (tmp_project);
DoLoad (new StreamReader (filename));
} finally {
if (Environment.GetEnvironmentVariable ("XBUILD_EMIT_SOLUTION") == null)
File.Delete (filename);
}
} else {
DoLoad (new StreamReader (filename));
}
}
[MonoTODO ("Not tested")]
public void Load (TextReader textReader)
{
Load (textReader, ProjectLoadSettings.None);
}
public void Load (TextReader textReader, ProjectLoadSettings projectLoadSettings)
{
project_load_settings = projectLoadSettings;
if (!string.IsNullOrEmpty (fullFileName))
PushThisFileProperty (fullFileName);
DoLoad (textReader);
}
public void LoadXml (string projectXml)
{
LoadXml (projectXml, ProjectLoadSettings.None);
}
public void LoadXml (string projectXml, ProjectLoadSettings projectLoadSettings)
{
project_load_settings = projectLoadSettings;
if (!string.IsNullOrEmpty (fullFileName))
PushThisFileProperty (fullFileName);
DoLoad (new StringReader (projectXml));
MarkProjectAsDirty ();
}
public void MarkProjectAsDirty ()
{
isDirty = true;
timeOfLastDirty = DateTime.Now;
}
[MonoTODO ("Not tested")]
public void RemoveAllItemGroups ()
{
int length = ItemGroups.Count;
BuildItemGroup [] groups = new BuildItemGroup [length];
ItemGroups.CopyTo (groups, 0);
for (int i = 0; i < length; i++)
RemoveItemGroup (groups [i]);
MarkProjectAsDirty ();
NeedToReevaluate ();
}
[MonoTODO ("Not tested")]
public void RemoveAllPropertyGroups ()
{
int length = PropertyGroups.Count;
BuildPropertyGroup [] groups = new BuildPropertyGroup [length];
PropertyGroups.CopyTo (groups, 0);
for (int i = 0; i < length; i++)
RemovePropertyGroup (groups [i]);
MarkProjectAsDirty ();
NeedToReevaluate ();
}
[MonoTODO]
public void RemoveItem (BuildItem itemToRemove)
{
if (itemToRemove == null)
throw new ArgumentNullException ("itemToRemove");
if (!itemToRemove.FromXml && !itemToRemove.HasParentItem)
throw new InvalidOperationException ("The object passed in is not part of the project.");
BuildItemGroup big = itemToRemove.ParentItemGroup;
if (big.Count == 1) {
// ParentItemGroup for items from xml and that have parent is the same
groupingCollection.Remove (big);
} else {
if (big.ParentProject != this)
throw new InvalidOperationException ("The object passed in is not part of the project.");
if (itemToRemove.FromXml)
big.RemoveItem (itemToRemove);
else
big.RemoveItem (itemToRemove.ParentItem);
}
MarkProjectAsDirty ();
NeedToReevaluate ();
}
[MonoTODO ("Not tested")]
public void RemoveItemGroup (BuildItemGroup itemGroupToRemove)
{
if (itemGroupToRemove == null)
throw new ArgumentNullException ("itemGroupToRemove");
groupingCollection.Remove (itemGroupToRemove);
MarkProjectAsDirty ();
}
[MonoTODO]
// NOTE: does not modify imported projects
public void RemoveItemGroupsWithMatchingCondition (string matchingCondition)
{
throw new NotImplementedException ();
}
[MonoTODO]
public void RemoveItemsByName (string itemName)
{
if (itemName == null)
throw new ArgumentNullException ("itemName");
throw new NotImplementedException ();
}
[MonoTODO ("Not tested")]
public void RemovePropertyGroup (BuildPropertyGroup propertyGroupToRemove)
{
if (propertyGroupToRemove == null)
throw new ArgumentNullException ("propertyGroupToRemove");
groupingCollection.Remove (propertyGroupToRemove);
MarkProjectAsDirty ();
}
[MonoTODO]
// NOTE: does not modify imported projects
public void RemovePropertyGroupsWithMatchingCondition (string matchCondition)
{
throw new NotImplementedException ();
}
[MonoTODO]
public void ResetBuildStatus ()
{
// hack to allow built targets to be removed
building = true;
Reevaluate ();
building = false;
}
public void Save (string projectFileName)
{
Save (projectFileName, Encoding.Default);
isDirty = false;
}
[MonoTODO ("Ignores encoding")]
public void Save (string projectFileName, Encoding encoding)
{
xmlDocument.Save (projectFileName);
isDirty = false;
}
public void Save (TextWriter outTextWriter)
{
xmlDocument.Save (outTextWriter);
isDirty = false;
}
public void SetImportedProperty (string propertyName,
string propertyValue,
string condition,
Project importProject)
{
SetImportedProperty (propertyName, propertyValue, condition, importProject,
PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup);
}
public void SetImportedProperty (string propertyName,
string propertyValue,
string condition,
Project importedProject,
PropertyPosition position)
{
SetImportedProperty (propertyName, propertyValue, condition, importedProject,
PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup, false);
}
[MonoTODO]
public void SetImportedProperty (string propertyName,
string propertyValue,
string condition,
Project importedProject,
PropertyPosition position,
bool treatPropertyValueAsLiteral)
{
throw new NotImplementedException ();
}
public void SetProjectExtensions (string id, string xmlText)
{
if (id == null)
throw new ArgumentNullException ("id");
if (xmlText == null)
throw new ArgumentNullException ("xmlText");
XmlNode projectExtensions, node;
projectExtensions = xmlDocument.SelectSingleNode ("/tns:Project/tns:ProjectExtensions", XmlNamespaceManager);
if (projectExtensions == null) {
projectExtensions = xmlDocument.CreateElement ("ProjectExtensions", XmlNamespace);
xmlDocument.DocumentElement.AppendChild (projectExtensions);
node = xmlDocument.CreateElement (id, XmlNamespace);
node.InnerXml = xmlText;
projectExtensions.AppendChild (node);
} else {
node = xmlDocument.SelectSingleNode (String.Format ("/tns:Project/tns:ProjectExtensions/tns:{0}", id), XmlNamespaceManager);
if (node == null) {
node = xmlDocument.CreateElement (id, XmlNamespace);
projectExtensions.AppendChild (node);
}
node.InnerXml = xmlText;
}
MarkProjectAsDirty ();
}
public void SetProperty (string propertyName,
string propertyValue)
{
SetProperty (propertyName, propertyValue, "true",
PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup, false);
}
public void SetProperty (string propertyName,
string propertyValue,
string condition)
{
SetProperty (propertyName, propertyValue, condition,
PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup);
}
public void SetProperty (string propertyName,
string propertyValue,
string condition,
PropertyPosition position)
{
SetProperty (propertyName, propertyValue, condition,
PropertyPosition.UseExistingOrCreateAfterLastPropertyGroup, false);
}
[MonoTODO]
public void SetProperty (string propertyName,
string propertyValue,
string condition,
PropertyPosition position,
bool treatPropertyValueAsLiteral)
{
throw new NotImplementedException ();
}
internal void Unload ()
{
unloaded = true;
}
internal void CheckUnloaded ()
{
if (unloaded)
throw new InvalidOperationException ("This project object has been unloaded from the MSBuild engine and is no longer valid.");
}
internal void NeedToReevaluate ()
{
needToReevaluate = true;
}
// Does the actual loading.
void DoLoad (TextReader textReader)
{
try {
ParentEngine.RemoveLoadedProject (this);
xmlDocument.Load (textReader);
if (xmlDocument.DocumentElement.Name == "VisualStudioProject")
throw new InvalidProjectFileException (String.Format (
"Project file '{0}' is a VS2003 project, which is not " +
"supported by xbuild. You need to convert it to msbuild " +
"format to build with xbuild.", fullFileName));
if (SchemaFile != null) {
xmlDocument.Schemas.Add (XmlSchema.Read (
new StreamReader (SchemaFile), ValidationCallBack));
xmlDocument.Validate (ValidationCallBack);
}
if (xmlDocument.DocumentElement.Name != "Project") {
throw new InvalidProjectFileException (String.Format (
"The element <{0}> is unrecognized, or not supported in this context.", xmlDocument.DocumentElement.Name));
}
if (xmlDocument.DocumentElement.GetAttribute ("xmlns") != ns) {
throw new InvalidProjectFileException (
@"The default XML namespace of the project must be the MSBuild XML namespace." +
" If the project is authored in the MSBuild 2003 format, please add " +
"xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\" to the <Project> element. " +
"If the project has been authored in the old 1.0 or 1.2 format, please convert it to MSBuild 2003 format. ");
}
ProcessXml ();
ParentEngine.AddLoadedProject (this);
} catch (Exception e) {
throw new InvalidProjectFileException (String.Format ("{0}: {1}",
fullFileName, e.Message), e);
} finally {
if (textReader != null)
textReader.Close ();
}
}
void Reevaluate ()
{
ProcessXml ();
}
void ProcessXml ()
{
groupingCollection = new GroupingCollection (this);
imports = new ImportCollection (groupingCollection);
usingTasks = new UsingTaskCollection (this);
itemGroups = new BuildItemGroupCollection (groupingCollection);
propertyGroups = new BuildPropertyGroupCollection (groupingCollection);
targets = new TargetCollection (this);
last_item_group_containing = new Dictionary <string, BuildItemGroup> ();
string effective_tools_version = GetToolsVersionToUse (false);
taskDatabase = new TaskDatabase ();
taskDatabase.CopyTasks (ParentEngine.GetDefaultTasks (effective_tools_version));
initialTargets = new List<string> ();
defaultTargets = new string [0];
PrepareForEvaluate (effective_tools_version);
ProcessElements (xmlDocument.DocumentElement, null);
isDirty = false;
Evaluate ();
}
void ProcessProjectAttributes (XmlAttributeCollection attributes)
{
foreach (XmlAttribute attr in attributes) {
switch (attr.Name) {
case "InitialTargets":
initialTargets.AddRange (attr.Value.Split (
new char [] {';', ' '},
StringSplitOptions.RemoveEmptyEntries));
break;
case "DefaultTargets":
// first non-empty DefaultTargets found is used
if (defaultTargets == null || defaultTargets.Length == 0)
defaultTargets = attr.Value.Split (new char [] {';', ' '},
StringSplitOptions.RemoveEmptyEntries);
EvaluatedProperties.AddProperty (new BuildProperty ("MSBuildProjectDefaultTargets",
DefaultTargets, PropertyType.Reserved));
break;
}
}
}
internal void ProcessElements (XmlElement rootElement, ImportedProject ip)
{
ProcessProjectAttributes (rootElement.Attributes);
foreach (XmlNode xn in rootElement.ChildNodes) {
if (xn is XmlElement) {
XmlElement xe = (XmlElement) xn;
switch (xe.Name) {
case "ProjectExtensions":
AddProjectExtensions (xe);
break;
case "Warning":
case "Message":
case "Error":
AddMessage (xe);
break;
case "Target":
AddTarget (xe, ip);
break;
case "UsingTask":
AddUsingTask (xe, ip);
break;
case "Import":
AddImport (xe, ip, true);
break;
case "ImportGroup":
AddImportGroup (xe, ip, true);
break;
case "ItemGroup":
AddItemGroup (xe, ip);
break;
case "PropertyGroup":
AddPropertyGroup (xe, ip);
break;
case "Choose":
AddChoose (xe, ip);
break;
case "ItemDefinitionGroup":
AddItemDefinitionGroup (xe);
break;
default:
var pf = ip == null ? null : string.Format (" '{0}'", ip.FullFileName);
throw new InvalidProjectFileException (String.Format ("Invalid element '{0}' in project file{1}.", xe.Name, pf));
}
}
}
}
void PrepareForEvaluate (string effective_tools_version)
{
evaluatedItems = new BuildItemGroup (null, this, null, true);
evaluatedItemsIgnoringCondition = new BuildItemGroup (null, this, null, true);
evaluatedItemsByName = new Dictionary <string, BuildItemGroup> (StringComparer.OrdinalIgnoreCase);
evaluatedItemsByNameIgnoringCondition = new Dictionary <string, BuildItemGroup> (StringComparer.OrdinalIgnoreCase);
if (building && current_settings == BuildSettings.None)
RemoveBuiltTargets ();
InitializeProperties (effective_tools_version);
}
void Evaluate ()
{
groupingCollection.Evaluate ();
//FIXME: UsingTasks aren't really evaluated. (shouldn't use expressions or anything)
foreach (UsingTask usingTask in UsingTasks)
usingTask.Evaluate ();
}
// Removes entries of all earlier built targets for this project
void RemoveBuiltTargets ()
{
ParentEngine.ClearBuiltTargetsForProject (this);
}
void InitializeProperties (string effective_tools_version)
{
BuildProperty bp;
evaluatedProperties = new BuildPropertyGroup (null, null, null, true);
conditionedProperties = new Dictionary<string, List<string>> ();
foreach (BuildProperty gp in GlobalProperties) {
bp = new BuildProperty (gp.Name, gp.Value, PropertyType.Global);
evaluatedProperties.AddProperty (bp);
}
foreach (BuildProperty gp in GlobalProperties)
ParentEngine.GlobalProperties.AddProperty (gp);
// add properties that we dont have from parent engine's
// global properties
foreach (BuildProperty gp in ParentEngine.GlobalProperties) {
if (evaluatedProperties [gp.Name] == null) {
bp = new BuildProperty (gp.Name, gp.Value, PropertyType.Global);
evaluatedProperties.AddProperty (bp);
}
}
foreach (DictionaryEntry de in Environment.GetEnvironmentVariables ()) {
bp = new BuildProperty ((string) de.Key, (string) de.Value, PropertyType.Environment);
evaluatedProperties.AddProperty (bp);
}
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildProjectFile", Path.GetFileName (fullFileName),
PropertyType.Reserved));
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildProjectFullPath", fullFileName, PropertyType.Reserved));
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildProjectName",
Path.GetFileNameWithoutExtension (fullFileName),
PropertyType.Reserved));
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildProjectExtension",
Path.GetExtension (fullFileName),
PropertyType.Reserved));
string toolsPath = parentEngine.Toolsets [effective_tools_version].ToolsPath;
if (toolsPath == null)
throw new Exception (String.Format ("Invalid tools version '{0}', no tools path set for this.", effective_tools_version));
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildBinPath", toolsPath, PropertyType.Reserved));
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildToolsPath", toolsPath, PropertyType.Reserved));
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildToolsRoot", Path.GetDirectoryName (toolsPath), PropertyType.Reserved));
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildToolsVersion", effective_tools_version, PropertyType.Reserved));
SetExtensionsPathProperties (DefaultExtensionsPath);
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildProjectDefaultTargets", DefaultTargets, PropertyType.Reserved));
evaluatedProperties.AddProperty (new BuildProperty ("OS", OS, PropertyType.Environment));
#if XBUILD_12
// see http://msdn.microsoft.com/en-us/library/vstudio/hh162058(v=vs.120).aspx
if (effective_tools_version == "12.0") {
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildToolsPath32", toolsPath, PropertyType.Reserved));
var frameworkToolsPath = ToolLocationHelper.GetPathToDotNetFramework (TargetDotNetFrameworkVersion.Version451);
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildFrameworkToolsPath", frameworkToolsPath, PropertyType.Reserved));
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildFrameworkToolsPath32", frameworkToolsPath, PropertyType.Reserved));
}
#endif
// FIXME: make some internal method that will work like GetDirectoryName but output String.Empty on null/String.Empty
string projectDir;
if (FullFileName == String.Empty)
projectDir = Environment.CurrentDirectory;
else
projectDir = Path.GetDirectoryName (FullFileName);
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildProjectDirectory", projectDir, PropertyType.Reserved));
if (this_file_property_stack.Count > 0)
// Just re-inited the properties, but according to the stack,
// we should have a MSBuild*This* property set
SetMSBuildThisFileProperties (this_file_property_stack.Peek ());
}
internal void SetExtensionsPathProperties (string extn_path)
{
if (!String.IsNullOrEmpty (extn_path)) {
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildExtensionsPath", extn_path, PropertyType.Reserved));
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildExtensionsPath32", extn_path, PropertyType.Reserved));
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildExtensionsPath64", extn_path, PropertyType.Reserved));
}
}
// precedence:
// ToolsVersion property
// ToolsVersion attribute on the project
// parentEngine's DefaultToolsVersion
string GetToolsVersionToUse (bool emitWarning)
{
if (!String.IsNullOrEmpty (ToolsVersion))
return ToolsVersion;
if (!HasToolsVersionAttribute)
return parentEngine.DefaultToolsVersion;
if (parentEngine.Toolsets [DefaultToolsVersion] == null) {
if (emitWarning)
LogWarning (FullFileName, "Project has unknown ToolsVersion '{0}'. Using the default tools version '{1}' instead.",
DefaultToolsVersion, parentEngine.DefaultToolsVersion);
return parentEngine.DefaultToolsVersion;
}
return DefaultToolsVersion;
}
void AddProjectExtensions (XmlElement xmlElement)
{
}
void AddMessage (XmlElement xmlElement)
{
}
void AddTarget (XmlElement xmlElement, ImportedProject importedProject)
{
Target target = new Target (xmlElement, this, importedProject);
targets.AddTarget (target);
if (firstTargetName == null)
firstTargetName = target.Name;
}
void AddUsingTask (XmlElement xmlElement, ImportedProject importedProject)
{
UsingTask usingTask;
usingTask = new UsingTask (xmlElement, this, importedProject);
UsingTasks.Add (usingTask);
}
void AddImport (XmlElement xmlElement, ImportedProject importingProject, bool evaluate_properties)
{
// eval all the properties etc till the import
if (evaluate_properties) {
groupingCollection.Evaluate (EvaluationType.Property | EvaluationType.Choose);
}
try {
PushThisFileProperty (importingProject != null ? importingProject.FullFileName : FullFileName);
string project_attribute = xmlElement.GetAttribute ("Project");
if (String.IsNullOrEmpty (project_attribute))
throw new InvalidProjectFileException ("The required attribute \"Project\" is missing from element <Import>.");
Import.ForEachExtensionPathTillFound (xmlElement, this, importingProject,
(importPath, from_source_msg) => AddSingleImport (xmlElement, importPath, importingProject, from_source_msg));
} finally {
PopThisFileProperty ();
}
}
void AddImportGroup (XmlElement xmlElement, ImportedProject importedProject, bool evaluate_properties)
{
// eval all the properties etc till the import group
if (evaluate_properties) {
groupingCollection.Evaluate (EvaluationType.Property | EvaluationType.Choose);
}
string condition_attribute = xmlElement.GetAttribute ("Condition");
if (!ConditionParser.ParseAndEvaluate (condition_attribute, this))
return;
foreach (XmlNode xn in xmlElement.ChildNodes) {
if (xn is XmlElement) {
XmlElement xe = (XmlElement) xn;
switch (xe.Name) {
case "Import":
AddImport (xe, importedProject, evaluate_properties);
break;
default:
throw new InvalidProjectFileException(String.Format("Invalid element '{0}' inside ImportGroup in project file '{1}'.", xe.Name, importedProject.FullFileName));
}
}
}
}
void AddItemDefinitionGroup (XmlElement xmlElement)
{
string condition_attribute = xmlElement.GetAttribute ("Condition");
if (!ConditionParser.ParseAndEvaluate (condition_attribute, this))
return;
foreach (XmlNode xn in xmlElement.ChildNodes) {
// TODO: Add all nodes to some internal dictionary?
}
}
bool AddSingleImport (XmlElement xmlElement, string projectPath, ImportedProject importingProject, string from_source_msg)
{
Import import = new Import (xmlElement, projectPath, this, importingProject);
if (!ConditionParser.ParseAndEvaluate (import.Condition, this)) {
ParentEngine.LogMessage (MessageImportance.Low,
"Not importing project '{0}' as the condition '{1}' is false",
import.ProjectPath, import.Condition);
return false;
}
Import existingImport;
if (Imports.TryGetImport (import, out existingImport)) {
if (importingProject == null)
LogWarning (fullFileName,
"Cannot import project '{0}' again. It was already imported by " +
"'{1}'. Ignoring.",
projectPath, existingImport.ContainedInProjectFileName);
else
LogWarning (importingProject != null ? importingProject.FullFileName : fullFileName,
"A circular reference was found involving the import of '{0}'. " +
"It was earlier imported by '{1}'. Only " +
"the first import of this file will be used, ignoring others.",
import.EvaluatedProjectPath, existingImport.ContainedInProjectFileName);
return true;
}
if (String.Compare (fullFileName, import.EvaluatedProjectPath) == 0) {
LogWarning (importingProject != null ? importingProject.FullFileName : fullFileName,
"The main project file was imported here, which creates a circular " +
"reference. Ignoring this import.");
return true;
}
if (project_load_settings != ProjectLoadSettings.IgnoreMissingImports &&
!import.CheckEvaluatedProjectPathExists ())
return false;
Imports.Add (import);
string importingFile = importingProject != null ? importingProject.FullFileName : FullFileName;
ParentEngine.LogMessage (MessageImportance.Low,
"{0}: Importing project {1} {2}",
importingFile, import.EvaluatedProjectPath, from_source_msg);
import.Evaluate (project_load_settings == ProjectLoadSettings.IgnoreMissingImports);
return true;
}
void AddItemGroup (XmlElement xmlElement, ImportedProject importedProject)
{
BuildItemGroup big = new BuildItemGroup (xmlElement, this, importedProject, false);
ItemGroups.Add (big);
}
void AddPropertyGroup (XmlElement xmlElement, ImportedProject importedProject)
{
BuildPropertyGroup bpg = new BuildPropertyGroup (xmlElement, this, importedProject, false);
PropertyGroups.Add (bpg);
}
void AddChoose (XmlElement xmlElement, ImportedProject importedProject)
{
BuildChoose bc = new BuildChoose (xmlElement, this, importedProject);
groupingCollection.Add (bc);
}
static void ValidationCallBack (object sender, ValidationEventArgs e)
{
Console.WriteLine ("Validation Error: {0}", e.Message);
}
public bool BuildEnabled {
get {
return buildEnabled;
}
set {
buildEnabled = value;
}
}
[MonoTODO]
public Encoding Encoding {
get { return encoding; }
}
public string DefaultTargets {
get {
return String.Join ("; ", defaultTargets);
}
set {
xmlDocument.DocumentElement.SetAttribute ("DefaultTargets", value);
if (value != null)
defaultTargets = value.Split (new char [] {';', ' '},
StringSplitOptions.RemoveEmptyEntries);
}
}
public BuildItemGroup EvaluatedItems {
get {
if (needToReevaluate) {
needToReevaluate = false;
Reevaluate ();
}
return evaluatedItems;
}
}
public BuildItemGroup EvaluatedItemsIgnoringCondition {
get {
if (needToReevaluate) {
needToReevaluate = false;
Reevaluate ();
}
return evaluatedItemsIgnoringCondition;
}
}
internal IDictionary <string, BuildItemGroup> EvaluatedItemsByName {
get {
// FIXME: do we need to do this here?
if (needToReevaluate) {
needToReevaluate = false;
Reevaluate ();
}
return evaluatedItemsByName;
}
}
internal IEnumerable EvaluatedItemsByNameAsDictionaryEntries {
get {
if (EvaluatedItemsByName.Count == 0)
yield break;
foreach (KeyValuePair<string, BuildItemGroup> pair in EvaluatedItemsByName) {
foreach (BuildItem bi in pair.Value)
yield return new DictionaryEntry (pair.Key, bi.ConvertToITaskItem (null, ExpressionOptions.ExpandItemRefs));
}
}
}
internal IDictionary <string, BuildItemGroup> EvaluatedItemsByNameIgnoringCondition {
get {
// FIXME: do we need to do this here?
if (needToReevaluate) {
needToReevaluate = false;
Reevaluate ();
}
return evaluatedItemsByNameIgnoringCondition;
}
}
// For batching implementation
Dictionary<string, BuildItemGroup> perBatchItemsByName;
Dictionary<string, BuildItemGroup> commonItemsByName;
struct Batch {
public Dictionary<string, BuildItemGroup> perBatchItemsByName;
public Dictionary<string, BuildItemGroup> commonItemsByName;
public Batch (Dictionary<string, BuildItemGroup> perBatchItemsByName, Dictionary<string, BuildItemGroup> commonItemsByName)
{
this.perBatchItemsByName = perBatchItemsByName;
this.commonItemsByName = commonItemsByName;
}
}
Stack<Batch> Batches {
get { return batches; }
}
internal void PushBatch (Dictionary<string, BuildItemGroup> perBatchItemsByName, Dictionary<string, BuildItemGroup> commonItemsByName)
{
batches.Push (new Batch (perBatchItemsByName, commonItemsByName));
SetBatchedItems (perBatchItemsByName, commonItemsByName);
}
internal void PopBatch ()
{
batches.Pop ();
if (batches.Count > 0) {
Batch b = batches.Peek ();
SetBatchedItems (b.perBatchItemsByName, b.commonItemsByName);
} else {
SetBatchedItems (null, null);
}
}
void SetBatchedItems (Dictionary<string, BuildItemGroup> perBatchItemsByName, Dictionary<string, BuildItemGroup> commonItemsByName)
{
this.perBatchItemsByName = perBatchItemsByName;
this.commonItemsByName = commonItemsByName;
}
// Honors batching
internal bool TryGetEvaluatedItemByNameBatched (string itemName, out BuildItemGroup group)
{
if (perBatchItemsByName != null && perBatchItemsByName.TryGetValue (itemName, out group))
return true;
if (commonItemsByName != null && commonItemsByName.TryGetValue (itemName, out group))
return true;
group = null;
return EvaluatedItemsByName.TryGetValue (itemName, out group);
}
internal string GetMetadataBatched (string itemName, string metadataName)
{
BuildItemGroup group = null;
if (itemName == null) {
//unqualified, all items in a batch(bucket) have the
//same metadata values
group = GetFirst<BuildItemGroup> (perBatchItemsByName.Values);
if (group == null)
group = GetFirst<BuildItemGroup> (commonItemsByName.Values);
} else {
//qualified
TryGetEvaluatedItemByNameBatched (itemName, out group);
}
if (group != null) {
foreach (BuildItem item in group) {
if (item.HasMetadata (metadataName))
return item.GetEvaluatedMetadata (metadataName);
}
}
return String.Empty;
}
internal IEnumerable<BuildItemGroup> GetAllItemGroups ()
{
if (perBatchItemsByName == null && commonItemsByName == null)
foreach (BuildItemGroup group in EvaluatedItemsByName.Values)
yield return group;
if (perBatchItemsByName != null)
foreach (BuildItemGroup group in perBatchItemsByName.Values)
yield return group;
if (commonItemsByName != null)
foreach (BuildItemGroup group in commonItemsByName.Values)
yield return group;
}
T GetFirst<T> (ICollection<T> list)
{
if (list == null)
return default (T);
foreach (T t in list)
return t;
return default (T);
}
internal string ThisFileFullPath {
get { return this_file_property_stack.Peek (); }
}
// Used for MSBuild*This* set of properties
internal void PushThisFileProperty (string full_filename)
{
string last_file = this_file_property_stack.Count == 0 ? String.Empty : this_file_property_stack.Peek ();
this_file_property_stack.Push (full_filename);
if (last_file != full_filename)
// first time, or different from previous one
SetMSBuildThisFileProperties (full_filename);
}
internal void PopThisFileProperty ()
{
string last_file = this_file_property_stack.Pop ();
if (this_file_property_stack.Count > 0 && last_file != this_file_property_stack.Peek ())
SetMSBuildThisFileProperties (this_file_property_stack.Peek ());
}
void SetMSBuildThisFileProperties (string full_filename)
{
if (String.IsNullOrEmpty (full_filename))
return;
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildThisFile", Path.GetFileName (full_filename), PropertyType.Reserved));
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildThisFileFullPath", full_filename, PropertyType.Reserved));
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildThisFileName", Path.GetFileNameWithoutExtension (full_filename), PropertyType.Reserved));
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildThisFileExtension", Path.GetExtension (full_filename), PropertyType.Reserved));
string project_dir = Path.GetDirectoryName (full_filename) + Path.DirectorySeparatorChar;
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildThisFileDirectory", project_dir, PropertyType.Reserved));
evaluatedProperties.AddProperty (new BuildProperty ("MSBuildThisFileDirectoryNoRoot",
project_dir.Substring (Path.GetPathRoot (project_dir).Length),
PropertyType.Reserved));
}
internal void LogWarning (string filename, string message, params object[] messageArgs)
{
BuildWarningEventArgs bwea = new BuildWarningEventArgs (
null, null, filename, 0, 0, 0, 0, String.Format (message, messageArgs),
null, null);
ParentEngine.EventSource.FireWarningRaised (this, bwea);
}
internal void LogError (string filename, string message,
params object[] messageArgs)
{
BuildErrorEventArgs beea = new BuildErrorEventArgs (
null, null, filename, 0, 0, 0, 0, String.Format (message, messageArgs),
null, null);
ParentEngine.EventSource.FireErrorRaised (this, beea);
}
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 BuildPropertyGroup EvaluatedProperties {
get {
if (needToReevaluate) {
needToReevaluate = false;
Reevaluate ();
}
return evaluatedProperties;
}
}
internal IEnumerable EvaluatedPropertiesAsDictionaryEntries {
get {
foreach (BuildProperty bp in EvaluatedProperties)
yield return new DictionaryEntry (bp.Name, bp.Value);
}
}
public string FullFileName {
get { return fullFileName; }
set { fullFileName = value; }
}
public BuildPropertyGroup GlobalProperties {
get { return globalProperties; }
set {
if (value == null)
throw new ArgumentNullException ("value");
if (value.FromXml)
throw new InvalidOperationException ("GlobalProperties can not be set to persisted property group.");
globalProperties = value;
}
}
public bool IsDirty {
get { return isDirty; }
}
public bool IsValidated {
get { return isValidated; }
set { isValidated = value; }
}
public BuildItemGroupCollection ItemGroups {
get { return itemGroups; }
}
public ImportCollection Imports {
get { return imports; }
}
public string InitialTargets {
get {
return String.Join ("; ", initialTargets.ToArray ());
}
set {
initialTargets.Clear ();
xmlDocument.DocumentElement.SetAttribute ("InitialTargets", value);
if (value != null)
initialTargets.AddRange (value.Split (
new char [] {';', ' '}, StringSplitOptions.RemoveEmptyEntries));
}
}
public Engine ParentEngine {
get { return parentEngine; }
}
public BuildPropertyGroupCollection PropertyGroups {
get { return propertyGroups; }
}
public string SchemaFile {
get { return schemaFile; }
set { schemaFile = value; }
}
public TargetCollection Targets {
get { return targets; }
}
public DateTime TimeOfLastDirty {
get { return timeOfLastDirty; }
}
public UsingTaskCollection UsingTasks {
get { return usingTasks; }
}
[MonoTODO]
public string Xml {
get { return xmlDocument.InnerXml; }
}
// corresponds to the xml attribute
public string DefaultToolsVersion {
get {
if (xmlDocument != null)
return xmlDocument.DocumentElement.GetAttribute ("ToolsVersion");
return null;
}
set {
if (xmlDocument != null)
xmlDocument.DocumentElement.SetAttribute ("ToolsVersion", value);
}
}
public bool HasToolsVersionAttribute {
get {
return xmlDocument != null && xmlDocument.DocumentElement.HasAttribute ("ToolsVersion");
}
}
public string ToolsVersion {
get; internal set;
}
internal Dictionary <string, BuildItemGroup> LastItemGroupContaining {
get { return last_item_group_containing; }
}
internal ProjectLoadSettings ProjectLoadSettings {
get { return project_load_settings; }
set { project_load_settings = value; }
}
internal static XmlNamespaceManager XmlNamespaceManager {
get {
if (manager == null) {
manager = new XmlNamespaceManager (new NameTable ());
manager.AddNamespace ("tns", ns);
}
return manager;
}
}
internal TaskDatabase TaskDatabase {
get { return taskDatabase; }
}
internal XmlDocument XmlDocument {
get { return xmlDocument; }
}
internal static string XmlNamespace {
get { return ns; }
}
static string OS {
get {
PlatformID pid = Environment.OSVersion.Platform;
switch ((int)pid) {
case 128:
case 4:
return "Unix";
case 6:
return "OSX";
default:
return "Windows_NT";
}
}
}
}
}