[xbuild]: Support <PropertyGroup/ItemGroup> inside <Target>.
authorMartin Baulig <martin.baulig@xamarin.com>
Thu, 4 Apr 2013 17:24:26 +0000 (19:24 +0200)
committerMartin Baulig <martin.baulig@xamarin.com>
Fri, 5 Apr 2013 11:07:02 +0000 (13:07 +0200)
23 files changed:
mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/BuildItem.cs
mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/BuildItemGroup.cs
mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/BuildTask.cs
mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/BuildTaskItemGroup.cs [new file with mode: 0644]
mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/BuildTaskPropertyGroup.cs [new file with mode: 0644]
mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ConditionParser.cs
mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/IBuildTask.cs [new file with mode: 0644]
mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/Target.cs
mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/TargetBatchingImpl.cs
mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/TaskBatchingImpl.cs
mcs/class/Microsoft.Build.Engine/Microsoft.Build.Engine.dll.sources
mcs/class/Microsoft.Build.Engine/Test/Microsoft.Build.BuildEngine/BuildItemTest.cs
mcs/class/Microsoft.Build.Engine/Test/Microsoft.Build.BuildEngine/BuildPropertyGroupTest.cs
mcs/class/Microsoft.Build.Engine/Test/Microsoft.Build.BuildEngine/BuildPropertyTest.cs
mcs/class/Microsoft.Build.Engine/Test/Microsoft.Build.BuildEngine/ConsoleLoggerTest.cs
mcs/class/Microsoft.Build.Engine/Test/Microsoft.Build.BuildEngine/EngineTest.cs
mcs/class/Microsoft.Build.Engine/Test/Microsoft.Build.BuildEngine/ProjectTest.cs
mcs/class/Microsoft.Build.Engine/Test/Microsoft.Build.BuildEngine/TargetTest.cs
mcs/class/Microsoft.Build.Engine/Test/Microsoft.Build.BuildEngine/UsingTaskTest.cs
mcs/class/Microsoft.Build.Engine/Test/various/Conditions.cs
mcs/class/Microsoft.Build.Engine/Test/various/EvaluationOrder.cs
mcs/class/Microsoft.Build.Engine/Test/various/Items.cs
mcs/class/Microsoft.Build.Engine/Test/various/Properties.cs

index 3421813ce8db754f87759d7f5edb70b516957531..8d67fec080c800d076f0e2559be92896493a2f6c 100644 (file)
@@ -26,6 +26,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 using System;
+using System.Linq;
 using System.Collections;
 using System.Collections.Generic;
 using System.Collections.Specialized;
@@ -50,6 +51,9 @@ namespace Microsoft.Build.BuildEngine {
                //string                recursiveDir;
                IDictionary     evaluatedMetadata;
                IDictionary     unevaluatedMetadata;
+               bool            isDynamic;
+               bool            keepDuplicates = true;
+               string          removeMetadata, keepMetadata;
 
                BuildItem ()
                {
@@ -90,11 +94,49 @@ namespace Microsoft.Build.BuildEngine {
                        this.parent_item_group = parentItemGroup;
                        
                        this.itemElement = itemElement;
-                       
-                       if (Include == String.Empty)
-                               throw new InvalidProjectFileException (String.Format ("The required attribute \"Include\" is missing from element <{0}>.", Name));
+                       isDynamic = parentItemGroup.IsDynamic;
+
+                       if (IsDynamic) {
+                               if (!string.IsNullOrEmpty (Remove)) {
+                                       if (!string.IsNullOrEmpty (Include) || !string.IsNullOrEmpty (Exclude))
+                                               throw new InvalidProjectFileException (string.Format ("The attribute \"Remove\" in element <{0}> is unrecognized.", Name));
+                                       if (itemElement.HasChildNodes)
+                                               throw new InvalidProjectFileException ("Children are not allowed below an item remove element.");
+                               }
+                               if (string.IsNullOrEmpty (Include) && !string.IsNullOrEmpty (Exclude))
+                                       throw new InvalidProjectFileException (string.Format ("The attribute \"Exclude\" in element <{0}> is unrecognized.", Name));
+                       } else {
+                               if (string.IsNullOrEmpty (Include))
+                                       throw new InvalidProjectFileException (string.Format ("The required attribute \"Include\" is missing from element <{0}>.", Name));
+                               if (!string.IsNullOrEmpty (Remove))
+                                       throw new InvalidProjectFileException (string.Format ("The attribute \"Remove\" in element <{0}> is unrecognized.", Name));
+                       }
+
+                       foreach (XmlAttribute attr in itemElement.Attributes) {
+                               if (attr.Name == "Include" || attr.Name == "Exclude" || attr.Name == "Condition")
+                                       continue;
+                               if (!IsDynamic)
+                                       throw new InvalidProjectFileException (string.Format ("The attribute \"{0}\" in element <{1}> is unrecognized.", attr.Name, Name));
+
+                               switch (attr.Name) {
+                               case "Remove":
+                                       Remove = attr.Value;
+                                       break;
+                               case "KeepDuplicates":
+                                       KeepDuplicates = bool.Parse (attr.Value);
+                                       break;
+                               case "RemoveMetadata":
+                                       removeMetadata = attr.Value;
+                                       break;
+                               case "KeepMetadata":
+                                       keepMetadata = attr.Value;
+                                       break;
+                               default:
+                                       throw new InvalidProjectFileException (string.Format ("The attribute \"{0}\" in element <{1}> is unrecognized.", attr.Name, Name));
+                               }
+                       }
                }
-               
+
                BuildItem (BuildItem parent)
                {
                        isImported = parent.isImported;
@@ -254,21 +296,39 @@ namespace Microsoft.Build.BuildEngine {
                                this.finalItemSpec = MSBuildUtils.Unescape (Include);
                                return;
                        }
-                       
+
                        foreach (XmlNode xn in itemElement.ChildNodes) {
                                XmlElement xe = xn as XmlElement;
                                if (xe != null && ConditionParser.ParseAndEvaluate (xe.GetAttribute ("Condition"), project))
                                        AddMetadata (xe.Name, xe.InnerText);
                        }
 
+                       if (IsDynamic) {
+                               if (!evaluatedTo)
+                                       return;
+
+                               if (!string.IsNullOrEmpty (Remove)) {
+                                       RemoveItems (project);
+                                       return;
+                               }
+
+                               if (string.IsNullOrEmpty (Include)) {
+                                       UpdateMetadata (project);
+                                       return;
+                               }
+                       }
+                       
                        DirectoryScanner directoryScanner;
                        Expression includeExpr, excludeExpr;
                        ITaskItem[] includes, excludes;
 
+                       var options = IsDynamic ?
+                               ParseOptions.AllowItemsMetadataAndSplit : ParseOptions.AllowItemsNoMetadataAndSplit;
+
                        includeExpr = new Expression ();
-                       includeExpr.Parse (Include, ParseOptions.AllowItemsNoMetadataAndSplit);
+                       includeExpr.Parse (Include, options);
                        excludeExpr = new Expression ();
-                       excludeExpr.Parse (Exclude, ParseOptions.AllowItemsNoMetadataAndSplit);
+                       excludeExpr.Parse (Exclude, options);
                        
                        includes = (ITaskItem[]) includeExpr.ConvertTo (project, typeof (ITaskItem[]),
                                                                ExpressionOptions.ExpandItemRefs);
@@ -293,9 +353,123 @@ namespace Microsoft.Build.BuildEngine {
                        foreach (ITaskItem matchedItem in directoryScanner.MatchedItems)
                                AddEvaluatedItem (project, evaluatedTo, matchedItem);
                }
-               
+
+               bool CheckCondition (Project project)
+               {
+                       if (parent_item_group != null && !ConditionParser.ParseAndEvaluate (parent_item_group.Condition, project))
+                               return false;
+                       if (parent_item != null && !parent_item.CheckCondition (project))
+                               return false;
+                       return ConditionParser.ParseAndEvaluate (Condition, project);
+               }
+
+               void UpdateMetadata (Project project)
+               {
+                       BuildItemGroup group;
+                       if (!project.TryGetEvaluatedItemByNameBatched (Name, out group))
+                               return;
+
+                       foreach (BuildItem item in group) {
+                               if (!item.CheckCondition (project))
+                                       continue;
+                               
+                               foreach (string name in evaluatedMetadata.Keys) {
+                                       item.SetMetadata (name, (string)evaluatedMetadata [name]);
+                               }
+
+                               AddAndRemoveMetadata (project, item);
+                       }
+               }
+
+               void AddAndRemoveMetadata (Project project, BuildItem item)
+               {
+                       if (!string.IsNullOrEmpty (removeMetadata)) {
+                               var removeExpr = new Expression ();
+                               removeExpr.Parse (removeMetadata, ParseOptions.AllowItemsNoMetadataAndSplit);
+
+                               var removeSpec = (string[]) removeExpr.ConvertTo (
+                                       project, typeof (string[]), ExpressionOptions.ExpandItemRefs);
+
+                               foreach (var remove in removeSpec) {
+                                       item.DeleteMetadata (remove);
+                               }
+                       }
+
+                       if (!string.IsNullOrEmpty (keepMetadata)) {
+                               var keepExpr = new Expression ();
+                               keepExpr.Parse (keepMetadata, ParseOptions.AllowItemsNoMetadataAndSplit);
+
+                               var keepSpec = (string[]) keepExpr.ConvertTo (
+                                       project, typeof (string[]), ExpressionOptions.ExpandItemRefs);
+
+                               var metadataNames = new string [item.evaluatedMetadata.Count];
+                               item.evaluatedMetadata.Keys.CopyTo (metadataNames, 0);
+
+                               foreach (string name in metadataNames) {
+                                       if (!keepSpec.Contains (name))
+                                               item.DeleteMetadata (name);
+                               }
+                       }
+               }
+
+               void RemoveItems (Project project)
+               {
+                       BuildItemGroup group;
+                       if (!project.TryGetEvaluatedItemByNameBatched (Name, out group))
+                               return;
+
+                       var removeExpr = new Expression ();
+                       removeExpr.Parse (Remove, ParseOptions.AllowItemsNoMetadataAndSplit);
+
+                       var removes = (ITaskItem[]) removeExpr.ConvertTo (
+                               project, typeof (ITaskItem[]), ExpressionOptions.ExpandItemRefs);
+
+                       var directoryScanner = new DirectoryScanner ();
+                       
+                       directoryScanner.Includes = removes;
+
+                       if (project.FullFileName != String.Empty)
+                               directoryScanner.BaseDirectory = new DirectoryInfo (Path.GetDirectoryName (project.FullFileName));
+                       else
+                               directoryScanner.BaseDirectory = new DirectoryInfo (Directory.GetCurrentDirectory ());
+                       
+                       directoryScanner.Scan ();
+
+                       foreach (ITaskItem matchedItem in directoryScanner.MatchedItems) {
+                               group.RemoveItem (matchedItem);
+                       }
+               }
+
+               bool ContainsItem (Project project, ITaskItem taskItem)
+               {
+                       BuildItemGroup group;
+                       if (!project.TryGetEvaluatedItemByNameBatched (Name, out group))
+                               return false;
+
+                       var item = group.FindItem (taskItem);
+                       if (item == null)
+                               return false;
+
+                       foreach (string metadataName in evaluatedMetadata.Keys) {
+                               string metadataValue = (string)evaluatedMetadata [metadataName];
+                               if (!metadataValue.Equals (item.evaluatedMetadata [metadataName]))
+                                       return false;
+                       }
+                       
+                       foreach (string metadataName in item.evaluatedMetadata.Keys) {
+                               string metadataValue = (string)item.evaluatedMetadata [metadataName];
+                               if (!metadataValue.Equals (evaluatedMetadata [metadataName]))
+                                       return false;
+                       }
+
+                       return true;
+               }
+
                void AddEvaluatedItem (Project project, bool evaluatedTo, ITaskItem taskitem)
                {
+                       if (IsDynamic && evaluatedTo && !KeepDuplicates && ContainsItem (project, taskitem))
+                               return;
+
                        BuildItemGroup big;                     
                        BuildItem bi = new BuildItem (this);
                        bi.finalItemSpec = taskitem.ItemSpec;
@@ -328,6 +502,9 @@ namespace Microsoft.Build.BuildEngine {
                        }
 
                        big.AddItem (bi);
+
+                       if (IsDynamic)
+                               AddAndRemoveMetadata (project, bi);
                }
                
                // during item's eval phase, any item refs in this item, have either
@@ -488,6 +665,20 @@ namespace Microsoft.Build.BuildEngine {
                        }
                }
 
+               internal bool IsDynamic {
+                       get { return isDynamic; }
+               }
+
+               internal string Remove {
+                       get;
+                       private set;
+               }
+
+               internal bool KeepDuplicates {
+                       get { return keepDuplicates; }
+                       private set { keepDuplicates = value; }
+               }
+
                public bool IsImported {
                        get { return isImported; }
                }
@@ -522,6 +713,10 @@ namespace Microsoft.Build.BuildEngine {
                internal bool FromXml {
                        get { return itemElement != null; }
                }
+
+               internal XmlElement XmlElement {
+                       get { return itemElement; }
+               }
                
                internal bool HasParentItem {
                        get { return parent_item != null; }
index 444731a8cee60b70538b3055085f8b73478c782c..034ead032b841e68c1191c27504d61bfe3a51fd4 100644 (file)
@@ -26,6 +26,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 using System;
+using System.Linq;
 using System.Reflection;
 using System.Collections;
 using System.Collections.Generic;
@@ -42,7 +43,8 @@ namespace Microsoft.Build.BuildEngine {
                GroupingCollection      parentCollection;
                Project                 parentProject;
                bool                    read_only;
-               bool evaluated;
+               bool                    evaluated;
+               bool                    isDynamic;
 
                public BuildItemGroup ()
                        : this (null, null, null, false)
@@ -55,12 +57,18 @@ namespace Microsoft.Build.BuildEngine {
                }
 
                internal BuildItemGroup (XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly)
+                       : this (xmlElement, project, importedProject, readOnly, false)
+               {
+               }
+
+               internal BuildItemGroup (XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly, bool dynamic)
                {
                        this.buildItems = new List <BuildItem> ();
                        this.importedProject = importedProject;
                        this.itemGroupElement = xmlElement;
                        this.parentProject = project;
                        this.read_only = readOnly;
+                       this.isDynamic = dynamic;
                        
                        if (!FromXml)
                                return;
@@ -169,6 +177,24 @@ namespace Microsoft.Build.BuildEngine {
                        RemoveItem (item);
                }
 
+               internal BuildItem FindItem (ITaskItem taskItem)
+               {
+                       return buildItems.FirstOrDefault (i => i.FinalItemSpec == taskItem.ItemSpec);
+               }
+
+               internal void RemoveItem (ITaskItem itemToRemove)
+               {
+                       if (itemToRemove == null)
+                               return;
+
+                       var item = FindItem (itemToRemove);
+                       if (item == null)
+                               return;
+
+                       item.Detach ();
+                       buildItems.Remove (item);
+               }
+
                public BuildItem[] ToArray ()
                {
                        return buildItems.ToArray ();
@@ -239,7 +265,7 @@ namespace Microsoft.Build.BuildEngine {
 
                internal void Evaluate ()
                {
-                       if (evaluated)
+                       if (!isDynamic && evaluated)
                                return;
                        foreach (BuildItem bi in buildItems) {
                                if (bi.Condition == String.Empty)
@@ -317,5 +343,11 @@ namespace Microsoft.Build.BuildEngine {
                                return itemGroupElement;
                        }       
                }
+
+               internal bool IsDynamic {
+                       get {
+                               return isDynamic;
+                       }
+               }
        }
 }
index 97191e365d23069f6b671098565884b647afbf07..d0048815a18d690db6de37c8f4c9cb578c394355 100644 (file)
@@ -35,7 +35,7 @@ using Microsoft.Build.Framework;
 using Microsoft.Build.Utilities;
 
 namespace Microsoft.Build.BuildEngine {
-       public class BuildTask {
+       public class BuildTask : IBuildTask {
        
                ITaskHost               hostObject;
                Target                  parentTarget;
@@ -127,7 +127,7 @@ namespace Microsoft.Build.BuildEngine {
                                        continue;
                                tempNames.Add (xmlAttribute.Name);
                        }
-                       
+
                        return tempNames.ToArray ();
                }
                
@@ -156,7 +156,7 @@ namespace Microsoft.Build.BuildEngine {
                        else
                                taskElement.SetAttribute (parameterName, parameterValue);
                }
-               
+
                void LogTaskStarted ()
                {
                        TaskStartedEventArgs tsea = new TaskStartedEventArgs ("Task started.", null,
@@ -266,11 +266,29 @@ namespace Microsoft.Build.BuildEngine {
                        get { return taskElement; }
                        set { taskElement = value; }
                }
-               
+
                [MonoTODO]
                public Type Type {
                        get { return parentTarget.Project.TaskDatabase.GetTypeFromClassName (Name); }
                }
+
+               public IEnumerable<string> GetAttributes ()
+               {
+                       foreach (XmlAttribute attrib in TaskElement.Attributes)
+                               yield return attrib.Value;
                
+                       foreach (XmlNode xn in TaskElement.ChildNodes) {
+                               XmlElement xe = xn as XmlElement;
+                               if (xe == null)
+                                       continue;
+                       
+                               //FIXME: error on any other child
+                               if (String.Compare (xe.LocalName, "Output", StringComparison.Ordinal) == 0) {
+                                       foreach (XmlAttribute attrib in xe.Attributes)
+                                               yield return attrib.Value;
+                               }
+                       }
+               }
+
        }
 }
diff --git a/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/BuildTaskItemGroup.cs b/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/BuildTaskItemGroup.cs
new file mode 100644 (file)
index 0000000..9449cd8
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// BuildTaskItemGroup.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.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.Generic;
+using System.Xml;
+
+namespace Microsoft.Build.BuildEngine {
+
+       internal class BuildTaskItemGroup : BuildItemGroup, IBuildTask {
+
+               public bool ContinueOnError {
+                       get; set;
+               }
+
+               internal BuildTaskItemGroup (XmlElement element, Target target)
+                       : base (element, target.Project, null, false, true)
+               {
+               }
+               
+               public bool Execute ()
+               {
+                       Evaluate ();
+                       return true;
+               }
+
+               public IEnumerable<string> GetAttributes ()
+               {
+                       foreach (XmlAttribute attrib in XmlElement.Attributes)
+                               yield return attrib.Value;
+
+                       foreach (BuildItem item in this) {
+                               foreach (XmlAttribute attrib in item.XmlElement.Attributes)
+                                       yield return attrib.Value;
+                       }
+               }
+
+       }
+}
+
diff --git a/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/BuildTaskPropertyGroup.cs b/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/BuildTaskPropertyGroup.cs
new file mode 100644 (file)
index 0000000..4df2f78
--- /dev/null
@@ -0,0 +1,59 @@
+//
+// BuildTaskPropertyGroup.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.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.Generic;
+using System.Xml;
+
+namespace Microsoft.Build.BuildEngine {
+       
+       internal class BuildTaskPropertyGroup : BuildPropertyGroup, IBuildTask {
+               
+               public bool ContinueOnError {
+                       get; set;
+               }
+               
+               internal BuildTaskPropertyGroup (XmlElement element, Target target)
+                       : base (element, target.Project, null, false)
+               {
+               }
+               
+               public bool Execute ()
+               {
+                       Evaluate ();
+                       return true;
+               }
+
+               public IEnumerable<string> GetAttributes ()
+               {
+                       foreach (XmlAttribute attrib in XmlElement.Attributes)
+                               yield return attrib.Value;
+               }
+               
+       }
+}
+
index d7f4ac5c80b022d15c32a4ffb8b3bb4132243348..ec538abc29f3441d5927656608e29ecdb24ed11c 100644 (file)
@@ -89,6 +89,11 @@ namespace Microsoft.Build.BuildEngine {
                {
                        return ParseBooleanAnd ();
                }
+
+               public static string And (string a, string b)
+               {
+                       return a + " and " + b;
+               }
                
                ConditionExpression ParseBooleanAnd ()
                {
diff --git a/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/IBuildTask.cs b/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/IBuildTask.cs
new file mode 100644 (file)
index 0000000..aa18248
--- /dev/null
@@ -0,0 +1,44 @@
+//
+// IBuildTask.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.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.Generic;
+
+namespace Microsoft.Build.BuildEngine {
+       internal interface IBuildTask {
+               bool ContinueOnError {
+                       get; set;
+               }
+               
+               string Condition {
+                       get; set;
+               }
+               
+               bool Execute ();
+
+               IEnumerable<string> GetAttributes ();
+       }
+}
index 378348c1f4afbc96463a2a582fa1125a4820578a..430ea1daf73cf5b5b6c86a51dca8c9e1d07a03c0 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 using System;
+using System.Text;
 using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
 using System.Xml;
 using Microsoft.Build.Framework;
 using Microsoft.Build.Utilities;
+using Mono.XBuild.Utilities;
 
 namespace Microsoft.Build.BuildEngine {
        public class Target : IEnumerable {
@@ -44,7 +46,7 @@ namespace Microsoft.Build.BuildEngine {
                Project         project;
                XmlElement      targetElement;
                List <XmlElement>       onErrorElements;
-               List <BuildTask>        buildTasks;
+               List <IBuildTask>       buildTasks;
                
                internal Target (XmlElement targetElement, Project project, ImportedProject importedProject)
                {
@@ -62,7 +64,7 @@ namespace Microsoft.Build.BuildEngine {
 
                        this.onErrorElements  = new List <XmlElement> ();
                        this.buildState = BuildState.NotStarted;
-                       this.buildTasks = new List <BuildTask> ();
+                       this.buildTasks = new List <IBuildTask> ();
                        this.batchingImpl = new TargetBatchingImpl (project, this.targetElement);
 
                        bool onErrorFound = false;
@@ -77,8 +79,10 @@ namespace Microsoft.Build.BuildEngine {
                                                        "The element <OnError> must be last under element <Target>. Found element <Error> instead.");
 #if NET_3_5
                                        else if (xe.Name == "ItemGroup") {
-                                               //don't blow up for ItemGroups inside Targets in >= 3.5
-                                               // TODO: evaluate them (see https://bugzilla.xamarin.com/show_bug.cgi?id=1862 and test in TargetTest.cs )
+                                               buildTasks.Add (new BuildTaskItemGroup (xe, this));
+                                               continue;
+                                       } else if (xe.Name == "PropertyGroup") {
+                                               buildTasks.Add (new BuildTaskPropertyGroup (xe, this));
                                                continue;
                                        }
 #endif
@@ -379,7 +383,7 @@ namespace Microsoft.Build.BuildEngine {
                internal List<string> AfterThisTargets { get; set; }
 #endif
 
-               internal List<BuildTask> BuildTasks {
+               internal List<IBuildTask> BuildTasks {
                        get { return buildTasks; }
                }
 
index 28ea4c8c69ce366a569d07b964ac8cc465475331..3873a93c498f64c124ae70f214f56bada47ac940 100644 (file)
@@ -118,7 +118,7 @@ namespace Microsoft.Build.BuildEngine {
 
                                for (int i = 0; i < target.BuildTasks.Count; i ++) {
                                        //FIXME: parsing attributes repeatedly
-                                       BuildTask bt = target.BuildTasks [i];
+                                       IBuildTask bt = target.BuildTasks [i];
 
                                        TaskBatchingImpl batchingImpl = new TaskBatchingImpl (project);
                                        bool task_result = batchingImpl.Build (bt, out executeOnErrors);
index 65ed711aed56e5921ea910839ed10a90ed2434d9..80e1d5272a17ba566d5961761db208e93f7a6348 100644 (file)
@@ -40,7 +40,7 @@ namespace Microsoft.Build.BuildEngine {
                {
                }
 
-               public bool Build (BuildTask buildTask, out bool executeOnErrors)
+               public bool Build (IBuildTask buildTask, out bool executeOnErrors)
                {
                        executeOnErrors = false;
                        try {
@@ -68,7 +68,7 @@ namespace Microsoft.Build.BuildEngine {
                        }
                }
 
-               bool Run (BuildTask buildTask, out bool executeOnErrors)
+               bool Run (IBuildTask buildTask, out bool executeOnErrors)
                {
                        executeOnErrors = false;
 
@@ -108,21 +108,10 @@ namespace Microsoft.Build.BuildEngine {
                // Parse task attributes to get list of referenced metadata and items
                // to determine batching
                //
-               void ParseTaskAttributes (BuildTask buildTask)
+               void ParseTaskAttributes (IBuildTask buildTask)
                {
-                       foreach (XmlAttribute attrib in buildTask.TaskElement.Attributes)
-                               ParseAttribute (attrib.Value);
-
-                       foreach (XmlNode xn in buildTask.TaskElement.ChildNodes) {
-                               XmlElement xe = xn as XmlElement;
-                               if (xe == null)
-                                       continue;
-
-                               //FIXME: error on any other child
-                               if (String.Compare (xe.LocalName, "Output", StringComparison.Ordinal) == 0) {
-                                       foreach (XmlAttribute attrib in xe.Attributes)
-                                               ParseAttribute (attrib.Value);
-                               }
+                       foreach (var attr in buildTask.GetAttributes ()) {
+                               ParseAttribute (attr);
                        }
                }
        }
index 41ed073a7ab5384a7e7e2075cacb7ffc2906f8ba..fa51fafd89f245d24a4b15fce24a2e21fd759cdb 100644 (file)
@@ -18,6 +18,8 @@ Microsoft.Build.BuildEngine/BuildPropertyGroupCollection.cs
 Microsoft.Build.BuildEngine/BuildPropertyGroup.cs
 Microsoft.Build.BuildEngine/BuildSettings.cs
 Microsoft.Build.BuildEngine/BuildTask.cs
+Microsoft.Build.BuildEngine/BuildTaskItemGroup.cs
+Microsoft.Build.BuildEngine/BuildTaskPropertyGroup.cs
 Microsoft.Build.BuildEngine/BuildWhen.cs
 Microsoft.Build.BuildEngine/ChangeType.cs
 Microsoft.Build.BuildEngine/ColorResetter.cs
@@ -46,6 +48,7 @@ Microsoft.Build.BuildEngine/ImportCollection.cs
 Microsoft.Build.BuildEngine/ImportedProject.cs
 Microsoft.Build.BuildEngine/InternalLoggerException.cs
 Microsoft.Build.BuildEngine/InvalidProjectFileException.cs
+Microsoft.Build.BuildEngine/IBuildTask.cs
 Microsoft.Build.BuildEngine/IReference.cs
 Microsoft.Build.BuildEngine/ItemReference.cs
 Microsoft.Build.BuildEngine/LogExtensions.cs
index 36f5e52f9b098933a5e1c2271a4c2dd179069e79..e580d358ed07dd16235f4eec2c0bb939b4a91d12 100644 (file)
@@ -95,6 +95,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
 
                // Parameter "itemInclude" cannot have zero length.
                [Test]
+               [Category ("NotDotNet")]
                [ExpectedException (typeof (ArgumentException))]
                public void TestCtor6 ()
                {
index 528ea5f9a56c3526536a7530f7494c2b2d992998..73df7340741a5f03699479c82c844563c8543993 100644 (file)
@@ -220,6 +220,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestGetEnumerator1 ()
                {
                        BuildPropertyGroup bpg = new BuildPropertyGroup ();
index 03f46be4183592552e65d1949ee44ec734bc2c10..f5f0472292b2b04b41d1b650685961fdde463480 100644 (file)
@@ -349,6 +349,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestValueXml ()
                {
                        BuildPropertyGroup [] bpgs = new BuildPropertyGroup [1];
index 258e4bb962d66822d93b175848171326ce8466a1..aa0e69d8158182e77b24e2bfd56a4f3a87a70baa 100755 (executable)
@@ -35,6 +35,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
        [TestFixture]
        public class ConsoleLoggerTest {
                [Test]
+               [Category ("NotDotNet")]
                public void TestAssignment ()
                {
                        ConsoleLogger cl = new ConsoleLogger ();
index d46108b8464cef109968d2f2f1c07117ba40c444..0a9edff4e5dd3255ed6492e95709d28cd0294081 100755 (executable)
@@ -275,6 +275,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                [ExpectedException (typeof (ArgumentException))]
                public void TestBuildProject1 ()
                {
@@ -305,6 +306,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                [ExpectedException (typeof (ArgumentException))]
                public void TestBuildProjectNull1 ()
                {
@@ -313,6 +315,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                [ExpectedException (typeof (ArgumentException))]
                public void TestBuildProjectNull2 ()
                {
index 0d07f2c2e042c96fd1f4da85d0a121d9d98fb2fc..8a78fad3c8e95cf32e2c44321cf773d0396bcaa1 100644 (file)
@@ -1301,6 +1301,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestBatchedMetadataRef1 ()
                {
                        //test for multiple items with same metadata also
@@ -1341,6 +1342,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestBatchedMetadataRef2 ()
                {
                        string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
@@ -1394,6 +1396,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestBatchedMetadataRef3 ()
                {
                        string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
@@ -1429,6 +1432,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestBatchedMetadataRef4 ()
                {
                        string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
@@ -1457,6 +1461,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestBatchedMetadataRef5 ()
                {
                        string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
@@ -1492,6 +1497,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestBatchedMetadataRefInOutput () {
                        string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
                        <UsingTask TaskName=""BatchingTestTask"" AssemblyFile=""Test/resources/TestTasks.dll"" />
@@ -1831,6 +1837,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestMSBuildThisProperties ()
                {
                        Engine engine = new Engine (Consts.BinPath);
@@ -2005,6 +2012,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestRequiredTask_TaskItemArray1 ()
                {
                        Project p = CheckProjectForRequiredTests ("RequiredTestTask_TaskItems", "@(NonExistant)",
@@ -2016,6 +2024,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestRequiredTask_TaskItemArray2 ()
                {
                        Project p = CheckProjectForRequiredTests ("RequiredTestTask_TaskItems", "$(NonExistant)",
@@ -2027,6 +2036,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestRequiredTask_TaskItemArray3 ()
                {
                        Project p = CheckProjectForRequiredTests ("RequiredTestTask_IntArray", "$(NonExistant)",
@@ -2038,6 +2048,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestRequiredTask_TaskItemArray4 () {
                        Project p = CheckProjectForRequiredTests ("RequiredTestTask_IntArray", "%(NonExistant.Md)",
                                true, "Build failed", "count: 0");
@@ -2048,6 +2059,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestRequiredTask_TaskItemArray5 () {
                        // with extra space in prop value
                        Project p = CheckProjectForRequiredTests ("RequiredTestTask_IntArray", "  %(NonExistant.Md)",
index 9a40fd342a8f714d53625c640953318592a6b12e..03edf3db2b09f01b3164203c8a92626c59c7e731 100644 (file)
 // 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 Microsoft.Build.BuildEngine;
 using Microsoft.Build.Framework;
 using Microsoft.Build.Utilities;
+using MonoTests.Microsoft.Build.Tasks;
 using NUnit.Framework;
 using System.IO;
+using System.Xml;
 
 namespace MonoTests.Microsoft.Build.BuildEngine {
        [TestFixture]
@@ -349,38 +350,87 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
 #if NET_3_5
-               [Test]
-               public void BuildProjectWithItemGroupInsideTarget()
+               bool Build (string projectXml, ILogger logger)
                {
-                       ItemGroupInsideATarget ();
+                       if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
+                               var reader = new StringReader (projectXml);
+                               var xml = XmlReader.Create (reader);
+                               return BuildOnWindows (xml, logger);
+                       } else {
+                               return BuildOnLinux (projectXml, logger);
+                       }
                }
 
-               private MonoTests.Microsoft.Build.Tasks.TestMessageLogger ItemGroupInsideATarget() {
-                       var engine = new Engine(Consts.BinPath);
-                       var project = engine.CreateNewProject();
-                       var projectXml = GetProjectXmlWithItemGroupInsideATarget ();
-                       project.LoadXml(projectXml);
+               bool BuildOnWindows (XmlReader reader, ILogger logger)
+               {
+                       var type = Type.GetType ("Microsoft.Build.Evaluation.ProjectCollection, Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
+
+                       var prop = type.GetProperty ("GlobalProjectCollection");
+                       var coll = prop.GetValue (null);
+                               
+                       var loadProject = coll.GetType ().GetMethod (
+                                       "LoadProject", new Type[] { typeof (XmlReader), typeof (string) });
+                       var proj = loadProject.Invoke (coll, new object[] { reader, "4.0" });
+                               
+                       var build = proj.GetType ().GetMethod ("Build", new Type[] { typeof (string), typeof (ILogger[]) });
+                       var ret = (bool)build.Invoke (proj, new object[] { "Main", new ILogger[] { logger }});
+                       return ret;
+               }
 
-                       MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
-                               new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
+               bool BuildOnLinux (string projectXml, ILogger logger)
+               {
+                       var engine = new Engine (Consts.BinPath);
+                       var project = engine.CreateNewProject ();
+                       project.LoadXml (projectXml);
+                       
                        engine.RegisterLogger (logger);
+                       
+                       return project.Build ("Main");
+               }
 
-                       bool result = project.Build("Main");
-                       if (!result)
-                       {
+               TestMessageLogger CreateLogger (string projectXml)
+               {
+                       var logger = new TestMessageLogger ();
+                       var result = Build (projectXml, logger);
+
+                       if (!result) {
                                logger.DumpMessages ();
-                               Assert.Fail("Build failed");
+                               Assert.Fail ("Build failed");
                        }
 
                        return logger;
                }
 
-               private string GetProjectXmlWithItemGroupInsideATarget ()
+               void ItemGroupInsideTarget (string xml, params string[] messages)
+               {
+                       var logger = CreateLogger (xml);
+                       
+                       try
+                       {
+                               Assert.AreEqual(messages.Length, logger.NormalMessageCount, "Expected number of messages");
+                               for (int i = 0; i < messages.Length; i++)
+                                       logger.CheckLoggedMessageHead (messages [i], i.ToString ());
+                               Assert.AreEqual(0, logger.NormalMessageCount, "Extra messages found");
+                               
+                               Assert.AreEqual(1, logger.TargetStarted, "TargetStarted count");
+                               Assert.AreEqual(1, logger.TargetFinished, "TargetFinished count");
+                               Assert.AreEqual(messages.Length, logger.TaskStarted, "TaskStarted count");
+                               Assert.AreEqual(messages.Length, logger.TaskFinished, "TaskFinished count");
+                       }
+                       catch (AssertionException)
+                       {
+                               logger.DumpMessages();
+                               throw;
+                       }
+               }
+
+               [Test]
+               public void BuildProjectWithItemGroupInsideTarget ()
                {
-                       return
+                       ItemGroupInsideTarget (
                                @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
                                        <ItemGroup>
-                                               <fruit Include=""apple""/>
+                                       <fruit Include=""apple""/>
                                                <fruit Include=""apricot""/>
                                        </ItemGroup>
 
@@ -390,35 +440,258 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                                                </ItemGroup>
                                                <Message Text=""%(fruit.Identity)""/>
                                        </Target>
-                               </Project>";
+                               </Project>", "apple", "apricot", "raspberry");
                }
+               
+               [Test]
+               public void BuildProjectWithItemGroupInsideTarget2 ()
+               {
+                       ItemGroupInsideTarget (
+                               @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" ToolsVersion=""4.0"">
+                                       <ItemGroup>
+                                               <A Include='1'>
+                                                       <Sub>Foo</Sub>
+                                               </A>
+                                       </ItemGroup>
+                                       <PropertyGroup>
+                                               <Foo>Bar</Foo>
+                                       </PropertyGroup>
 
+                                       <Target Name='Main'>
+                                               <ItemGroup>
+                                                       <A Include='2'>
+                                                               <Sub>$(Foo);Hello</Sub>
+                                                       </A>
+                                               </ItemGroup>
+                               
+                                               <Message Text='@(A)' />
+                                               <Message Text='%(A.Sub)' />
+                                       </Target>
+                               </Project>", "1;2", "Foo", "Bar;Hello");
+               }
+               
                [Test]
-               [Category ("NotWorking")] //https://bugzilla.xamarin.com/show_bug.cgi?id=1862
-               public void BuildProjectOutputWithItemGroupInsideTarget()
+               public void BuildProjectWithPropertyGroupInsideTarget ()
                {
-                       var logger = ItemGroupInsideATarget ();
+                       ItemGroupInsideTarget (
+                               @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+                                       <PropertyGroup>
+                                               <A>Foo</A>
+                                               <B>Bar</B>
+                                       </PropertyGroup>
 
-                       try
-                       {
-                               Assert.AreEqual(3, logger.NormalMessageCount, "Expected number of messages");
-                               logger.CheckLoggedMessageHead("apple", "A1");
-                               logger.CheckLoggedMessageHead("apricot", "A2");
-                               logger.CheckLoggedMessageHead("raspberry", "A3");
-                               Assert.AreEqual(0, logger.NormalMessageCount, "Extra messages found");
+                                       <Target Name=""Main"">
+                                               <Message Text='$(A)' />
+                                               <PropertyGroup>
+                                                       <A>$(B)</A>
+                                               </PropertyGroup>
+                                               <Message Text='$(A)' />
+                                       </Target>
+                               </Project>", "Foo", "Bar");
+               }
 
-                               Assert.AreEqual(1, logger.TargetStarted, "TargetStarted count");
-                               Assert.AreEqual(1, logger.TargetFinished, "TargetFinished count");
-                               Assert.AreEqual(3, logger.TaskStarted, "TaskStarted count");
-                               Assert.AreEqual(3, logger.TaskFinished, "TaskFinished count");
+               [Test]
+               public void BuildProjectWithPropertyGroupInsideTarget2 ()
+               {
+                       ItemGroupInsideTarget (
+                               @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+                                       <PropertyGroup>
+                                               <A>Foo</A>
+                                               <B>Bar</B>
+                                       </PropertyGroup>
 
-                       }
-                       catch (AssertionException)
-                       {
-                               logger.DumpMessages();
-                               throw;
-                       }
+                                       <Target Name=""Main"">
+                                               <Message Text='$(A)' />
+                                               <PropertyGroup Condition='true'>
+                                                       <B Condition='false'>False</B>
+                                               </PropertyGroup>
+                                               <PropertyGroup Condition='true'>
+                                                       <A>$(B)</A>
+                                               </PropertyGroup>
+                                               <Message Text='$(A)' />
+                                               <Message Text='$(B)' />
+                                               <PropertyGroup>
+                                                       <A Condition='$(A) == $(B)'>Equal</A>
+                                               </PropertyGroup>
+                                               <Message Text='$(A)' />
+                                       </Target>
+                               </Project>", "Foo", "Bar", "Bar", "Equal");
                }
+
+               [Test]
+               public void ItemGroupInsideTarget_ModifyMetadata ()
+               {
+                       ItemGroupInsideTarget (
+                               @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+                                       <ItemGroup>
+                                               <Server Include='Server1'>
+                                                       <AdminContact>Mono</AdminContact>
+                                               </Server>
+                                               <Server Include='Server2'>
+                                                       <AdminContact>Mono</AdminContact>
+                                               </Server>
+                                               <Server Include='Server3'>
+                                                       <AdminContact>Root</AdminContact>
+                                               </Server>
+                                       </ItemGroup>
+
+                                       <Target Name='Main'>
+                                               <ItemGroup>
+                                                       <Server Condition=""'%(Server.AdminContact)' == 'Mono'"">
+                                                               <AdminContact>Monkey</AdminContact>
+                                                       </Server>
+                                               </ItemGroup>
+                                       
+                                               <Message Text='%(Server.Identity) : %(Server.AdminContact)' />
+                                               </Target>
+                                       </Project>", "Server1 : Monkey", "Server2 : Monkey", "Server3 : Root");
+               }
+
+               [Test]
+               public void ItemGroupInsideTarget_RemoveItem ()
+               {
+                       ItemGroupInsideTarget (
+                               @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+                                       <ItemGroup>
+                                               <Foo Include='A;B;C;D' />
+                                       </ItemGroup>
+
+                                       <Target Name='Main'>
+                                               <ItemGroup>
+                                                       <Foo Remove='B' />
+                                               </ItemGroup>
+
+                                               <Message Text='@(Foo)' />
+                                       </Target>
+                               </Project>", "A;C;D");
+               }
+
+               [Test]
+               public void ItemGroupInsideTarget_DontKeepDuplicates ()
+               {
+                       ItemGroupInsideTarget (
+                               @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+                                       <ItemGroup>
+                                               <Foo Include='A;B' />
+                                               <Foo Include='C'>
+                                                       <Hello>World</Hello>
+                                               </Foo>
+                                               <Foo Include='D'>
+                                                       <Hello>Boston</Hello>
+                                               </Foo>
+                                       </ItemGroup>
+
+                                       <Target Name='Main'>
+                                               <ItemGroup>
+                                                       <Foo Include='B;C;D' KeepDuplicates='false'>
+                                                               <Hello>Boston</Hello>
+                                                       </Foo>
+                                               </ItemGroup>
+                               
+                                               <Message Text='@(Foo)' />
+                                       </Target>
+                               </Project>", "A;B;C;D;B;C");
+               }
+
+               [Test]
+               public void ItemGroupInsideTarget_RemoveMetadata ()
+               {
+                       ItemGroupInsideTarget (
+                               @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+                                       <ItemGroup>
+                                               <Foo Include='A' />
+                                               <Foo Include='B'>
+                                                       <Hello>World</Hello>
+                                               </Foo>
+                                               <Foo Include='C'>
+                                                       <Hello>Boston</Hello>
+                                               </Foo>
+                                               <Foo Include='D'>
+                                                       <Test>Monkey</Test>
+                                               </Foo>
+                                       </ItemGroup>
+                                       <PropertyGroup>
+                                               <Foo>Hello</Foo>
+                                       </PropertyGroup>
+
+                                       <Target Name='Main'>
+                                               <ItemGroup>
+                                                       <Bar Include='@(Foo)' RemoveMetadata='$(Foo)' />
+                                                       <Bar Include='E'>
+                                                               <Hello>Monkey</Hello>
+                                                       </Bar>
+                                               </ItemGroup>
+                               
+                                               <Message Text='%(Bar.Identity)' Condition=""'%(Bar.Hello)' != ''""/>
+                                       </Target>
+                               </Project>", "E");
+               }
+
+               [Test]
+               public void ItemGroupInsideTarget_RemoveMetadata2 ()
+               {
+                       ItemGroupInsideTarget (
+                               @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+                                       <ItemGroup>
+                                               <Foo Include='A' />
+                                               <Foo Include='B'>
+                                                       <Hello>World</Hello>
+                                               </Foo>
+                                               <Foo Include='C'>
+                                                       <Hello>Boston</Hello>
+                                               </Foo>
+                                               <Foo Include='D'>
+                                                       <Test>Monkey</Test>
+                                               </Foo>
+                                       </ItemGroup>
+                                       <PropertyGroup>
+                                       <Foo>Hello</Foo>
+                                       </PropertyGroup>
+
+                                       <Target Name='Main'>
+                                               <ItemGroup>
+                                                       <Foo RemoveMetadata='$(Foo)' />
+                                                       <Foo Include='E'>
+                                                               <Hello>Monkey</Hello>
+                                                       </Foo>
+                                               </ItemGroup>
+                               
+                                       <Message Text='%(Foo.Identity)' Condition=""'%(Foo.Hello)' != ''""/>
+                                       </Target>
+                               </Project>", "E");
+               }
+
+               [Test]
+               public void ItemGroupInsideTarget_KeepMetadata ()
+               {
+                       ItemGroupInsideTarget (
+                               @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+                                       <ItemGroup>
+                                               <Foo Include='A' />
+                                               <Foo Include='B'>
+                                                       <Hello>World</Hello>
+                                               </Foo>
+                                               <Foo Include='C'>
+                                                       <Hello>Boston</Hello>
+                                               </Foo>
+                                               <Foo Include='D'>
+                                                       <Test>Monkey</Test>
+                                               </Foo>
+                                       </ItemGroup>
+
+                                       <Target Name='Main'>
+                                               <ItemGroup>
+                                                       <Foo KeepMetadata='Test' />
+                                                       <Foo Include='E'>
+                                                               <Hello>Monkey</Hello>
+                                                       </Foo>
+                                               </ItemGroup>
+                               
+                                               <Message Text='%(Foo.Identity)' Condition=""'%(Foo.Test)' != ''""/>
+                                       </Target>
+                               </Project>", "D");
+               }
+
 #endif
 
                [Test]
@@ -542,6 +815,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
 
 #if NET_4_0
                [Test]
+               [Category ("NotDotNet")]
                public void TestBeforeAndAfterTargets ()
                {
                        Engine engine;
index 4c62d4145cb2796178e9d51f81970a77615533b4..82d5e3009103d442f8f9e8560ee58e2e26226699 100644 (file)
@@ -202,6 +202,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestDuplicate1 ()
                {
                        string documentString = @"
@@ -294,6 +295,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestLazyLoad2 ()
                {
                        string documentString = @"
index d3954a2f322d73ac4320d87f96045efaae9b9ed3..51c3da6cfbf3ff0f779d3b5d4facac81819f1574 100644 (file)
@@ -284,6 +284,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestCondition10 ()
                {
                        Engine engine = new Engine (Consts.BinPath);
index 66968658e8a8e6083cf64c055c6a5ed7c8c2a7c3..77b45eb5bc059022f7cb782e886c1b5d34b0de7a 100644 (file)
@@ -233,6 +233,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestImportOrder1 ()
                {
                        Engine engine = new Engine (Consts.BinPath);
@@ -255,6 +256,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                [ExpectedException (typeof (InvalidProjectFileException))]
                public void TestImportOrder2 ()
                {
@@ -326,6 +328,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestImportOrder5 ()
                {
                        Engine engine = new Engine (Consts.BinPath);
@@ -348,6 +351,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestImportOrder6 ()
                {
                        Engine engine = new Engine (Consts.BinPath);
@@ -370,6 +374,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestImportOrder7 ()
                {
                        Engine engine = new Engine (Consts.BinPath);
index 5f6863be0757e2722555f6cf67a739341239c03c..ee93c4b932d47924a461760dc727b8081bdc2c26 100755 (executable)
@@ -718,6 +718,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestEmptyItemsWithBatching ()
                {
                        string project_xml = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
@@ -799,6 +800,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestItemsInTarget1 ()
                {
                        Engine engine = new Engine (Consts.BinPath);
@@ -891,6 +893,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestItemsInTarget3 ()
                {
                        Engine engine = new Engine (Consts.BinPath);
@@ -934,6 +937,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                //Test with ITaskItem[]
                public void TestItemsInTarget3a ()
                {
@@ -982,6 +986,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                //Test with string[]
                public void TestItemsInTarget3b ()
                {
@@ -1024,6 +1029,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                //Test with string
                public void TestItemsInTarget3c ()
                {
@@ -1131,6 +1137,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestSingleTaskItem1 ()
                {
                        Project proj = BuildProjectForSingleTaskItem ("$(D)$(C)");
@@ -1138,6 +1145,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestSingleTaskItem2 ()
                {
                        Project proj = BuildProjectForSingleTaskItem ("@(Item1)");
@@ -1145,6 +1153,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestSingleTaskItem3 ()
                {
                        Project proj = BuildProjectForSingleTaskItem ("$(A).foo");
@@ -1152,6 +1161,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestSingleTaskItem4 ()
                {
                        Project proj = BuildProjectForSingleTaskItem ("$(C)");
index f5c6bdf307f0439d6f1fa12606f34b267167bfff..70b14ecf9a86862aa63461cfc89906bb5cca2832 100644 (file)
@@ -55,6 +55,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                }
 
                [Test]
+               [Category ("NotDotNet")]
                public void TestProperties2 ()
                {
                        Engine engine = new Engine (Consts.BinPath);